summaryrefslogtreecommitdiff
path: root/cesar/lib
diff options
context:
space:
mode:
Diffstat (limited to 'cesar/lib')
-rw-r--r--cesar/lib/Config9
-rw-r--r--cesar/lib/Module14
-rw-r--r--cesar/lib/aatree.h117
-rw-r--r--cesar/lib/atox.h61
-rw-r--r--cesar/lib/bitstream.h202
-rw-r--r--cesar/lib/blk.h218
-rw-r--r--cesar/lib/circular_buffer.h75
-rw-r--r--cesar/lib/crc.h117
-rw-r--r--cesar/lib/dbg.h327
-rw-r--r--cesar/lib/defs.h41
-rw-r--r--cesar/lib/heap.h124
-rw-r--r--cesar/lib/heapsort.h125
-rw-r--r--cesar/lib/leftheap.h81
-rw-r--r--cesar/lib/list.h191
-rw-r--r--cesar/lib/preproc.h307
-rw-r--r--cesar/lib/python/Module7
-rw-r--r--cesar/lib/python/test/pyhello/Makefile8
-rw-r--r--cesar/lib/python/test/pyhello/py/test_hello.py16
-rw-r--r--cesar/lib/python/test/pyhello/src/hello.cpp41
-rw-r--r--cesar/lib/read_word.h126
-rw-r--r--cesar/lib/restrack.h137
-rw-r--r--cesar/lib/rnd.h56
-rw-r--r--cesar/lib/set.h48
-rw-r--r--cesar/lib/skewheap.h78
-rw-r--r--cesar/lib/src/aatree.c312
-rw-r--r--cesar/lib/src/atox.c383
-rw-r--r--cesar/lib/src/bitstream.c394
-rw-r--r--cesar/lib/src/blk.c244
-rw-r--r--cesar/lib/src/circular_buffer.c101
-rw-r--r--cesar/lib/src/crc.c193
-rw-r--r--cesar/lib/src/dbg.c71
-rw-r--r--cesar/lib/src/heap.c62
-rw-r--r--cesar/lib/src/leftheap.c159
-rw-r--r--cesar/lib/src/list.c181
-rw-r--r--cesar/lib/src/mt19937ar.c260
-rw-r--r--cesar/lib/src/read_word.c129
-rw-r--r--cesar/lib/src/restrack.c353
-rw-r--r--cesar/lib/src/skewheap.c138
-rw-r--r--cesar/lib/src/swap.c31
-rw-r--r--cesar/lib/src/test.c138
-rw-r--r--cesar/lib/src/trace.c655
-rw-r--r--cesar/lib/src/try.c17
-rw-r--r--cesar/lib/swap.h38
-rw-r--r--cesar/lib/test.h228
-rw-r--r--cesar/lib/test/atox/Makefile7
-rw-r--r--cesar/lib/test/atox/src/test_atox.c117
-rw-r--r--cesar/lib/test/bitstream/Config1
-rw-r--r--cesar/lib/test/bitstream/Makefile7
-rw-r--r--cesar/lib/test/bitstream/src/test_bit.c222
-rw-r--r--cesar/lib/test/blk/Makefile7
-rw-r--r--cesar/lib/test/blk/src/test_blk.c125
-rw-r--r--cesar/lib/test/circular_buffer/Makefile7
-rw-r--r--cesar/lib/test/circular_buffer/src/test_circular.c94
-rw-r--r--cesar/lib/test/crc/Makefile7
-rw-r--r--cesar/lib/test/crc/inc/crcmodel.h160
-rw-r--r--cesar/lib/test/crc/src/crcmodel.c148
-rw-r--r--cesar/lib/test/crc/src/test_crc.c294
-rw-r--r--cesar/lib/test/heap/Makefile7
-rw-r--r--cesar/lib/test/heap/src/test_heap.c272
-rw-r--r--cesar/lib/test/list/Makefile7
-rw-r--r--cesar/lib/test/list/src/test_list.c267
-rw-r--r--cesar/lib/test/read_word/Makefile7
-rw-r--r--cesar/lib/test/read_word/src/read_word.c151
-rw-r--r--cesar/lib/test/restrack/Config2
-rw-r--r--cesar/lib/test/restrack/Makefile7
-rw-r--r--cesar/lib/test/restrack/src/test_restrack.c104
-rw-r--r--cesar/lib/test/rnd/Makefile19
-rw-r--r--cesar/lib/test/rnd/mt19937ar.out213
-rw-r--r--cesar/lib/test/rnd/src/test_rnd.c164
-rw-r--r--cesar/lib/test/set/Makefile8
-rw-r--r--cesar/lib/test/set/src/test_set.c362
-rw-r--r--cesar/lib/test/test/Config1
-rw-r--r--cesar/lib/test/test/Makefile8
-rw-r--r--cesar/lib/test/test/src/test_test.c90
-rw-r--r--cesar/lib/test/trace/Config2
-rw-r--r--cesar/lib/test/trace/Makefile7
-rw-r--r--cesar/lib/test/trace/src/test_trace.c302
-rw-r--r--cesar/lib/test/try/Makefile8
-rw-r--r--cesar/lib/test/try/src/test_try.c125
-rw-r--r--cesar/lib/test/utils/Makefile7
-rw-r--r--cesar/lib/test/utils/src/test_utils.c65
-rw-r--r--cesar/lib/trace.h403
-rw-r--r--cesar/lib/try.h120
-rw-r--r--cesar/lib/types.h59
-rw-r--r--cesar/lib/utils.h258
-rw-r--r--cesar/lib/visual_state_api/Module2
-rw-r--r--cesar/lib/visual_state_api/src/SEMExpl.c27
-rw-r--r--cesar/lib/visual_state_api/src/SEMExplA.c28
-rw-r--r--cesar/lib/visual_state_api/src/SEMForce.c27
-rw-r--r--cesar/lib/visual_state_api/src/SEMInq.c45
-rw-r--r--cesar/lib/visual_state_api/src/SEMInst.c33
-rw-r--r--cesar/lib/visual_state_api/src/SEMLibE.h1882
-rw-r--r--cesar/lib/visual_state_api/src/SEMMach.c27
-rw-r--r--cesar/lib/visual_state_api/src/SEMMain.c154
-rw-r--r--cesar/lib/visual_state_api/src/SEMName.c27
-rw-r--r--cesar/lib/visual_state_api/src/SEMNameA.c28
-rw-r--r--cesar/lib/visual_state_api/src/SEMStAll.c28
-rw-r--r--cesar/lib/visual_state_api/src/SEMState.c27
-rw-r--r--cesar/lib/visual_state_api/src/SMPExpl.c92
-rw-r--r--cesar/lib/visual_state_api/src/SMPExplA.c68
-rw-r--r--cesar/lib/visual_state_api/src/SMPForce.c32
-rw-r--r--cesar/lib/visual_state_api/src/SMPInq.c238
-rw-r--r--cesar/lib/visual_state_api/src/SMPInst.c78
-rw-r--r--cesar/lib/visual_state_api/src/SMPMach.c32
-rw-r--r--cesar/lib/visual_state_api/src/SMPMain.c939
-rw-r--r--cesar/lib/visual_state_api/src/SMPName.c92
-rw-r--r--cesar/lib/visual_state_api/src/SMPNameA.c67
-rw-r--r--cesar/lib/visual_state_api/src/SMPStAll.c36
-rw-r--r--cesar/lib/visual_state_api/src/SMPState.c32
109 files changed, 14895 insertions, 0 deletions
diff --git a/cesar/lib/Config b/cesar/lib/Config
new file mode 100644
index 0000000000..f83aa90d75
--- /dev/null
+++ b/cesar/lib/Config
@@ -0,0 +1,9 @@
+CONFIG_DEBUG = y
+CONFIG_DEBUG_MORE = n
+CONFIG_DEBUG_FATAL_CATCH = n
+CONFIG_HEAP_SKEW = y
+CONFIG_HEAP_LEFTIST = n
+CONFIG_RND_BUFFER_OPTIMISE = n
+CONFIG_TRACE = n
+CONFIG_RESTRACK = n
+CONFIG_RESTRACK_KEEP = n
diff --git a/cesar/lib/Module b/cesar/lib/Module
new file mode 100644
index 0000000000..99c6f1b8f6
--- /dev/null
+++ b/cesar/lib/Module
@@ -0,0 +1,14 @@
+SOURCES := mt19937ar.c crc.c dbg.c heap.c test.c blk.c list.c aatree.c try.c \
+ swap.c read_word.c bitstream.c circular_buffer.c atox.c
+ifeq ($(CONFIG_HEAP_SKEW),y)
+SOURCES += skewheap.c
+endif
+ifeq ($(CONFIG_HEAP_LEFTIST),y)
+SOURCES += leftheap.c
+endif
+ifeq ($(CONFIG_RESTRACK),y)
+SOURCES += restrack.c
+endif
+ifeq ($(CONFIG_TRACE),y)
+SOURCES += trace.c
+endif
diff --git a/cesar/lib/aatree.h b/cesar/lib/aatree.h
new file mode 100644
index 0000000000..0acab1d155
--- /dev/null
+++ b/cesar/lib/aatree.h
@@ -0,0 +1,117 @@
+#ifndef lib_aatree_h
+#define lib_aatree_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/aatree.h
+ * \brief Arne Andersson Trees.
+ * \ingroup lib
+ */
+
+/* Set node. */
+struct set_node_t
+{
+ /** Pointer to parent node. */
+ set_node_t *father;
+ /** Pointer to left and right children. */
+ set_node_t *left, *right;
+ /** Node level. */
+ uint level;
+};
+/* Forward declaration in lib/set.h. */
+
+BEGIN_DECLS
+
+/**
+ * Initialise a set.
+ * \param set the set
+ * \param less the "is lesser than" comparison function
+ */
+void
+set_init (set_t *set, set_node_less_t less);
+
+/**
+ * Initialise a set node.
+ * \param node the node to initialise
+ */
+void
+set_node_init (set_node_t *node);
+
+/**
+ * Find a node inside a set.
+ * \param set the set to look into
+ * \param node node to compare with nodes inside the set
+ * \return the found node or NULL if none found
+ *
+ * The \a node parameter just have to contains enough data to be used with the
+ * comparison function.
+ */
+set_node_t *
+set_find (set_t *set, set_node_t *node);
+
+/**
+ * Insert a node.
+ * \param set the set
+ * \param node node to insert
+ * \return true if successful (not in the set yet)
+ */
+bool
+set_insert (set_t *set, set_node_t *node);
+
+/**
+ * Remove a node from the set.
+ * \param set the set
+ * \param node the node to remove
+ *
+ * The node must be inside the set.
+ */
+void
+set_remove (set_t *set, set_node_t *node);
+
+/**
+ * Return the first node.
+ * \param set the set
+ * \return the minimum node
+ */
+set_node_t *
+set_begin (set_t *set);
+
+/**
+ * Return the node after the last one.
+ * \param set the set
+ * \return past the last node
+ */
+extern inline set_node_t *
+set_end (set_t *set)
+{
+ return NULL;
+}
+
+/**
+ * Return the next node.
+ * \param set the set
+ * \param node current node
+ * \return the following node
+ */
+set_node_t *
+set_next (set_t *set, set_node_t *node);
+
+/**
+ * Return whether the set is empty.
+ * \param set the set
+ * \return true if empty
+ */
+extern inline bool
+set_empty (set_t *set)
+{
+ return set->root->level == 0;
+}
+
+END_DECLS
+
+#endif /* lib_aatree_h */
diff --git a/cesar/lib/atox.h b/cesar/lib/atox.h
new file mode 100644
index 0000000000..28a5da879d
--- /dev/null
+++ b/cesar/lib/atox.h
@@ -0,0 +1,61 @@
+#ifndef atox_h
+#define atox_h
+/**{{{
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ }}}*/
+/**
+ * \file lib/atox.h
+ * \brief ASCII string convertions
+ * \ingroup lib
+ */
+
+/**
+ * Convert an ASCII string into a integer.
+ * \param nptr the string pointer
+ * \return the integer
+ */
+int atoi(const char *nptr);
+
+/**
+ * Convert an ASCII string into a long.
+ * \param nptr the string pointer
+ * \return the long
+ */
+long atol(const char *nptr);
+
+/**
+ * Convert an ASCII string into a long long.
+ * \param nptr the string pointer
+ * \return the long long
+ */
+long long atoll(const char *nptr);
+
+/**
+ * Convert an ASCII string into a unsigned long.
+ * \param nptr the string pointer
+ * \return the long
+ */
+unsigned long atoul(const char *nptr);
+
+/**
+ * Convert an ASCII string into a unsigned long long.
+ * \param nptr the string pointer
+ * \return the long long
+ */
+unsigned long long atoull(const char *nptr);
+
+#endif /* atox_h */
diff --git a/cesar/lib/bitstream.h b/cesar/lib/bitstream.h
new file mode 100644
index 0000000000..63c015b8db
--- /dev/null
+++ b/cesar/lib/bitstream.h
@@ -0,0 +1,202 @@
+#ifndef bitstream_h
+#define bitstream_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file bitstream.h
+ * \brief Bit stream access using word access.
+ * \ingroup lib
+ *
+ * This library provides sequential bit stream access functions using word
+ * access, providing bus optimised endian and boundary safe access.
+ */
+
+#define bitsizeof(x) (8*sizeof(x))
+
+typedef enum
+{
+ BITSTREAM_READ,
+ BITSTREAM_WRITE
+} bitstream_type_t;
+
+/** Bit stream sequential read context. */
+typedef struct bitstream
+{
+ /** Beginning address of data structure. */
+ u8 *start;
+ /** Bit stream pointer, read as words. */
+ u32 *stream;
+ /** Number of valid bytes in the stream. */
+ uint nb_bytes;
+ /** Bit offset of current read or write word. */
+ uint bit_offset;
+ /** Input buffer, valid bits are in LSB. */
+ u32 buf;
+ /** Bitstream type of access (Read or Write). */
+ bitstream_type_t type;
+} bitstream_t;
+
+/**
+ * Initialise a bit stream.
+ * \param ctx bit stream context
+ * \param data stream data pointer
+ * \param nb_bytes number of valid bytes in the stream
+ *
+ * Memory pointer doesn't have to be word aligned.
+ */
+void
+bitstream_init (bitstream_t *ctx, void *data, uint nb_bytes,
+ bitstream_type_t type);
+
+/**
+ * Write remaining bits.
+ * \param ctx bit stream context
+ * \return number of written bits if access is write, else 0
+ */
+uint
+bitstream_finalise (bitstream_t *ctx);
+
+uint bitstream_access_unknown_size (void);
+
+/**
+ * Read or write bits from the bit stream.
+ * \param ctx bit stream context
+ * \param value
+ * \param nb_bit number of bits to read (1-64)
+ * \return number of bits read/written
+ *
+ * Access type (read or write) depends on context initialization.
+ */
+#define bitstream_access(ctx, value, nb_bit) \
+ (sizeof(*(value)) == 1 ? bitstream_access_8 ((ctx), (value), (nb_bit)) \
+ : (sizeof(*(value)) == 2 ? bitstream_access_16 ((ctx), (value), (nb_bit)) \
+ : (sizeof(*(value)) == 4 ? bitstream_access_32 ((ctx), (value), (nb_bit)) \
+ : (sizeof(*(value)) == 8 ? bitstream_access_64 ((ctx), (value), (nb_bit)) \
+ : bitstream_access_unknown_size ()))))
+
+/**
+ * Return the number of remaining bits before the read or write limit.
+ * \param ctx bit stream context
+ * \return number of remaining bits
+ *
+ * Using this function, the user can check whether the next read or
+ * write accesses will succeed.
+ */
+uint
+bitstream_available_bits (bitstream_t *ctx);
+
+/**
+ * Read or write the next "nb_bit" from/to the memory pointer
+ * stored into the ctx.
+ * \param ctx bit stream context
+ * \param value pointer to the value
+ * \param nb_bit number of bits to read
+ *
+ * Access type (read or write) depends on context initialization.
+ */
+uint
+bitstream_access_8 (bitstream_t *ctx, void *value, uint nb_bit);
+
+/**
+ * Read or write the next "nb_bit" from/to the memory pointer
+ * stored into the ctx.
+ * \param ctx bit stream context
+ * \param value pointer to the value
+ * \param nb_bit number of bits to read
+ *
+ * Access type (read or write) depends on context initialization.
+ */
+uint
+bitstream_access_16 (bitstream_t *ctx, void *value, uint nb_bit);
+
+/**
+ * Read or write the next "nb_bit" from/to the memory pointer
+ * stored into the ctx.
+ * \param ctx bit stream context
+ * \param value pointer to the value
+ * \param nb_bit number of bits to read
+ *
+ * Access type (read or write) depends on context initialization.
+ */
+uint
+bitstream_access_32 (bitstream_t *ctx, void *value, uint nb_bit);
+
+/**
+ * Read or write the next "nb_bit" from/to the memory pointer
+ * stored into the ctx.
+ * \param ctx bit stream context
+ * \param value pointer to the value
+ * \param nb_bit number of bits to read
+ *
+ * Access type (read or write) depends on context initialization.
+ */
+uint
+bitstream_access_64 (bitstream_t *ctx, void *value, uint nb_bit);
+
+/**
+ * Read "nb_bit" bits from data pointer + bit offset
+ * \param data data base pointer
+ * \param bit_offset bit offset
+ * \param nb_bit number of bits to read
+ * \return bit read data
+ *
+ * Bit number must be <= 32 or use bitstream_direct_read_large
+ */
+uint
+bitstream_direct_read (void *data, uint bit_offset, uint nb_bit);
+
+/**
+ * Read "nb_bit" bits from data pointer + bit offset
+ * \param data data base pointer
+ * \param bit_offset bit offset
+ * \param nb_bit number of bits to read
+ * \return bit read data
+ */
+u64
+bitstream_direct_read_large (u8 *data, uint bit_offset, uint nb_bit);
+
+/**
+ * Write "nb_bit" bits to data pointer + bit offset
+ * \param data data base pointer
+ * \param bit_offset bit offset
+ * \param value bit value to write
+ * \param nb_bit number of bits to write
+ *
+ * Bit number must be <= 32 or use bitstream_direct_write_large
+ */
+void
+bitstream_direct_write (void *data, uint bit_offset, uint value, uint nb_bit);
+
+/**
+ * Write "nb_bit" bits to data pointer + bit offset
+ * \param data data base pointer
+ * \param bit_offset bit offset
+ * \param value bit value to write
+ * \param nb_bit number of bits to write
+*/
+void
+bitstream_direct_write_large (u8 *data, uint bit_offset, u64 value,
+ uint nb_bit);
+
+/**
+ *
+*/
+void*
+bitstream_memcpy (void *dest, void *src, size_t len);
+
+/**
+ * Compare two buffers and return true if the buffers are equals
+ * \param s1 the first buffer to compare.
+ * \param s2 the second buffer to compare.
+ * \param len the length in bytes to compare the buffers.
+ * \return true if equal, false otherwise.
+ */
+bool
+bitstream_memcmp (void *s1, void *s2, size_t len);
+
+#endif /* bitstream_h */
diff --git a/cesar/lib/blk.h b/cesar/lib/blk.h
new file mode 100644
index 0000000000..ff4ab45efc
--- /dev/null
+++ b/cesar/lib/blk.h
@@ -0,0 +1,218 @@
+#ifndef lib_blk_h
+#define lib_blk_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/blk.h
+ * \brief 512 byte memory blocks.
+ * \ingroup lib
+ *
+ * This entity provide 512 byte memory blocks allocation and reference
+ * counting. Each block counts the number of reference pointing to it. The
+ * user is responsible for managing this counter using addref and release
+ * functions. When the number of references of a block reach zero, the block
+ * is freed.
+ *
+ * Each block is associated with a descriptor. This descriptor is 16 byte
+ * long. The first 8 bytes are reserved for the blk_t type and the rest could
+ * be used for anything the user wants. The type blk_t provide a chaining and
+ * a pointer to data member. This is the basis for hardware blocks chaining.
+ *
+ * The API is available in two flavors. The first one works with descriptors.
+ * The user can request one or more chained blocks and will be given pointers
+ * to descriptors. The second one works directly with data, hiding the
+ * descriptor to the user. In the second flavor, only one block can be
+ * requested at a time.
+ *
+ * An extra feature is provided for block allocated without a descriptor:
+ * automatic destruction. In this case, the descriptor is used to store the
+ * destructor function pointer.
+ *
+ * The reference counter is placed just before the descriptor.
+ *
+ * The reference counter is modified atomically but once it reach zero
+ * reference, the block is freed immediately.
+ */
+
+#include "lib/restrack.h"
+
+/** A block is 512 bytes. */
+#define BLK_SIZE 512
+
+/** A block descriptor is 16 bytes, that is greater than \c blk_t. */
+#define BLK_DESC_SIZE 16
+
+/** A block descriptor reference counter is 4 bytes. */
+#define BLK_REFCNT_SIZE 4
+
+/** Memory block descriptor.
+ * This structure store information about a 512 byte memory block. This
+ * representation is shared between hardware and software. */
+struct blk_t
+{
+ /** Pointer to next descriptor. */
+ struct blk_t *next;
+ /** Pointer to data. */
+ u8 *data;
+};
+typedef struct blk_t blk_t;
+
+/**
+ * Block destructor called just before the block memory is released.
+ * \param data pointer to block data
+ *
+ * Destructor feature can only be used with block returned without a
+ * descriptor as the it is then used internally to store the destructor
+ * pointer.
+ */
+typedef void (*blk_destructor_t) (void *data);
+
+BEGIN_DECLS
+
+/**
+ * Return a newly allocated 512 byte block with its descriptor.
+ * \return the descriptor pointer
+ *
+ * The \c next pointer in the block descriptor is undefined.
+ */
+blk_t *
+blk_alloc_desc_ (void_FL);
+#define blk_alloc_desc() blk_alloc_desc_ (_fL)
+
+/**
+ * Return a number of newly allocated 512 byte blocks with their descriptors.
+ * \param n number of block
+ * \param last where to write the last block descriptor pointer
+ * \return the first block descriptor
+ *
+ * The returned blocks descriptors are chained, the \c next pointer in the
+ * last block descriptor is undefined.
+ */
+blk_t *
+blk_alloc_desc_range_ (uint n, blk_t **last __FL);
+#define blk_alloc_desc_range(n, last) blk_alloc_desc_range_ ((n), (last) __fL)
+
+/**
+ * Add a reference to a block.
+ * \param blk the block to reference
+ */
+void
+blk_addref_desc_ (blk_t *blk __FL);
+#define blk_addref_desc(blk) blk_addref_desc_ ((blk) __fL)
+
+/**
+ * Add a reference to a list of blocks.
+ * \param first first block to reference
+ * \param last last block to reference
+ */
+void
+blk_addref_desc_range_ (blk_t *first, blk_t *last __FL);
+#define blk_addref_desc_range(first, last) \
+ blk_addref_desc_range_ ((first), (last) __fL)
+
+/**
+ * Add a reference to a list of blocks, by number of blocks.
+ * \param first first block to reference
+ * \param n number of block
+ */
+void
+blk_addref_desc_range_nb_ (blk_t *first, uint n __FL);
+#define blk_addref_desc_range_nb(first, n) \
+ blk_addref_desc_range_nb_ ((first), (n) __fL)
+
+/**
+ * Release a block reference.
+ * \param blk the block to release
+ */
+void
+blk_release_desc_ (blk_t *blk __FL);
+#define blk_release_desc(blk) blk_release_desc_ ((blk) __fL)
+
+/**
+ * Release references for a list of blocks.
+ * \param first first block to release
+ * \param last last block to release
+ */
+void
+blk_release_desc_range_ (blk_t *first, blk_t *last __FL);
+#define blk_release_desc_range(first, last) \
+ blk_release_desc_range_ ((first), (last) __fL)
+
+/**
+ * Release references for a list of blocks, by number of blocks.
+ * \param first first block to release
+ * \param n number of block
+ */
+void
+blk_release_desc_range_nb_ (blk_t *first, uint n __FL);
+#define blk_release_desc_range_nb(first, n) \
+ blk_release_desc_range_nb_ ((first), (n) __fL)
+
+/**
+ * Allocate a 512 byte block, without descriptor.
+ * \return the newly allocated block
+ */
+void *
+blk_alloc_ (void_FL);
+#define blk_alloc() blk_alloc_ (_fL)
+
+/**
+ * Allocate a zero'ed 512 byte block, without descriptor.
+ * \return the newly allocated block
+ */
+void *
+blk_alloc_zero_ (void_FL);
+#define blk_alloc_zero() blk_alloc_zero_ (_fL)
+
+/**
+ * Allocate a 512 byte block, without descriptor and save the destructor.
+ * \param destructor destructor function pointer
+ * \return the newly allocated block
+ */
+void *
+blk_new_ (blk_destructor_t destructor __FL);
+#define blk_new(destructor) blk_new_ ((destructor) __fL)
+
+/**
+ * Add a reference to a block without descriptor.
+ */
+void
+blk_addref_ (void *data __FL);
+#define blk_addref(data) blk_addref_ ((data) __fL)
+
+/**
+ * Release a block reference and call the optional destructor if the block is
+ * freed.
+ * \param data pointer to block data
+ */
+void
+blk_release_ (void *data __FL);
+#define blk_release(data) blk_release_ ((data) __fL)
+
+/**
+ * Check if all the blocks previously allocated are now free.
+ * \return true if all blocks are free
+ *
+ * Check if the number of blocks freed is equals to the number of blocks
+ * allocated and if the number of blocks released is equals to the number of
+ * blocks referenced.
+ */
+bool
+blk_check_memory (void);
+
+/**
+ * Print memory blocks informations.
+ *
+ * Print the number of blocks allocated, freed, referenced, and released.
+ */
+void
+blk_print_memory (void);
+
+END_DECLS
+
+#endif /* lib_blk_h */
diff --git a/cesar/lib/circular_buffer.h b/cesar/lib/circular_buffer.h
new file mode 100644
index 0000000000..bb01c9a771
--- /dev/null
+++ b/cesar/lib/circular_buffer.h
@@ -0,0 +1,75 @@
+#ifndef lib_circular_buffer_h
+#define lib_circular_buffer_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/circular_buffer.h
+ * \brief Circular buffer list
+ * \ingroup lib
+ *
+ * Provides a circular buffer list API.
+ * Reserve the real size of the buffer just after the declaration of the
+ * circular buffer to not have some memory problems.
+ */
+
+struct circular_buffer_t
+{
+ /** Number of slots of power of 2. */
+ uint num_slots;
+ /** head. */
+ uint head;
+ /** tail. */
+ uint tail;
+ /** buffer. */
+ void **buffer;
+ /** number of elements in the list. */
+ uint nb_elements;
+};
+typedef struct circular_buffer_t circular_buffer_t;
+
+/**
+ * Initialize the buffer address list
+ *
+ * \param list the buffer address list to initiliaze
+ * \param buffer the circular buffer to use.
+ * \param number_slots the quantity of slots.
+ */
+void
+circular_buffer_init (circular_buffer_t *list, void *buffer, uint number_slots);
+
+/**
+ * Add an address to the buffer address buffer list
+ *
+ * \param ctx the ctx containing the list.
+ * \param address the address to add to the list
+ * \param number_of_slots the quantity of address it can keep in the list.
+ *
+ * \return true if the buffer had been added, false otherwise
+ */
+bool
+circular_buffer_add (circular_buffer_t *ctx, void *address);
+
+/**
+ * Peek the first element of the list without removing it.
+ *
+ * \param ctx the context.
+ */
+void*
+circular_buffer_peek (circular_buffer_t *ctx);
+
+/**
+ * Get the current address and go to the next one.
+ *
+ * \param ctx the ctx containing the list.
+ * \param number_of_slots the quantity of address it can keep in the list.
+ */
+void*
+circular_buffer_get (circular_buffer_t *ctx);
+
+
+#endif /* lib_circular_buffer_h */
diff --git a/cesar/lib/crc.h b/cesar/lib/crc.h
new file mode 100644
index 0000000000..87834fb807
--- /dev/null
+++ b/cesar/lib/crc.h
@@ -0,0 +1,117 @@
+#ifndef lib_crc_h
+#define lib_crc_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/crc.h
+ * \brief General Cyclic Redundancy Code utilities.
+ * \ingroup lib
+ *
+ * This module follows the Rocksoft^tm Model CRC Algorithm, introduced in "A
+ * painless guide to CRC error detection algorithms" by Ross N. Williams. You
+ * can get it at http://www.ross.net/crc/.
+ *
+ * Once you got a functional CRC algorithm, you also have to take care of
+ * details such as:
+ * - bit and byte order of the CRC digest,
+ * - whether extra zeros must be added to the message (this could be
+ * precomputed in crc_init),
+ * - what is the expected CRC result if feeding the algorithms with the
+ * message along with the appended CRC digest.
+ *
+ * CRC tables might be shared between several algorithms but this is an
+ * unsupported feature, use at your own risk (basically, any parameters used
+ * to initialise the table must be the same between the sharing algorithms).
+ * If you play this game, remember that there is more than the table to
+ * contain precomputed values.
+ */
+
+/** CRC description structure. */
+struct crc_t
+{
+ /** \name client
+ * Client filled values. */
+ /*@{*/
+ /** Width of the CRC register. */
+ uint width;
+ /** Generator polynomial, with the top bit left of. */
+ u32 generator;
+ /** Initial value of the CRC register. */
+ u32 init;
+ /** Whether to reflect input bytes. */
+ bool refin;
+ /** Whether to reflect the generated CRC. */
+ bool refout;
+ /** Value XOR'd with the final CRC register value. */
+ u32 xorout;
+ /*@}*/
+ /** \name precomputed
+ * Precomputed values, filled by crc_init(). */
+ /*@{*/
+ /** Precomputed initial register value. */
+ u32 reg_init;
+ /** Precomputed table, client should initialise table pointer. */
+ union {
+ /** Access by bytes. */
+ u8 *t8;
+ /** Access by halfwords. */
+ u16 *t16;
+ /** Access by words. */
+ u32 *t32;
+ } table;
+ /*@}*/
+};
+typedef struct crc_t crc_t;
+
+/**
+ * Compute precomputed values for the given CRC characteristics.
+ * \param ctx filled CRC description
+ */
+void
+crc_init (crc_t *ctx);
+
+/**
+ * Compute a CRC on a data block in one go.
+ * \param ctx initialised CRC description
+ * \param block data block
+ * \param block_size data block size
+ * \return computed CRC
+ */
+u32
+crc_compute_block (const crc_t *ctx, const u8 *block, uint block_size);
+
+/**
+ * Begin a CRC computation.
+ * \param ctx initialised CRC description
+ * \return initialised CRC register
+ */
+u32
+crc_compute_begin (const crc_t *ctx);
+
+/**
+ * Continue a CRC computation on a data block.
+ * \param ctx initialised CRC description
+ * \param reg previously used or initialised CRC register
+ * \param block data block
+ * \param block_size data block size
+ * \return CRC register
+ */
+u32
+crc_compute_continue_block (const crc_t *ctx, u32 reg, const u8 *block,
+ uint block_size);
+
+/**
+ * End a CRC computation.
+ * \param ctx initialised CRC description
+ * \param reg previously used CRC register
+ * \return computed CRC
+ */
+u32
+crc_compute_end (const crc_t *ctx, u32 reg);
+
+#endif /* lib_crc_h */
diff --git a/cesar/lib/dbg.h b/cesar/lib/dbg.h
new file mode 100644
index 0000000000..f3462a92e2
--- /dev/null
+++ b/cesar/lib/dbg.h
@@ -0,0 +1,327 @@
+#ifndef lib_dbg_h
+#define lib_dbg_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/dbg.h
+ * \brief Debug functions.
+ * \ingroup lib
+ */
+
+#include "config/debug.h"
+
+/** Shortcut for CONFIG_DEBUG */
+#define DEBUG CONFIG_DEBUG
+
+/** Shortcut for CONFIG_DEBUG_MORE.
+ * If activated, costly debugs are activated. */
+#define DEBUG_MORE CONFIG_DEBUG_MORE
+
+#if DEBUG && CONFIG_DEBUG_FATAL_CATCH
+# include "lib/try.h"
+#endif
+#include <stdarg.h>
+
+/**
+ * Check that the provided expression is true.
+ * \param expr the assumed truth
+ *
+ * \warning \a expr is not evaluated when asserts are disabled.
+ */
+#define dbg_assert(expr) \
+ dbg_assert_ (expr, #expr)
+
+/**
+ * Check that the provided pointer is fine.
+ * \param ptr the pointer to check
+ *
+ * \warning \a ptr is not evaluated when asserts are disabled.
+ */
+#define dbg_assert_ptr(ptr) \
+ dbg_assert_ptr_ (ptr, #ptr)
+
+/**
+ * Check that the provided expression is true and provide more information on
+ * failure.
+ * \param expr the assumed truth
+ * \param fmt printf-like format string
+ * \param rest printf-like arguments
+ *
+ * \warning \a expr is not evaluated when asserts are disabled.
+ */
+#define dbg_assert_print(expr, fmt, rest...) \
+ dbg_assert_print_ (expr, fmt, ## rest)
+
+/**
+ * Check that the provided expression is true and print additional errno
+ * information on failure.
+ * \param expr the assumed truth
+ *
+ * \warning \a expr is not evaluated when asserts are disabled.
+ */
+#define dbg_assert_perror(expr) \
+ dbg_assert_perror_ (expr, #expr)
+
+/**
+ * Use this macro in a forbidden default clause in switches.
+ */
+#define dbg_assert_default() \
+ dbg_assert_default_ ()
+
+/**
+ * Check that the provided expression is true, evaluate the expression even
+ * when asserts are disabled.
+ * \param expr the assumed truth
+ *
+ * \warning \a expr is always evaluated.
+ */
+#define dbg_check(expr) \
+ dbg_check_ (expr, #expr)
+
+/**
+ * Check that the provided expression is true, evaluate the expression even
+ * when asserts are disabled and provide more information on failure.
+ * \param expr the assumed truth
+ * \param fmt printf-like format string
+ * \param rest printf-like arguments
+ *
+ * \warning \a expr is always evaluated.
+ */
+#define dbg_check_print(expr, fmt, rest...) \
+ dbg_check_print_ (expr, fmt, ## rest)
+
+/**
+ * Check that the provided expression is true and print additional errno
+ * information on failure, evaluate the expression even when asserts are
+ * disabled.
+ * \param expr the assumed truth
+ *
+ * \warning \a expr is always evaluated.
+ */
+#define dbg_check_perror(expr) \
+ dbg_check_perror_ (expr, #expr)
+
+/* Asserts definitions. */
+#if DEBUG
+
+# define DBG_ASSERT_FMT_ "%s:%d: assertion failure in %s: "
+
+# define dbg_assert_ dbg_assert__
+# define dbg_assert_ptr_ dbg_assert_ptr__
+# define dbg_assert_print_ dbg_assert_print__
+# define dbg_assert_perror_ dbg_assert_perror__
+# define dbg_assert_default_ dbg_assert_default__
+# define dbg_check_ dbg_assert__
+# define dbg_check_print_ dbg_assert_print__
+# define dbg_check_perror_ dbg_assert_perror__
+# define dbg_assert__(expr, exprs) \
+ ((void) ((expr) ? 0 : (dbg_assert_fail (exprs, __FILE__, __LINE__, \
+ __PRETTY_FUNCTION__), 0)))
+# define dbg_assert_ptr__(ptr, ptrs) \
+ ((void) ((ptr && ptr != INVALID_PTR) ? 0 : \
+ (dbg_assert_fail ("@" ptrs, __FILE__, __LINE__, \
+ __PRETTY_FUNCTION__), 0)))
+# define dbg_assert_print__(expr, fmt, rest...) \
+ ((void) ((expr) ? 0 : (dbg_assert_print_fail (DBG_ASSERT_FMT_ fmt, \
+ __FILE__, __LINE__, \
+ __PRETTY_FUNCTION__, \
+ ##rest), 0)))
+# define dbg_assert_perror__(expr, exprs) \
+ ((void) ((expr) ? 0 : (dbg_assert_perror_fail (exprs, __FILE__, __LINE__, \
+ __PRETTY_FUNCTION__), 0)))
+# define dbg_assert_default__() \
+ dbg_assert_fail ("unexpected default case", __FILE__, __LINE__, \
+ __PRETTY_FUNCTION__)
+
+#else /* !DEBUG */
+
+# define dbg_assert_ dbg_void__
+# define dbg_assert_ptr_ dbg_void__
+# define dbg_assert_print_ dbg_void_print__
+# define dbg_assert_perror_ dbg_void__
+# define dbg_assert_default_ dbg_void__
+# define dbg_check_ dbg_eval__
+# define dbg_check_print_ dbg_eval_print__
+# define dbg_check_perror_ dbg_eval__
+# define dbg_void__(args...) ((void) 0)
+# define dbg_eval__(expr, exprs) ((void) (expr, 0))
+# define dbg_void_print__(expr, fmt, rest...) ((void) 0)
+# define dbg_eval_print__(expr, fmt, rest...) ((void) (expr, 0))
+
+#endif /* !DEBUG */
+
+/**
+ * Invalidate a pointer.
+ * \param ptr pointer to invalidate
+ *
+ * The pointer is set to an invalid value. This is better than set to NULL,
+ * because one could test a pointer for this special NULL value and be very
+ * disappointed when compiling without debug.
+ */
+#define dbg_invalid_ptr(ptr) dbg_invalid_ptr_ (ptr)
+
+/**
+ * Compile something only when debug is activated.
+ * \param smth the thing conditionally compiled
+ */
+#define dbg_do(smth) dbg_do_ (smth)
+
+#if DEBUG
+# define dbg_invalid_ptr_(ptr) (ptr) = INVALID_PTR
+# define dbg_do_(smth) smth
+#else /* !DEBUG */
+# define dbg_invalid_ptr_(ptr) ((void) 0)
+# define dbg_do_(smth)
+#endif /* !DEBUG */
+
+/**
+ * Begin a try block to catch fatal errors.
+ *
+ * dbg_fatal_try_begin, dbg_fatal_try_catch and dbg_fatal_try_end define a
+ * try-catch sequence to catch fatal errors:
+ *
+ * \code
+ * dbg_fatal_try_begin
+ * {
+ * ...code which could fail...
+ * }
+ * dbg_fatal_try_catch (const char *fatal_message)
+ * {
+ * ...code to handle failure...
+ * }
+ * dbg_fatal_try_end;
+ * \endcode
+ *
+ * This is implemented using setjmp, please see setjmp documentation for
+ * quirks about this.
+ */
+#define dbg_fatal_try_begin dbg_fatal_try_begin_
+/** End a try block to catch fatal errors. */
+#define dbg_fatal_try_end dbg_fatal_try_end_
+/** Catch fatal errors. */
+#define dbg_fatal_try_catch(vardecl) dbg_fatal_try_catch_(vardecl)
+/** Use in place of dbg_fatal_try_catch when not interested by the message. */
+#define dbg_fatal_try_catch_void() dbg_fatal_try_catch_void_
+
+#if DEBUG && CONFIG_DEBUG_FATAL_CATCH
+
+extern int dbg_fatal_try_level_;
+
+/** Fatal error message buffer. */
+extern char dbg_fatal_text_[];
+
+# define dbg_fatal_try_begin_ \
+{ \
+ dbg_fatal_try_level_++; \
+ try_begin \
+ {
+
+#define dbg_fatal_try_catch_(vardecl) \
+ } \
+ try_catch (TRY_CODE_FATAL) \
+ { \
+ vardecl = dbg_fatal_text_; \
+ {
+
+#define dbg_fatal_try_catch_void_ \
+ } \
+ try_catch (TRY_CODE_FATAL) \
+ { \
+ {
+
+# define dbg_fatal_try_end_ \
+ } \
+ } \
+ try_always \
+ { \
+ dbg_fatal_try_level_--; \
+ } \
+ try_end; \
+}
+
+#else /* !(DEBUG && CONFIG_DEBUG_FATAL_CATCH) */
+
+# define dbg_fatal_try_begin_ \
+{ \
+ if (1) \
+ {
+
+#define dbg_fatal_try_catch_(vardecl) \
+ } \
+ else \
+ { \
+ vardecl = NULL; \
+ {
+
+#define dbg_fatal_try_catch_void_ \
+ } \
+ else \
+ { \
+ {
+
+# define dbg_fatal_try_end_ \
+ } \
+ } \
+}
+
+#endif /* !(DEBUG && CONFIG_DEBUG_FATAL_CATCH) */
+
+BEGIN_DECLS
+
+/**
+ * Called on assertion failure.
+ * \param assertion assertion text
+ * \param file source file name
+ * \param line source file line
+ * \param function source function name
+ */
+void
+dbg_assert_fail (const char *assertion, const char *file, uint line,
+ const char *function) __attribute__ ((__noreturn__));
+
+/**
+ * Called on assertion failure with more information on failure.
+ * \param fmt printf-like format string
+ */
+void
+dbg_assert_print_fail (const char *fmt, ...)
+ __attribute__ ((__noreturn__, format (printf, 1, 2)));
+
+/**
+ * Called on errno assertion failure.
+ * \param assertion assertion text
+ * \param file source file name
+ * \param line source file line
+ * \param function source function name
+ *
+ * \todo implement
+ */
+void
+dbg_assert_perror_fail (const char *assertion, const char *file, uint line,
+ const char *function) __attribute__ ((__noreturn__));
+
+/**
+ * Stop the program with a fatal error.
+ * \param fmt printf-like format string
+ */
+void
+dbg_fatal (const char *fmt, ...)
+ __attribute__ ((__noreturn__, format (printf, 1, 2)));
+
+/**
+ * Stop the program with a fatal error, variable arguments version.
+ * \param fmt printf-like format string
+ * \param ap argument list pointer
+ */
+void
+dbg_vfatal (const char *fmt, va_list ap)
+ __attribute__ ((__noreturn__));
+
+END_DECLS
+
+#endif /* lib_dbg_h */
diff --git a/cesar/lib/defs.h b/cesar/lib/defs.h
new file mode 100644
index 0000000000..695b8d8832
--- /dev/null
+++ b/cesar/lib/defs.h
@@ -0,0 +1,41 @@
+#ifndef lib_defs_h
+#define lib_defs_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/defs.h
+ * \brief Globals compiler and target specific defines.
+ * \ingroup lib
+ */
+
+/** Defined to 1 if the target is using big endian. */
+#define DEFS_BIG_ENDIAN _see_below_
+#undef DEFS_BIG_ENDIAN
+
+/** Defined to 1 if structure's bit fields should be reversed. */
+#define DEFS_REVERSE_BITFIELDS _see_below_
+#undef DEFS_REVERSE_BITFIELDS
+
+#if defined (__sparc__)
+
+# define DEFS_BIG_ENDIAN 1
+# define DEFS_REVERSE_BITFIELDS 1
+
+#else /* others. */
+
+# define DEFS_BIG_ENDIAN 0
+# define DEFS_REVERSE_BITFIELDS 0
+
+#endif
+
+#if __GNUC__ < 4
+/* This attribute is not defined for older GCC versions. */
+# define warn_unused_result
+#endif
+
+#endif /* lib_defs_h */
diff --git a/cesar/lib/heap.h b/cesar/lib/heap.h
new file mode 100644
index 0000000000..6505f0f001
--- /dev/null
+++ b/cesar/lib/heap.h
@@ -0,0 +1,124 @@
+#ifndef lib_heap_h
+#define lib_heap_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/heap.h
+ * \brief Heap (the data structure) service.
+ * \ingroup lib
+ *
+ * An heap is a tree data structure which satisfies the following property: if B
+ * is a child of A, then B.key >= A.key.
+ *
+ * It defines the following set of operations efficiently:
+ * - insert,
+ * - find root (the minimum value),
+ * - remove root (the minimum value).
+ *
+ * Some heap algorithms also define the following efficient operations:
+ * - remove a arbitrary node,
+ * - merge two heaps.
+ *
+ * Its common use is to implement priority queue.
+ */
+#include "config/heap.h"
+
+/* Forward declaration. */
+typedef struct heap_node_t heap_node_t;
+
+/**
+ * Heap node comparison function pointer.
+ * \param left left hand node
+ * \param right right hand node
+ * \return true iff left is lesser than right
+ */
+typedef bool
+(*heap_node_less_t) (heap_node_t *left, heap_node_t *right);
+
+/** Heap structure. */
+struct heap_t
+{
+ /** Heap root node. */
+ heap_node_t *root;
+ /** Heap "is lesser than" comparison function. */
+ heap_node_less_t less;
+};
+typedef struct heap_t heap_t;
+
+#if CONFIG_HEAP_SKEW
+# include "lib/skewheap.h"
+#elif CONFIG_HEAP_LEFTIST
+# include "lib/leftheap.h"
+#endif
+
+/** Heap node with an u32 key. */
+struct heap_node_u32_t
+{
+ heap_node_t node;
+ u32 key;
+};
+typedef struct heap_node_u32_t heap_node_u32_t;
+
+BEGIN_DECLS
+
+/**
+ * Initialise a new heap.
+ * \param heap the heap
+ * \param less the "is lesser than" comparison function
+ */
+void
+heap_init (heap_t *heap, heap_node_less_t less);
+
+/**
+ * Adjust position of a given node after a key change.
+ * \param heap the heap
+ * \param node the node to adjust.
+ *
+ * Actually, if the node is at a good position, nothing is done. In other
+ * cases, it is removed, then inserted.
+ */
+void
+heap_adjust (heap_t *heap, heap_node_t *node);
+
+/**
+ * Get heap root.
+ * \param heap the heap
+ * \return the root or NULL if the heap is empty
+ */
+extern inline heap_node_t *
+heap_get_root (heap_t *heap)
+{
+ return heap->root;
+}
+
+/**
+ * Return whether the heap is empty.
+ * \param heap the heap
+ * \return true if empty
+ */
+extern inline bool
+heap_empty (heap_t *heap)
+{
+ return !heap->root;
+}
+
+/**
+ * Merge two heaps, result in the first one.
+ * \param heap_to heap receiving the result
+ * \param heap_from heap to be merge with the first one
+ */
+void
+heap_merge (heap_t *heap_to, heap_t *heap_from);
+
+/** Heap comparison function for an u32 node using modulo 2^32. */
+bool
+heap_node_u32_less_mod2p32 (heap_node_t *left, heap_node_t *right);
+
+END_DECLS
+
+#endif /* lib_heap_h */
diff --git a/cesar/lib/heapsort.h b/cesar/lib/heapsort.h
new file mode 100644
index 0000000000..5769c33b8f
--- /dev/null
+++ b/cesar/lib/heapsort.h
@@ -0,0 +1,125 @@
+#ifndef LIB_HEAPSORT_H_
+#define LIB_HEAPSORT_H_
+
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/heapsort.h
+ * \brief heapsort algorithm.
+ * \ingroup lib
+ *
+ * Sort an array of randomed value using a virtual heap (it does not create
+ * an real heap in the memory).
+ *
+ * see the heapsort page on wikipedia
+ * http://en.wikipedia.org/wiki/Heapsort
+ *
+ * Complexity : O (n log n)
+ * Mem : O (1)
+ *
+ * Some MACROS must be defined to use the heapsort.
+ *
+ * LIB_HEAPSORT_USER_TYPE corresponding to the type the lib heapsort will use
+ * to sort the array
+ *
+ * LIB_HEAPSORT_USER_COMP user function to compare two values.
+ * LIB_HEAPSORT_USER_SWAP user function swap to exchange two values.
+ *
+ * LIB_HEAPSORT_USER_PREFIX user prefix function.
+ */
+
+/** Verify if the MACROS had been defined. */
+#if (!defined (LIB_HEAPSORT_USER_TYPE) \
+ || !defined (LIB_HEAPSORT_USER_COMP_LESSER) \
+ || !defined (LIB_HEAPSORT_USER_SWAP) \
+ || !defined (LIB_HEAPSORT_USER_PREFIX))
+#error "Some macros had not been defined"
+#endif
+
+#define lib_heapsort_siftdown PASTE_EXPAND (LIB_HEAPSORT_USER_PREFIX, _siftdown)
+#define lib_heapsort_heapify PASTE_EXPAND (LIB_HEAPSORT_USER_PREFIX, _heapify)
+#define lib_heapsort PASTE_EXPAND (LIB_HEAPSORT_USER_PREFIX, _heapsort)
+
+/**
+ * siftdown the heap.
+ *
+ * \param user_type the user type to do the siftdown on
+ * \param start the start position
+ * \param end the end position
+ */
+void lib_heapsort_siftdown (LIB_HEAPSORT_USER_TYPE *user_type, uint start, uint end)
+{
+ uint root;
+ uint child;
+
+ dbg_assert (user_type);
+
+ root = start;
+ while ((child = root * 2 + 1) <= end)
+ {
+ if (child < end
+ && LIB_HEAPSORT_USER_COMP_LESSER (user_type, child, child + 1))
+ {
+ child ++;
+ }
+
+ if (LIB_HEAPSORT_USER_COMP_LESSER (user_type, root, child))
+ {
+ LIB_HEAPSORT_USER_SWAP (user_type, root, child);
+ root = child;
+ }
+ else
+ {
+ break;
+ }
+ }
+}
+
+/**
+ * heapify, the user_type to sort
+ *
+ * \param user_type to sort
+ * \param nb the number of data in the type
+ */
+void lib_heapsort_heapify (LIB_HEAPSORT_USER_TYPE *user_type, uint nb)
+{
+ int start;
+
+ dbg_assert (user_type);
+ start = nb / 2 - 1;
+
+ while (start >= 0)
+ {
+ lib_heapsort_siftdown (user_type, start, nb - 1);
+ start --;
+ }
+}
+
+/**
+ * heapsort algorithm
+ *
+ * \param user_type the data to sort
+ * \param nb the number of data in the type
+ */
+void lib_heapsort (LIB_HEAPSORT_USER_TYPE *user_type, uint nb)
+{
+ dbg_assert (user_type);
+
+ uint end;
+ lib_heapsort_heapify (user_type, nb);
+
+ end = nb - 1;
+ while (end)
+ {
+ LIB_HEAPSORT_USER_SWAP (user_type, 0, end);
+ end --;
+ lib_heapsort_siftdown (user_type, 0, end);
+ }
+}
+
+#endif /*LIB_HEAPSORT_H_*/
diff --git a/cesar/lib/leftheap.h b/cesar/lib/leftheap.h
new file mode 100644
index 0000000000..b2efd42cfe
--- /dev/null
+++ b/cesar/lib/leftheap.h
@@ -0,0 +1,81 @@
+#ifndef lib_leftheap_h
+#define lib_leftheap_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/leftheap.h
+ * \brief Leftist heaps.
+ * \ingroup lib
+ *
+ * Leftist heaps were invented by Clark Allan Crane. This heap structure has
+ * the particularity to be very unbalanced, where the shortest path to an
+ * external node is always to the right.
+ *
+ * All operations are defined using the merge operation which operates O(log
+ * n). The merge operation walks the right path (remember it is the shortest)
+ * and merge with the heap to be merged, swapping left and right children as
+ * needed.
+ */
+
+/** Heap node. */
+struct heap_node_t
+{
+ /** Pointer to parent node. */
+ struct heap_node_t *father;
+ /** Pointer to left and right children. */
+ struct heap_node_t *left, *right;
+ /** Shortest path to a external node. */
+ uint null_path_length;
+};
+
+BEGIN_DECLS
+
+/**
+ * Initialise an heap node.
+ * \param node the node to initialise
+ */
+void
+heap_node_init (heap_node_t *node);
+
+/**
+ * Merge two heaps rooted at the given nodes.
+ * \param root1 the first heap root
+ * \param root2 the second heap root (surprise!)
+ * \param less comparison function
+ * \return the new root node.
+ */
+heap_node_t *
+heap_node_merge (heap_node_t *root1, heap_node_t *root2,
+ heap_node_less_t less);
+
+/**
+ * Insert a new node in the given heap.
+ * \param heap the heap
+ * \param node the node to insert
+ */
+void
+heap_insert (heap_t *heap, heap_node_t *node);
+
+/**
+ * Remove the heap root.
+ * \param heap the heap
+ */
+void
+heap_remove_root (heap_t *heap);
+
+/**
+ * Remove an arbitrary element
+ * \param heap the heap
+ * \param node the node to remove
+ */
+void
+heap_remove (heap_t *heap, heap_node_t *node);
+
+END_DECLS
+
+#endif /* lib_leftheap_h */
diff --git a/cesar/lib/list.h b/cesar/lib/list.h
new file mode 100644
index 0000000000..042236ac65
--- /dev/null
+++ b/cesar/lib/list.h
@@ -0,0 +1,191 @@
+#ifndef lib_list_h
+#define lib_list_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/list.h
+ * \brief Double linked lists.
+ * \ingroup lib
+ */
+
+/** Double linked list node. */
+struct list_node_t
+{
+ /** Pointer to next node. */
+ struct list_node_t *next;
+ /** Pointer to previous node. */
+ struct list_node_t *prev;
+};
+typedef struct list_node_t list_node_t;
+
+/** Double linked list. */
+struct list_t
+{
+ /** List NIL element. */
+ list_node_t nil;
+};
+typedef struct list_t list_t;
+
+BEGIN_DECLS
+
+/**
+ * Initialise a double linked list.
+ * \param list the list to initialise
+ */
+void
+list_init (list_t *list);
+
+/**
+ * Initialise a list node.
+ * \param node the node to initialise
+ */
+void
+list_init_node (list_node_t *node);
+
+/**
+ * Return the first node.
+ * \param list the list
+ * \return the first node
+ */
+list_node_t *
+list_begin (list_t *list);
+
+/**
+ * Return past the last node.
+ * \param list the list
+ * \return the node after the last
+ */
+list_node_t *
+list_end (list_t *list);
+
+/**
+ * Return last node to backward iteration.
+ * \param list the list
+ * \return the last node
+ */
+list_node_t *
+list_rbegin (list_t *list);
+
+/**
+ * Return before the first node.
+ * \param list the list
+ * \return the node before the first
+ */
+list_node_t *
+list_rend (list_t *list);
+
+/**
+ * Return the next node.
+ * \param node the current node
+ * \return the node after the current one
+ */
+list_node_t *
+list_next (list_node_t *node);
+
+/**
+ * Return the previous node.
+ * \param node the current node
+ * \return the node before the current one
+ */
+list_node_t *
+list_prev (list_node_t *node);
+
+/**
+ * Is the list empty?
+ * \param list the list
+ * \return true if empty
+ */
+bool
+list_empty (list_t *list);
+
+/**
+ * Push a node to the end of a list.
+ * \param list the list
+ * \param node the node to push
+ */
+void
+list_push (list_t *list, list_node_t *node);
+
+/**
+ * Unshift a node to the begin of a list.
+ * \param list the list
+ * \param node the node to unshift
+ */
+void
+list_unshift (list_t *list, list_node_t *node);
+
+/**
+ * Pop a node from the end of a list.
+ * \param list the list
+ * \return the popped node
+ */
+list_node_t *
+list_pop (list_t *list);
+
+/**
+ * Shift a node from the begin of a list.
+ * \param list the list
+ * \return the shifted node
+ */
+list_node_t *
+list_shift (list_t *list);
+
+/**
+ * Remove a node from a list.
+ * \param list the list
+ * \param node the node to remove
+ */
+void
+list_remove (list_t *list, list_node_t *node);
+
+/**
+ * Insert a node into a list.
+ * \param list the list
+ * \param before node before which to insert
+ * \param node node to insert
+ */
+void
+list_insert (list_t *list, list_node_t *before, list_node_t *node);
+
+/**
+ * Push a range [first, last) to a end of a list.
+ * \param to list to push to
+ * \param from list to remove from
+ * \param first first node to push
+ * \param last node after the last one to push
+ */
+void
+list_push_range (list_t *to, list_t *from,
+ list_node_t *first, list_node_t *last);
+
+/**
+ * Unshift a range [first, last) to a begin of a list.
+ * \param to list to unshift to
+ * \param from list to remove from
+ * \param first first node to unshift
+ * \param last node after the last one to unshift
+ */
+void
+list_unshift_range (list_t *to, list_t *from,
+ list_node_t *first, list_node_t *last);
+
+/**
+ * Insert a range [first, last) to a list
+ * \param to list to insert to
+ * \param from list to remove from
+ * \param before node before which to insert
+ * \param first first node to insert
+ * \param last node after the last one to insert
+ */
+void
+list_insert_range (list_t *to, list_t *from, list_node_t *before,
+ list_node_t *first, list_node_t *last);
+
+END_DECLS
+
+#endif /* lib_list_h */
diff --git a/cesar/lib/preproc.h b/cesar/lib/preproc.h
new file mode 100644
index 0000000000..d8fe82c5e8
--- /dev/null
+++ b/cesar/lib/preproc.h
@@ -0,0 +1,307 @@
+#ifndef lib_preproc_h
+#define lib_preproc_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/preproc.h
+ * \brief Preprocessor utilities.
+ * \ingroup lib
+ */
+
+/** Count the number of arguments. A very nice trick from Laurent Deniau, in
+ * <dqgm2f$ije$1@sunnews.cern.ch> on comp.std.c.
+ * Changed a little bit to handle zero arguments with gcc. */
+#define PREPROC_NARG(args...) \
+ PREPROC_NARG_(0, ## args, PREPROC_RSEQ_N())
+#define PREPROC_NARG_(...) \
+ PREPROC_ARG_N(__VA_ARGS__)
+#define PREPROC_ARG_N( _0, \
+ _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
+ _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
+ _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
+ _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
+ _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
+ _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
+ _61,_62,_63,N,...) N
+#define PREPROC_RSEQ_N() \
+ 63,62,61,60, \
+ 59,58,57,56,55,54,53,52,51,50, \
+ 49,48,47,46,45,44,43,42,41,40, \
+ 39,38,37,36,35,34,33,32,31,30, \
+ 29,28,27,26,25,24,23,22,21,20, \
+ 19,18,17,16,15,14,13,12,11,10, \
+ 9,8,7,6,5,4,3,2,1,0
+
+/** Paste two expanded arguments. */
+#define PASTE_EXPAND(a, b) PASTE (a, b)
+
+/** Paste two arguments without expansion. */
+#define PASTE(a, b) a ## b
+
+/** Reverse the list of arguments. */
+#define PREPROC_REVERSE(args...) \
+ PASTE_EXPAND (PREPROC_REVERSE_, PREPROC_NARG (args)) (args)
+
+#define PREPROC_REVERSE_0(t...)
+#define PREPROC_REVERSE_1(h, t...) h
+#define PREPROC_REVERSE_2(h, t...) PREPROC_REVERSE_1 (t), h
+#define PREPROC_REVERSE_3(h, t...) PREPROC_REVERSE_2 (t), h
+#define PREPROC_REVERSE_4(h, t...) PREPROC_REVERSE_3 (t), h
+#define PREPROC_REVERSE_5(h, t...) PREPROC_REVERSE_4 (t), h
+#define PREPROC_REVERSE_6(h, t...) PREPROC_REVERSE_5 (t), h
+#define PREPROC_REVERSE_7(h, t...) PREPROC_REVERSE_6 (t), h
+#define PREPROC_REVERSE_8(h, t...) PREPROC_REVERSE_7 (t), h
+#define PREPROC_REVERSE_9(h, t...) PREPROC_REVERSE_8 (t), h
+#define PREPROC_REVERSE_10(h, t...) PREPROC_REVERSE_9 (t), h
+#define PREPROC_REVERSE_11(h, t...) PREPROC_REVERSE_10 (t), h
+#define PREPROC_REVERSE_12(h, t...) PREPROC_REVERSE_11 (t), h
+#define PREPROC_REVERSE_13(h, t...) PREPROC_REVERSE_12 (t), h
+#define PREPROC_REVERSE_14(h, t...) PREPROC_REVERSE_13 (t), h
+#define PREPROC_REVERSE_15(h, t...) PREPROC_REVERSE_14 (t), h
+#define PREPROC_REVERSE_16(h, t...) PREPROC_REVERSE_15 (t), h
+#define PREPROC_REVERSE_17(h, t...) PREPROC_REVERSE_16 (t), h
+#define PREPROC_REVERSE_18(h, t...) PREPROC_REVERSE_17 (t), h
+#define PREPROC_REVERSE_19(h, t...) PREPROC_REVERSE_18 (t), h
+#define PREPROC_REVERSE_20(h, t...) PREPROC_REVERSE_19 (t), h
+#define PREPROC_REVERSE_21(h, t...) PREPROC_REVERSE_20 (t), h
+#define PREPROC_REVERSE_22(h, t...) PREPROC_REVERSE_21 (t), h
+#define PREPROC_REVERSE_23(h, t...) PREPROC_REVERSE_22 (t), h
+#define PREPROC_REVERSE_24(h, t...) PREPROC_REVERSE_23 (t), h
+#define PREPROC_REVERSE_25(h, t...) PREPROC_REVERSE_24 (t), h
+#define PREPROC_REVERSE_26(h, t...) PREPROC_REVERSE_25 (t), h
+#define PREPROC_REVERSE_27(h, t...) PREPROC_REVERSE_26 (t), h
+#define PREPROC_REVERSE_28(h, t...) PREPROC_REVERSE_27 (t), h
+#define PREPROC_REVERSE_29(h, t...) PREPROC_REVERSE_28 (t), h
+#define PREPROC_REVERSE_30(h, t...) PREPROC_REVERSE_29 (t), h
+#define PREPROC_REVERSE_31(h, t...) PREPROC_REVERSE_30 (t), h
+#define PREPROC_REVERSE_32(h, t...) PREPROC_REVERSE_31 (t), h
+
+/** Call macro for each argument. */
+#define PREPROC_FOR_EACH(macro, args...) \
+ PASTE_EXPAND (PREPROC_FOR_EACH_, PREPROC_NARG (args)) (macro, args)
+
+/* PREPROC_FOR_EACH_x {{{ */
+#define PREPROC_FOR_EACH_0(macro, t...)
+#define PREPROC_FOR_EACH_1(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_0 (macro, ## t)
+#define PREPROC_FOR_EACH_2(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_1 (macro, ## t)
+#define PREPROC_FOR_EACH_3(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_2 (macro, ## t)
+#define PREPROC_FOR_EACH_4(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_3 (macro, ## t)
+#define PREPROC_FOR_EACH_5(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_4 (macro, ## t)
+#define PREPROC_FOR_EACH_6(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_5 (macro, ## t)
+#define PREPROC_FOR_EACH_7(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_6 (macro, ## t)
+#define PREPROC_FOR_EACH_8(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_7 (macro, ## t)
+#define PREPROC_FOR_EACH_9(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_8 (macro, ## t)
+#define PREPROC_FOR_EACH_10(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_9 (macro, ## t)
+#define PREPROC_FOR_EACH_11(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_10 (macro, ## t)
+#define PREPROC_FOR_EACH_12(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_11 (macro, ## t)
+#define PREPROC_FOR_EACH_13(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_12 (macro, ## t)
+#define PREPROC_FOR_EACH_14(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_13 (macro, ## t)
+#define PREPROC_FOR_EACH_15(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_14 (macro, ## t)
+#define PREPROC_FOR_EACH_16(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_15 (macro, ## t)
+#define PREPROC_FOR_EACH_17(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_16 (macro, ## t)
+#define PREPROC_FOR_EACH_18(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_17 (macro, ## t)
+#define PREPROC_FOR_EACH_19(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_18 (macro, ## t)
+#define PREPROC_FOR_EACH_20(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_19 (macro, ## t)
+#define PREPROC_FOR_EACH_21(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_20 (macro, ## t)
+#define PREPROC_FOR_EACH_22(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_21 (macro, ## t)
+#define PREPROC_FOR_EACH_23(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_22 (macro, ## t)
+#define PREPROC_FOR_EACH_24(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_23 (macro, ## t)
+#define PREPROC_FOR_EACH_25(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_24 (macro, ## t)
+#define PREPROC_FOR_EACH_26(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_25 (macro, ## t)
+#define PREPROC_FOR_EACH_27(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_26 (macro, ## t)
+#define PREPROC_FOR_EACH_28(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_27 (macro, ## t)
+#define PREPROC_FOR_EACH_29(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_28 (macro, ## t)
+#define PREPROC_FOR_EACH_30(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_29 (macro, ## t)
+#define PREPROC_FOR_EACH_31(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_30 (macro, ## t)
+#define PREPROC_FOR_EACH_32(macro, h, t...) \
+ macro (h)PREPROC_FOR_EACH_31 (macro, ## t)
+/* }}} */
+
+/** Call macro for each argument, with an extra parameter. */
+#define PREPROC_FOR_EACH_PARAM(macro, param, args...) \
+ PASTE_EXPAND (PREPROC_FOR_EACH_PARAM_, \
+ PREPROC_NARG (args)) (macro, param, args)
+
+/* PREPROC_FOR_EACH_PARAM_x {{{ */
+#define PREPROC_FOR_EACH_PARAM_0(macro, param, t...)
+#define PREPROC_FOR_EACH_PARAM_1(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_0 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_2(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_1 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_3(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_2 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_4(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_3 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_5(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_4 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_6(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_5 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_7(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_6 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_8(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_7 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_9(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_8 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_10(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_9 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_11(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_10 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_12(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_11 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_13(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_12 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_14(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_13 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_15(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_14 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_16(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_15 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_17(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_16 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_18(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_17 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_19(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_18 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_20(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_19 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_21(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_20 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_22(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_21 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_23(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_22 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_24(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_23 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_25(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_24 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_26(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_25 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_27(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_26 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_28(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_27 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_29(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_28 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_30(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_29 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_31(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_30 (macro, param, ## t)
+#define PREPROC_FOR_EACH_PARAM_32(macro, param, h, t...) \
+ macro (param, h)PREPROC_FOR_EACH_PARAM_31 (macro, param, ## t)
+/* }}} */
+
+/** Call macro for each argument, with comma between calls. */
+#define PREPROC_FOR_EACH_COMMA(macro, args...) \
+ PASTE_EXPAND (PREPROC_FOR_EACH_COMMA_, PREPROC_NARG (args)) (macro, args)
+
+/* PREPROC_FOR_EACH_COMMA_x {{{ */
+#define PREPROC_FOR_EACH_COMMA_1(macro, h, t...) macro (h)
+#define PREPROC_FOR_EACH_COMMA_2(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_1 (macro, ## t)
+#define PREPROC_FOR_EACH_COMMA_3(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_2 (macro, ## t)
+#define PREPROC_FOR_EACH_COMMA_4(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_3 (macro, ## t)
+#define PREPROC_FOR_EACH_COMMA_5(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_4 (macro, ## t)
+#define PREPROC_FOR_EACH_COMMA_6(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_5 (macro, ## t)
+#define PREPROC_FOR_EACH_COMMA_7(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_6 (macro, ## t)
+#define PREPROC_FOR_EACH_COMMA_8(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_7 (macro, ## t)
+#define PREPROC_FOR_EACH_COMMA_9(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_8 (macro, ## t)
+#define PREPROC_FOR_EACH_COMMA_10(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_9 (macro, ## t)
+#define PREPROC_FOR_EACH_COMMA_11(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_10 (macro, ## t)
+#define PREPROC_FOR_EACH_COMMA_12(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_11 (macro, ## t)
+#define PREPROC_FOR_EACH_COMMA_13(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_12 (macro, ## t)
+#define PREPROC_FOR_EACH_COMMA_14(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_13 (macro, ## t)
+#define PREPROC_FOR_EACH_COMMA_15(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_14 (macro, ## t)
+#define PREPROC_FOR_EACH_COMMA_16(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_15 (macro, ## t)
+#define PREPROC_FOR_EACH_COMMA_17(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_16 (macro, ## t)
+#define PREPROC_FOR_EACH_COMMA_18(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_17 (macro, ## t)
+#define PREPROC_FOR_EACH_COMMA_19(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_18 (macro, ## t)
+#define PREPROC_FOR_EACH_COMMA_20(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_19 (macro, ## t)
+#define PREPROC_FOR_EACH_COMMA_21(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_20 (macro, ## t)
+#define PREPROC_FOR_EACH_COMMA_22(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_21 (macro, ## t)
+#define PREPROC_FOR_EACH_COMMA_23(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_22 (macro, ## t)
+#define PREPROC_FOR_EACH_COMMA_24(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_23 (macro, ## t)
+#define PREPROC_FOR_EACH_COMMA_25(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_24 (macro, ## t)
+#define PREPROC_FOR_EACH_COMMA_26(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_25 (macro, ## t)
+#define PREPROC_FOR_EACH_COMMA_27(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_26 (macro, ## t)
+#define PREPROC_FOR_EACH_COMMA_28(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_27 (macro, ## t)
+#define PREPROC_FOR_EACH_COMMA_29(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_28 (macro, ## t)
+#define PREPROC_FOR_EACH_COMMA_30(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_29 (macro, ## t)
+#define PREPROC_FOR_EACH_COMMA_31(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_30 (macro, ## t)
+#define PREPROC_FOR_EACH_COMMA_32(macro, h, t...) \
+ macro (h), PREPROC_FOR_EACH_COMMA_31 (macro, ## t)
+/* }}} */
+
+/** Remove parenthesis: (a, b, c) => a, b, c. */
+#define PREPROC_UNPACK(args...) \
+ PREPROC_UNPACK_ args
+
+#define PREPROC_UNPACK_(args...) \
+ PREPROC_FOR_EACH_COMMA (PREPROC_UNPACK__, ## args)
+#define PREPROC_UNPACK__(arg) arg
+
+#endif /* lib_preproc_h */
diff --git a/cesar/lib/python/Module b/cesar/lib/python/Module
new file mode 100644
index 0000000000..7bb2c04cf5
--- /dev/null
+++ b/cesar/lib/python/Module
@@ -0,0 +1,7 @@
+PYTHON_VERSION := $(shell for i in 2.5 2.4; do which python$$i-config > /dev/null && echo $$i && break; done)
+PYTHON_CONFIG := python$(PYTHON_VERSION)-config
+PYTHON_CFLAGS := $(shell $(PYTHON_CONFIG) --cflags)
+PYTHON_CPPFLAGS := $(filter -I%, $(PYTHON_CFLAGS))
+PYTHON_LDFLAGS := $(shell $(PYTHON_CONFIG) --ldflags) -lboost_python
+EXTRA_HOST_CPPFLAGS += $(PYTHON_CPPFLAGS)
+EXTRA_HOST_LDLIBS += $(PYTHON_LDFLAGS)
diff --git a/cesar/lib/python/test/pyhello/Makefile b/cesar/lib/python/test/pyhello/Makefile
new file mode 100644
index 0000000000..0846f1002c
--- /dev/null
+++ b/cesar/lib/python/test/pyhello/Makefile
@@ -0,0 +1,8 @@
+BASE = ../../../..
+
+HOST_PROGRAMS = hello.so
+hello.so_SOURCES = hello.cpp
+hello.so_MODULES = lib/python
+hello.so_LDLIBS = -fPIC -shared
+
+include $(BASE)/common/make/top.mk
diff --git a/cesar/lib/python/test/pyhello/py/test_hello.py b/cesar/lib/python/test/pyhello/py/test_hello.py
new file mode 100644
index 0000000000..ebdacc336e
--- /dev/null
+++ b/cesar/lib/python/test/pyhello/py/test_hello.py
@@ -0,0 +1,16 @@
+#! usr/bin/env python
+
+print __name__
+
+import sys
+sys.path.append('./obj')
+sys.path.append('../obj')
+
+import hello
+
+print hello.greet ("Tintin", "Belgium")
+
+h = hello.hello ("France")
+print h.greet ()
+print h.invite ()
+
diff --git a/cesar/lib/python/test/pyhello/src/hello.cpp b/cesar/lib/python/test/pyhello/src/hello.cpp
new file mode 100644
index 0000000000..bd766f7401
--- /dev/null
+++ b/cesar/lib/python/test/pyhello/src/hello.cpp
@@ -0,0 +1,41 @@
+#include <boost/python/class.hpp>
+#include <boost/python/module.hpp>
+#include <boost/python/def.hpp>
+#include <iostream>
+#include <string>
+
+namespace {
+
+ class hello
+ {
+ public:
+ hello(const std::string& country) { this->country = country; }
+ std::string greet() const { return "Hello from " + country; }
+ private:
+ std::string country;
+ };
+
+ std::string invite(const hello& w) {
+ return w.greet() + "! Please come soon!";
+ }
+
+ std::string greet(const std::string& name, const std::string& country) {
+ return "Hello " + name + " from " + country;
+ }
+}
+
+BOOST_PYTHON_MODULE(hello)
+{
+ using namespace boost::python;
+ class_<hello>("hello", init<std::string>())
+ // Add a regular member function.
+ .def("greet", &hello::greet)
+ // Add invite() as a member of hello!
+ .def("invite", invite)
+ ;
+
+ // Also add invite() as a regular function to the module.
+ def("invite", invite);
+
+ def("greet", greet);
+}
diff --git a/cesar/lib/read_word.h b/cesar/lib/read_word.h
new file mode 100644
index 0000000000..cb8e7bea4d
--- /dev/null
+++ b/cesar/lib/read_word.h
@@ -0,0 +1,126 @@
+#ifndef LIB_READ_WORD_H_
+#define LIB_READ_WORD_H_
+
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/read_word.h
+ * \brief Read a word from the memory aligned on an integer address.
+ * \ingroup lib
+ *
+ * Allows the system to get a value from the memory reading it word by word
+ * and returning the value request from the user.
+ *
+ * Exemple : we need to get a 4 bytes word from the address 503 on the
+ * memory it will calculate the address from the one it should start reading
+ * the data to be aligned.
+ * So it will read a word from the address 500 and the next one from the @
+ * 504, it will take the last byte of the first word and concatante it with
+ * the three bytes in the last word.
+ * result = word2 << 24 | word1
+ *
+ */
+
+/**
+ * Read the necessary words from the memory and return the data requested.
+ * Aware : if less than a word is request, it will need to be masqued to
+ * desable the bytes which are note necessary.
+ * Example : if you only need the two first bytes you should request:
+ * read_bytes_from_word (addr, 2) & 0xFFFF
+ */
+extern inline uint read_bytes_from_word (u8 *addr, uint bytes)
+{
+ u8* addr_new;
+ uint rest;
+ uint result;
+
+ uint word1;
+ uint word2;
+
+ dbg_assert (addr);
+ dbg_assert (bytes <= 4);
+
+ addr_new = (u8*) (((uint) addr) & ~3);
+ rest = (((uint) addr) & 3);
+
+ if (rest == 0)
+ {
+ result = *(u32*) (addr_new);
+ }
+ else if ((4-rest) >= bytes)
+ {
+ result = (*(u32*) (addr_new)) >> (8* rest);
+ }
+ else
+ {
+ word1 = (*(u32*) addr_new) >> (rest * 8);
+ word2 = (*(u32*) (addr_new + 4));
+
+ result = word2 << (4 - rest) * 8 | word1;
+ }
+
+ return result;
+}
+
+/**
+ * Read u64 from two words.
+ *
+ * \param addr the address to read the next two 48 bits.
+ * \return u64 masked on 48 bits.
+ */
+u64 read_u64_from_word (u8 *addr);
+
+/**
+ * Read u56 from two words.
+ *
+ * \param addr the address to read the next two 48 bits.
+ * \return u64 masked on 48 bits.
+ */
+u64 read_u56_from_word (u8 *addr);
+
+/**
+ * Read u48 from two words.
+ *
+ * \param addr the address to read the next two 48 bits.
+ * \return u64 masked on 48 bits.
+ */
+u64 read_u48_from_word (u8 *addr);
+
+/**
+ * Read 32 bits from the word.
+ *
+ * \param addr the address from the one the value should be read.
+ * \return the u32
+ */
+uint read_u32_from_word (u8 *addr);
+
+/**
+ * Read 24 bits from the word.
+ *
+ * \param addr the address from the one the value should be read.
+ * \return the u32 with the last byte set to 0
+ */
+uint read_u24_from_word (u8 *addr);
+
+/**
+ * Read 16 bits from the word.
+ *
+ * \param addr the address from the one the value should be read.
+ * \return the u32 with the last byte set to 0
+ */
+uint read_u16_from_word (u8 *addr);
+
+/**
+ * Read 8 bits from the word.
+ *
+ * \param addr the address from the one the value should be read.
+ * \return uint with only one byte filled.
+ */
+uint read_u8_from_word (u8 *addr);
+
+#endif /*LIB_READ_WORD_H_*/
diff --git a/cesar/lib/restrack.h b/cesar/lib/restrack.h
new file mode 100644
index 0000000000..af530583b8
--- /dev/null
+++ b/cesar/lib/restrack.h
@@ -0,0 +1,137 @@
+#ifndef restrack_h
+#define restrack_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/restrack.h
+ * \brief Resources tracker.
+ * \ingroup lib
+ *
+ * The resources tracker is a debugging tool to trace resources allocations
+ * and releases.
+ *
+ * It provides services to track resources references with two flavors.
+ *
+ * The first one and simpler one (lite) will record all the places where
+ * allocations and releases are done during the whole resource life time.
+ * This flavor can not determine current resource owner because it can not
+ * associate the source line recorded with the owner.
+ *
+ * The second flavor (full) will request an extra argument for each allocation
+ * and release. This argument is an owner of the resources. This flavor can
+ * track much more errors as it can detect wrong releases and will bark if a
+ * resources is freed while it still own other resources.
+ *
+ * At any time, the user can check for unbalanced resources allocations or
+ * releases.
+ *
+ * Use CONFIG_RESTRACK to enable Resources tracker.
+ *
+ * Use CONFIG_RESTRACK_KEEP to keep records of destructed resources (not safe,
+ * but may be useful for debug in some cases).
+ */
+
+#include "config/restrack.h"
+
+/* Macro helpers. */
+#if CONFIG_RESTRACK
+
+# define _FL const char *function, int line
+# define void_FL _FL
+# define __FL , _FL
+# define _fL __func__, __LINE__
+# define __fL , _fL
+# define _fl function, line
+# define __fl , _fl
+# define _fl_ function, line
+
+#else /* !CONFIG_RESTRACK */
+
+# define _FL
+# define void_FL void
+# define __FL
+# define _fL
+# define __fL
+# define _fl
+# define __fl
+# define _fl_ NULL, 0
+
+#endif /* !CONFIG_RESTRACK */
+
+#if CONFIG_RESTRACK
+
+BEGIN_DECLS
+
+/**
+ * Create a resource reference counter.
+ * \param owner owner of the resource, ignored for the lite flavor
+ * \param resource resource referenced
+ * \param function function name (__func__)
+ * \param line source line
+ * \param initial reference counter initial value
+ */
+void
+restrack_create (void *owner, void *resource, const char *function, int line,
+ int initial);
+
+/**
+ * Update a resource reference counter.
+ * \param owner owner of the resource, ignored for the lite flavor
+ * \param resource resource referenced
+ * \param function function name (__func__)
+ * \param line source line
+ * \param change reference counter change
+ */
+void
+restrack_update (void *owner, void *resource, const char *function, int line,
+ int change);
+
+/**
+ * Destroy a resource reference counter.
+ * \param owner owner of the resource, ignored for the lite flavor
+ * \param resource resource referenced
+ * \param function function name (__func__)
+ * \param line source line
+ * \param change reference counter change
+ *
+ * Will check if the counter reaches zero.
+ */
+void
+restrack_destroy (void *owner, void *resource, const char *function, int line,
+ int change);
+
+/**
+ * Check that the current state of resources allocations is balanced.
+ * \return true if no unbalanced resource.
+ *
+ * Will output statistics for any unbalanced resources.
+ */
+bool
+restrack_check (void);
+
+/**
+ * Free all memory used by the Resources Tracker.
+ *
+ * Useful for memory leaks analysis. Called automatically on exit.
+ */
+void
+restrack_uninit (void);
+
+END_DECLS
+
+#else /* !CONFIG_RESTRACK */
+
+# define restrack_create(...) ((void) 0)
+# define restrack_update(...) ((void) 0)
+# define restrack_destroy(...) ((void) 0)
+# define restrack_check() true
+# define restrack_uninit() ((void) 0)
+
+#endif /* !CONFIG_RESTRACK */
+
+#endif /* restrack_h */
diff --git a/cesar/lib/rnd.h b/cesar/lib/rnd.h
new file mode 100644
index 0000000000..222617a462
--- /dev/null
+++ b/cesar/lib/rnd.h
@@ -0,0 +1,56 @@
+#ifndef lib_rnd_h
+#define lib_rnd_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/rnd.h
+ * \brief Random Number Generator header.
+ * \ingroup lib
+ */
+
+/** Random number generator context. */
+struct lib_rnd_t
+{
+#define LIB_MT_N 624
+ unsigned long state[LIB_MT_N];
+ int state_index;
+};
+typedef struct lib_rnd_t lib_rnd_t;
+
+/** Generate a integer which has a probability of \a prob to be greater than a
+ * random 32 bit integer. Works with 0.0 <= \a prob < 1.0. */
+#define LIB_RND_RATIO(prob) ((u32) ((1ull << 32) * (prob)))
+
+BEGIN_DECLS
+
+void
+lib_rnd_init (lib_rnd_t *ctx, u32 seed);
+void
+lib_rnd_init_by_array (lib_rnd_t *ctx, const u32 init_key[], int key_length);
+u32
+lib_rnd32 (lib_rnd_t *ctx);
+uint
+lib_rnd_uniform (lib_rnd_t *ctx, uint bound);
+void
+lib_rnd_buffer (lib_rnd_t *ctx, u8 *buf, uint buf_size);
+
+/**
+ * Return true with the wanted probability.
+ * \param ctx the rnd context
+ * \param prob probability integer returned by LIB_RND_RATIO
+ * \return true when lib_rnd32() < \p prob
+ */
+extern inline bool
+lib_rnd_flip_coin (lib_rnd_t *ctx, u32 prob)
+{
+ return lib_rnd32 (ctx) < prob;
+}
+
+END_DECLS
+
+#endif /* lib_rnd_h */
diff --git a/cesar/lib/set.h b/cesar/lib/set.h
new file mode 100644
index 0000000000..97f5353631
--- /dev/null
+++ b/cesar/lib/set.h
@@ -0,0 +1,48 @@
+#ifndef lib_set_h
+#define lib_set_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/set.h
+ * \brief Set of ordered data service.
+ * \ingroup lib
+ *
+ * A set is a ordered binary tree structure.
+ *
+ * It defines the following set of operations efficiently:
+ * - insert an element,
+ * - find an element,
+ * - remove an element,
+ * - travel the set in order.
+ */
+
+/* Forward declaration. */
+typedef struct set_node_t set_node_t;
+
+/**
+ * Set node comparison function pointer.
+ * \param left left hand node
+ * \param right right hand node
+ * \return true iff left is lesser than right
+ */
+typedef bool
+(*set_node_less_t) (set_node_t *left, set_node_t *right);
+
+/** Set structure. */
+struct set_t
+{
+ /** Set root node. */
+ set_node_t *root;
+ /** Set "is lesser than" comparison function. */
+ set_node_less_t less;
+};
+typedef struct set_t set_t;
+
+#include "lib/aatree.h"
+
+#endif /* lib_set_h */
diff --git a/cesar/lib/skewheap.h b/cesar/lib/skewheap.h
new file mode 100644
index 0000000000..ad095f43a5
--- /dev/null
+++ b/cesar/lib/skewheap.h
@@ -0,0 +1,78 @@
+#ifndef lib_skewheap_h
+#define lib_skewheap_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/skewheap.h
+ * \brief Skew heaps.
+ * \ingroup lib
+ *
+ * Skew heaps were invented by Daniel Dominic Sleator and Robert Endre Tarjan.
+ * Skew heaps do not define any constrain on the tree structure. All
+ * operations should use the skew merge.
+ *
+ * The skew merge operation merges the right paths of the two heaps to be
+ * merged and swap all right and left children. The idea is that the right
+ * path will be long after a merge.
+ */
+
+/** Heap node. */
+struct heap_node_t
+{
+ /** Pointer to parrent node. */
+ struct heap_node_t *father;
+ /** Pointer to left and right children. */
+ struct heap_node_t *left, *right;
+};
+
+BEGIN_DECLS
+
+/**
+ * Initialise an heap node.
+ * \param node the node to initialise
+ */
+void
+heap_node_init (heap_node_t *node);
+
+/**
+ * Merge two heaps rooted at the given nodes.
+ * \param root1 the first heap root
+ * \param root2 the second heap root (surprise!)
+ * \param less comparison function
+ * \return the new root node.
+ */
+heap_node_t *
+heap_node_merge (heap_node_t *root1, heap_node_t *root2,
+ heap_node_less_t less);
+
+/**
+ * Insert a new node in the given heap.
+ * \param heap the heap
+ * \param node the node to insert
+ */
+void
+heap_insert (heap_t *heap, heap_node_t *node);
+
+/**
+ * Remove the heap root.
+ * \param heap the heap
+ */
+void
+heap_remove_root (heap_t *heap);
+
+/**
+ * Remove an arbitrary element
+ * \param heap the heap
+ * \param node the node to remove
+ */
+void
+heap_remove (heap_t *heap, heap_node_t *node);
+
+END_DECLS
+
+#endif /* lib_skewheap_h */
diff --git a/cesar/lib/src/aatree.c b/cesar/lib/src/aatree.c
new file mode 100644
index 0000000000..d58085a1f8
--- /dev/null
+++ b/cesar/lib/src/aatree.c
@@ -0,0 +1,312 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/src/aatree.c
+ * \brief Arne Andersson Trees.
+ * \ingroup lib
+ */
+#include "common/std.h"
+
+#include "lib/set.h"
+
+/** The NIL node, which loops to itself. */
+static set_node_t aatree_nil =
+{
+ NULL, &aatree_nil, &aatree_nil, 0
+};
+
+/** Pointer to the NIL node. */
+#define NIL (&aatree_nil)
+
+/**
+ * Skew operation, eliminate horizontal left edge, non recursive.
+ * \param nodep upper node pointer
+ */
+extern inline void
+aatree_skew (set_node_t **nodep)
+{
+ /*
+ * If l.level == r.level, they are the same pseudo-node and r left link is
+ * horizontal. This is forbidden.
+ *
+ * \ \
+ * r l
+ * / \ => / \
+ * l 3 1 r
+ * / \ / \
+ * 1 2 2 3
+ */
+ set_node_t *r, *l;
+ r = *nodep;
+ l = r->left;
+ if (l->level == r->level)
+ {
+ *nodep = l;
+ l->father = r->father;
+ r->left = l->right;
+ if (r->left != NIL)
+ r->left->father = r;
+ l->right = r;
+ r->father = l;
+ }
+}
+
+/**
+ * Split operation, split a too large pseudo-node.
+ * \param nodep upper node pointer
+ */
+extern inline void
+aatree_split (set_node_t **nodep)
+{
+ /*
+ * If l.level == r.level, the pseudo-node is too large, slit it.
+ *
+ * \ \
+ * l m
+ * / \ _/ \_
+ * 1 m => l r
+ * / \ / \ / \
+ * 2 r 1 2 3 4
+ * / \
+ * 3 4
+ */
+ set_node_t *r, *m, *l;
+ l = *nodep;
+ m = l->right;
+ r = m->right;
+ if (l->level == r->level)
+ {
+ *nodep = m;
+ m->father = l->father;
+ l->right = m->left;
+ if (l->right != NIL)
+ l->right->father = l;
+ m->left = l;
+ l->father = m;
+ m->level++;
+ }
+}
+
+void
+set_init (set_t *set, set_node_less_t less)
+{
+ dbg_assert (set);
+ set->root = NIL;
+ set->less = less;
+}
+
+void
+set_node_init (set_node_t *node)
+{
+ dbg_assert (node);
+ node->father = NULL;
+ node->left = node->right = NULL;
+ node->level = 0;
+}
+
+set_node_t *
+set_find (set_t *set, set_node_t *node)
+{
+ /* Use the two-way comparison optimisation from "A. Andersson. A note on
+ * searching in a binary search tree". */
+ set_node_t *p, *candidate;
+ dbg_assert (set);
+ dbg_assert (node && node->level == 0);
+ p = set->root;
+ candidate = NULL;
+ while (p != NIL)
+ {
+ if (set->less (node, p))
+ {
+ p = p->left;
+ }
+ else
+ {
+ candidate = p;
+ p = p->right;
+ }
+ }
+ if (candidate && !set->less (candidate, node))
+ return candidate;
+ else
+ return NULL;
+}
+
+bool
+set_insert (set_t *set, set_node_t *node)
+{
+ set_node_t *father, *candidate, **np, *up;
+ dbg_assert (set);
+ dbg_assert (node && node->level == 0);
+ /* Go down, from root. */
+ father = NULL;
+ np = &set->root;
+ candidate = NULL;
+ while (*np != NIL)
+ {
+ father = *np;
+ dbg_assert_print (father != node, "node is in the set yet");
+ if (set->less (node, father))
+ {
+ np = &father->left;
+ }
+ else
+ {
+ candidate = father;
+ np = &father->right;
+ }
+ }
+ /* Refuse to add a node equal to another node. */
+ if (candidate && !set->less (candidate, node))
+ return false;
+ /* Add the new node in np. */
+ *np = node;
+ node->father = father;
+ node->left = node->right = NIL;
+ node->level = 1;
+ /* Go up. */
+ while (father)
+ {
+ up = father->father;
+ if (!up)
+ np = &set->root;
+ else if (up->right == father)
+ np = &up->right;
+ else
+ np = &up->left;
+ father = up;
+ aatree_skew (np);
+ aatree_split (np);
+ }
+ return true;
+}
+
+void
+set_remove (set_t *set, set_node_t *node)
+{
+ set_node_t *heir, **np, *up;
+ dbg_assert (set);
+ dbg_assert (node && node != NIL && node->level != 0);
+ /* Find node pointer. */
+ if (!node->father)
+ np = &set->root;
+ else if (node->father->left == node)
+ np = &node->father->left;
+ else
+ np = &node->father->right;
+ /* Find the heir node (the leaf node which will replace the removed node
+ * in the tree). */
+ if (node->left == NIL)
+ {
+ *np = node->right;
+ up = node->father;
+ if (node->right != NIL)
+ node->right->father = up;
+ }
+ else if (node->right == NIL)
+ {
+ dbg_assert (node->left == NIL && node->level == 1);
+ *np = NIL;
+ up = node->father;
+ }
+ else
+ {
+ for (heir = node->left; heir->right != NIL; heir = heir->right)
+ ;
+ /* The heir node can not have a left child because it does not have a
+ * right child. Why:
+ * heir->right == NIL => heir->right->level == 0 => heir->level = 1
+ * heir->left != NIL => heir->left->level >= 1 => horizontal left link
+ * forbidden! */
+ dbg_assert (heir->left == NIL && heir->level == 1);
+ if (heir != node->left)
+ {
+ heir->father->right = NIL;
+ up = heir->father;
+ heir->left = node->left;
+ heir->left->father = heir;
+ }
+ else
+ {
+ up = heir;
+ }
+ heir->father = node->father;
+ heir->right = node->right;
+ heir->right->father = heir;
+ heir->level = node->level;
+ *np = heir;
+ }
+ /* Go up and rebalance. */
+ while (up)
+ {
+ if (!up->father)
+ np = &set->root;
+ else if (up->father->right == up)
+ np = &up->father->right;
+ else
+ np = &up->father->left;
+ /* Rebalance. */
+ if (up->left->level < up->level - 1
+ || up->right->level < up->level - 1)
+ {
+ up->level--;
+ if (up->right->level > up->level)
+ up->right->level = up->level;
+ aatree_skew (np);
+ if ((*np)->right != NIL)
+ aatree_skew (&(*np)->right);
+ if ((*np)->right->right != NIL)
+ aatree_skew (&(*np)->right->right);
+ aatree_split (np);
+ if ((*np)->right != NIL)
+ aatree_split (&(*np)->right);
+ }
+ /* Next. */
+ up = up->father;
+ }
+ node->father = NULL;
+ node->left = node->right = NULL;
+ node->level = 0;
+}
+
+set_node_t *
+set_begin (set_t *set)
+{
+ set_node_t *n;
+ dbg_assert (set);
+ /* First node is far on the left. */
+ for (n = set->root; n->left != NIL; n = n->left)
+ ;
+ return n != NIL ? n : NULL;
+}
+
+set_node_t *
+set_next (set_t *set, set_node_t *node)
+{
+ set_node_t *n, *nc;
+ dbg_assert (set);
+ dbg_assert (node && node != NIL && node->level != 0);
+ n = node;
+ if (n->right != NIL)
+ {
+ /* If there is a right subtree, find its minimal node. */
+ for (n = n->right; n->left != NIL; n = n->left)
+ ;
+ }
+ else
+ {
+ /* Else, go up until we come from left. */
+ do
+ {
+ nc = n;
+ n = n->father;
+ } while (n && n->right == nc);
+ }
+ return n;
+}
+
diff --git a/cesar/lib/src/atox.c b/cesar/lib/src/atox.c
new file mode 100644
index 0000000000..9dd8160710
--- /dev/null
+++ b/cesar/lib/src/atox.c
@@ -0,0 +1,383 @@
+/**{{{
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ }}}*/
+/**
+ * \file lib/src/atox.c
+ * \brief ASCII string convertions
+ * \ingroup lib
+ */
+#include "lib/atox.h"
+
+#define LONG_MAX 2147483647L
+#define LONG_MIN (-LONG_MAX-1)
+#define LONG_LONG_MAX 9223372036854775807LL
+#define LONG_LONG_MIN (-LONG_LONG_MAX-1)
+#define ULONG_MAX (LONG_MAX * 2UL + 1)
+#define ULONG_LONG_MAX (LONG_LONG_MAX * 2ULL + 1)
+
+static inline int isupper(int c)
+{
+ return (('A' <= c) && (c <= 'Z'));
+} //isupper
+
+static inline int islower(int c)
+{
+ return (('a' <= c) && (c <= 'z'));
+} //islower
+
+static inline int isalpha(int c)
+{
+ return ( islower(c) || isupper(c) );
+} //isalpha
+
+static inline int isdigit(int c)
+{
+ return ( ('0' <= c) && (c <= '9') );
+} //isdigit
+
+static inline int isspace(int c)
+{
+ return ( (c == ' ') || (c == '\f') || (c == '\n') || (c == '\r') ||
+ (c == '\t') || (c == '\v') );
+} //isspace
+
+static unsigned long long strtoull(const char *nptr, char **endptr, int base)
+{
+ const char *s = nptr;
+ unsigned long long acc;
+ int c;
+ unsigned long long cutoff;
+ int neg = 0, any, cutlim;
+
+ if (endptr != 0)
+ return -1;
+ //
+ // See strtoll for comments as to the logic used.
+ //
+ do {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else if (c == '+')
+ c = *s++;
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+ cutoff = (unsigned long long)ULONG_LONG_MAX / (unsigned long long)base;
+ cutlim = (unsigned long long)ULONG_LONG_MAX % (unsigned long long)base;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if ((any < 0) || (acc > cutoff) || ((acc == cutoff) && (c > cutlim)))
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = ULONG_LONG_MAX;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = (char *) (any ? s - 1 : nptr);
+
+ return acc;
+} //strtoull
+
+unsigned long strtoul(const char *nptr, char **endptr, int base)
+{
+ const char *s = nptr;
+ unsigned long acc;
+ int c;
+ unsigned long cutoff;
+ int neg = 0, any, cutlim;
+
+ if (endptr != 0)
+ return -1;
+ //
+ // See strtol for comments as to the logic used.
+ //
+ do {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else if (c == '+')
+ c = *s++;
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+ cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
+ cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if ((any < 0) || (acc > cutoff) || ((acc == cutoff) && (c > cutlim)))
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = ULONG_MAX;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = (char *) (any ? s - 1 : nptr);
+
+ return acc;
+} //strtoul
+
+long long strtoll(const char *nptr, char **endptr, int base)
+{
+ const char *s = nptr;
+ unsigned long long acc;
+ int c;
+ unsigned long long cutoff;
+ int neg = 0, any, cutlim;
+
+ if (endptr != 0)
+ return -1;
+
+ //
+ // Skip white space and pick up leading +/- sign if any.
+ // If base is 0, allow 0x for hex and 0 for octal, else
+ // assume decimal; if base is already 16, allow 0x.
+ //
+
+ do {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else if (c == '+')
+ c = *s++;
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+
+ //
+ // Compute the cutoff value between legal numbers and illegal
+ // numbers. That is the largest legal value, divided by the
+ // base. An input number that is greater than this value, if
+ // followed by a legal input character, is too big. One that
+ // is equal to this value may be valid or not; the limit
+ // between valid and invalid numbers is then based on the last
+ // digit. For instance, if the range for long longs is
+ // [-2147483648..2147483647] and the input base is 10,
+ // cutoff will be set to 214748364 and cutlim to either
+ // 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
+ // a value > 214748364, or equal but the next digit is > 7 (or 8),
+ // the number is too big, and we will return a range error.
+ //
+ // Set any if any `digits' consumed; make it negative to indicate
+ // overflow.
+ //
+
+ cutoff = neg ? -(unsigned long long)LONG_LONG_MIN : LONG_LONG_MAX;
+ cutlim = cutoff % (unsigned long long)base;
+ cutoff /= (unsigned long long)base;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if ((any < 0) || (acc > cutoff) || ((acc == cutoff) && (c > cutlim)))
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = neg ? LONG_LONG_MIN : LONG_LONG_MAX;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = (char *) (any ? s - 1 : nptr);
+
+ return acc;
+} // strtoll()
+
+static long strtol(const char *nptr, char **endptr, int base)
+{
+ const char *s = nptr;
+ unsigned long acc;
+ int c;
+ unsigned long cutoff;
+ int neg = 0, any, cutlim;
+
+ if (endptr != 0)
+ return -1;
+
+ //
+ // Skip white space and pick up leading +/- sign if any.
+ // If base is 0, allow 0x for hex and 0 for octal, else
+ // assume decimal; if base is already 16, allow 0x.
+ //
+
+ do {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else if (c == '+')
+ c = *s++;
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+
+ //
+ // Compute the cutoff value between legal numbers and illegal
+ // numbers. That is the largest legal value, divided by the
+ // base. An input number that is greater than this value, if
+ // followed by a legal input character, is too big. One that
+ // is equal to this value may be valid or not; the limit
+ // between valid and invalid numbers is then based on the last
+ // digit. For instance, if the range for longs is
+ // [-2147483648..2147483647] and the input base is 10,
+ // cutoff will be set to 214748364 and cutlim to either
+ // 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
+ // a value > 214748364, or equal but the next digit is > 7 (or 8),
+ // the number is too big, and we will return a range error.
+ //
+ // Set any if any `digits' consumed; make it negative to indicate
+ // overflow.
+ //
+
+ cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
+ cutlim = cutoff % (unsigned long)base;
+ cutoff /= (unsigned long)base;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if ((any < 0) || (acc > cutoff) || ((acc == cutoff) && (c > cutlim)))
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = neg ? LONG_MIN : LONG_MAX;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = (char *) (any ? s - 1 : nptr);
+
+ return acc;
+} //strtol
+
+int atoi(const char *nptr)
+{
+ int retval;
+
+ retval = (int) strtol(nptr, (char **)0, 10);
+
+ return retval;
+} //atoi
+
+
+long atol(const char *nptr)
+{
+ long retval;
+
+ retval = strtol(nptr, (char **)0, 10);
+
+ return retval;
+} //atol
+
+long long atoll(const char *nptr)
+{
+ long long retval;
+
+ retval = strtoll(nptr, (char **)0, 10);
+
+ return retval;
+} //atoll
+
+unsigned long atoul(const char *nptr)
+{
+ unsigned long retval;
+
+ retval = strtoul(nptr, (char **)0, 10);
+
+ return retval;
+} //atoul
+
+unsigned long long atoull(const char *nptr)
+{
+ unsigned long long retval;
+
+ retval = strtoull(nptr, (char **)0, 10);
+
+ return retval;
+} //atoull
+
diff --git a/cesar/lib/src/bitstream.c b/cesar/lib/src/bitstream.c
new file mode 100644
index 0000000000..b6d783fc6a
--- /dev/null
+++ b/cesar/lib/src/bitstream.c
@@ -0,0 +1,394 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/src/bitstream.c
+ * \brief Bit stream access using word access.
+ * \ingroup lib
+ */
+#include "common/std.h"
+
+#include "lib/bitstream.h"
+#include "lib/swap.h"
+
+static u32
+bitstream_rol32 (u32 val, uint n)
+{
+ return (n == bitsizeof (u32) ? 0x0 : (val << n));
+}
+
+static uint
+bitstream_read (bitstream_t *ctx, u32 *value, uint nb_bit)
+{
+ uint ret = 0;
+ u32 buf, mask, x;
+
+ for(buf = 0; nb_bit; nb_bit -= x, ret += x)
+ {
+ /* x is bits_left_in_ctx_buf or nb_bit */
+ x = MIN ((bitsizeof(ctx->buf) - ctx->bit_offset), nb_bit);
+ /* create bitmask */
+ mask = bitstream_rol32 (1ul, x) - 1;
+ /* fill local buf */
+ buf |= (((ctx->buf >> ctx->bit_offset) & mask) << ret);
+
+ if(x < nb_bit)
+ {
+ /* not enough bits in ctx->buf, get next word */
+ ctx->buf = *ctx->stream++;
+ ctx->bit_offset = 0;
+ /* if no more bits are available */
+ if(!bitstream_available_bits (ctx))
+ break;
+ }else
+ /* move ctx bit offset forward */
+ ctx->bit_offset += x;
+ }
+
+ *value = buf;
+ return ret;
+}
+
+static uint
+bitstream_write (bitstream_t *ctx, u32 *value, uint nb_bit)
+{
+ u32 mask, x;
+ uint ret = 0;
+
+ for(; nb_bit; nb_bit -= x, ret += x)
+ {
+ /* x is bits_left_in_ctx_buf or nb_bit */
+ x = MIN ((bitsizeof(ctx->buf) - ctx->bit_offset), nb_bit);
+ /* create bitmask */
+ mask = bitstream_rol32 (1ul, x) - 1;
+ /* fill ctx buf */
+ ctx->buf |= (((*value >> ret) & mask) << ctx->bit_offset);
+
+ if(x < nb_bit)
+ {
+ /* Write ctx buf to stream */
+ *ctx->stream++ = ctx->buf;
+ ctx->bit_offset = 0;
+ ctx->buf = 0;
+ /* if no more bits are available */
+ if(!bitstream_available_bits (ctx))
+ break;
+ }
+ else
+ /* move ctx bit offset forward */
+ ctx->bit_offset += x;
+ }
+
+ return ret;
+}
+
+void
+bitstream_init (bitstream_t *ctx, void *data, uint nb_bytes,
+ bitstream_type_t type)
+{
+ ctx->start = (u8*)data;
+
+ /* ensure 32-bit alignment */
+ ctx->stream = (u32*)((u8*)data - ((u32)data & 0x03));
+ ctx->bit_offset = ((u32)data & 0x03) * 8;
+ ctx->buf = ((1ul << ctx->bit_offset) - 1) & *ctx->stream;
+
+ ctx->nb_bytes = nb_bytes;
+ ctx->type = type;
+
+ /* In read mode, load first word */
+ if(ctx->type == BITSTREAM_READ)
+ ctx->buf = *ctx->stream++;
+}
+
+uint
+bitstream_finalise (bitstream_t *ctx)
+{
+ if(ctx->type == BITSTREAM_WRITE
+ && ctx->bit_offset)
+ {
+ /* In write mode, write last buffered word */
+ /* create bitmask */
+ u32 mask = ~(bitstream_rol32 (1ul, ctx->bit_offset) - 1);
+ /* write last word */
+ *ctx->stream = (*ctx->stream & mask) | ctx->buf;
+ return ctx->bit_offset;
+ }
+
+ return 0;
+}
+
+uint
+bitstream_available_bits (bitstream_t *ctx)
+{
+ dbg_assert (ctx);
+
+ uint n = (((u32)ctx->stream <= ((u32)ctx->start + ctx->nb_bytes))
+ ? ((((u32)ctx->start + ctx->nb_bytes) - (u32)(ctx->stream)) * 8)
+ : 0x00000000);
+
+ return (ctx->type == BITSTREAM_READ
+ ? n + (bitsizeof(ctx->buf) - ctx->bit_offset)
+ : n - ctx->bit_offset);
+}
+
+uint
+bitstream_access_8 (bitstream_t *ctx, void *value, uint nb_bit)
+{
+ dbg_assert (ctx);
+ dbg_assert (nb_bit <= 8);
+
+ u32 buf;
+ uint ret;
+
+ if(ctx->type == BITSTREAM_READ)
+ {
+ ret = bitstream_read (ctx, &buf, nb_bit);
+ *(u8*)value = 0xff & buf;
+ return ret;
+ }
+ else
+ {
+ buf = *(u8*)value;
+ return bitstream_write (ctx, &buf, nb_bit);
+ }
+}
+
+uint
+bitstream_access_16 (bitstream_t *ctx, void *value, uint nb_bit)
+{
+ dbg_assert (ctx);
+ dbg_assert (nb_bit <= 16);
+
+ u32 buf;
+ uint ret;
+
+ if(ctx->type == BITSTREAM_READ)
+ {
+ ret = bitstream_read (ctx, &buf, nb_bit);
+ *(u16*)value = 0xffff & buf;
+ return ret;
+ }
+ else
+ {
+ buf = *(u16*)value;
+ return bitstream_write (ctx, &buf, nb_bit);
+ }
+}
+
+uint
+bitstream_access_32 (bitstream_t *ctx, void *value, uint nb_bit)
+{
+ dbg_assert (ctx);
+ dbg_assert (nb_bit <= 32);
+
+ u32 buf;
+ uint ret;
+
+ if(ctx->type == BITSTREAM_READ)
+ {
+ ret = bitstream_read (ctx, &buf, nb_bit);
+ *(u32*)value = buf;
+ return ret;
+ }
+ else
+ {
+ buf = *(u32*)value;
+ return bitstream_write (ctx, &buf, nb_bit);
+ }
+}
+
+uint
+bitstream_access_64 (bitstream_t *ctx, void *value, uint nb_bit)
+{
+ dbg_assert (ctx);
+ dbg_assert (nb_bit <= 64);
+
+ u64 val;
+ u32 buf = 0;
+ uint ret = 0, x;
+
+ if(ctx->type == BITSTREAM_READ)
+ {
+ for(val = 0; nb_bit; nb_bit -= x, ret += x)
+ {
+ x = MIN (bitsizeof(buf), nb_bit);
+ bitstream_read (ctx, &buf, x);
+ val |= (u64)buf << ret;
+ }
+
+ *(u64*)value = val;
+ }
+ else
+ {
+ for(val = *(u64*)value; nb_bit; nb_bit -= x, ret += x)
+ {
+ x = MIN (bitsizeof(buf), nb_bit);
+ buf = (0xffffffff & (val >> ret));
+ bitstream_write (ctx, &buf, x);
+ }
+ }
+
+ return ret;
+}
+
+/* Direct access ops */
+
+uint
+bitstream_direct_read (void *data, uint bit_offset, uint nb_bit)
+{
+ u32 *stream;
+ uint ret = 0;
+ u32 buf, mask, x, y = 0;
+
+ /* ensure 32-bit alignment */
+ data = (u32*)data + (bit_offset >> 5);
+ stream = (u32*)((u8*)data - ((u32)data & 0x03));
+ bit_offset = ((u32)data & 0x03) * 8 + (bit_offset & 0x1f);
+
+ dbg_assert (nb_bit <= 32);
+
+ for(; nb_bit; nb_bit -= x, y += x, bit_offset += x)
+ {
+ /* bit_offset mod bitsizeof (buf) */
+ bit_offset &= (bitsizeof (buf) - 1);
+ /* direct access to buf */
+ buf = *stream++;
+ /* x is bits_left_in_local_buf or nb_bit */
+ x = MIN ((bitsizeof(buf) - bit_offset), nb_bit);
+ /* create bitmask */
+ mask = bitstream_rol32 (1ul, x) - 1;
+ /* set return value */
+ ret |= ((((buf >> bit_offset) & mask) << y));
+ }
+
+ return ret;
+}
+
+u64
+bitstream_direct_read_large (u8 *data, uint bit_offset, uint nb_bit)
+{
+ u64 ret;
+ u32 buf, x, y = 0;
+
+ dbg_assert (nb_bit <= 64);
+
+ for(ret = 0; nb_bit; nb_bit -= x, bit_offset += x, y += x)
+ {
+ x = MIN (bitsizeof(buf), nb_bit);
+ buf = bitstream_direct_read (data, bit_offset, x);
+ ret |= (u64)buf << y;
+ }
+
+ return ret;
+}
+
+void
+bitstream_direct_write (void *data, uint bit_offset, uint value, uint nb_bit)
+{
+ u32 *stream;
+ u32 buf, mask, x, y = 0;
+
+ dbg_assert (nb_bit <= 32);
+
+ /* ensure 32-bit alignment */
+ data = (u32*)data + (bit_offset >> 5);
+ stream = (u32*)((u8*)data - ((u32)data & 0x03));
+ bit_offset = ((u32)data & 0x03) * 8 + (bit_offset & 0x1f);
+
+ for(buf = 0; nb_bit; nb_bit -= x, y += x, bit_offset += x)
+ {
+ /* bit_offset mod bitsizeof (buf) */
+ bit_offset &= (bitsizeof (buf) - 1);
+ /* x is bits_left_in_local_buf or nb_bit */
+ x = MIN ((bitsizeof(buf) - bit_offset), nb_bit);
+ /* create bitmask */
+ mask = bitstream_rol32 (1ul, x) - 1;
+ /* fill local buf */
+ buf |= (((value >> y) & mask) << bit_offset);
+
+ /* direct access to stream */
+ *stream = (*stream & ~(mask << bit_offset)) | buf;
+ stream++;
+ buf = 0;
+ }
+}
+
+void
+bitstream_direct_write_large (u8 *data, uint bit_offset, u64 value,
+ uint nb_bit)
+{
+ u32 buf, x, y = 0;
+
+ dbg_assert (nb_bit <= 64);
+
+ for(buf = 0; nb_bit; nb_bit -= x, bit_offset += x, y += x)
+ {
+ x = MIN (bitsizeof(buf), nb_bit);
+ buf = 0xffffffff & (value >> y);
+ bitstream_direct_write (data, bit_offset, buf, x);
+ }
+}
+
+
+void*
+bitstream_memcpy (void *dest, void *src, size_t len)
+{
+ u32 tmp, x = 0;
+ bitstream_t ctx_r, ctx_w;
+
+ bitstream_init (&ctx_r, src, len, BITSTREAM_READ);
+ bitstream_init (&ctx_w, dest, len, BITSTREAM_WRITE);
+
+ for(len *= 8; len; len -= x)
+ {
+ x = MIN (bitsizeof (tmp), len);
+ bitstream_access (&ctx_r, &tmp, x);
+ bitstream_access (&ctx_w, &tmp, x);
+ }
+
+ bitstream_finalise (&ctx_r);
+ bitstream_finalise (&ctx_w);
+ return dest;
+}
+
+/**
+ * Compare two buffers and return true if the buffers are equals
+ * \param s1 the first buffer to compare.
+ * \param s2 the second buffer to compare.
+ * \param len the length in bytes to compare the buffers.
+ * \return true if equal, false otherwise.
+ */
+bool
+bitstream_memcmp (void *s1, void *s2, size_t len)
+{
+ u32 x = 0;
+ uint s1_data, s2_data;
+ bitstream_t ctx_r1, ctx_r2;
+
+ bitstream_init (&ctx_r1, s1, len, BITSTREAM_READ);
+ bitstream_init (&ctx_r2, s2, len, BITSTREAM_READ);
+
+ for(len *= 8; len; len -= x)
+ {
+ x = MIN (bitsizeof (s1_data), len);
+ bitstream_access (&ctx_r1, &s1_data, x);
+ bitstream_access (&ctx_r2, &s2_data, x);
+
+ if (s1_data != s2_data)
+ {
+ bitstream_finalise (&ctx_r1);
+ bitstream_finalise (&ctx_r2);
+
+ return false;
+ }
+ }
+
+ bitstream_finalise (&ctx_r1);
+ bitstream_finalise (&ctx_r2);
+ return true;
+}
diff --git a/cesar/lib/src/blk.c b/cesar/lib/src/blk.c
new file mode 100644
index 0000000000..069bde958a
--- /dev/null
+++ b/cesar/lib/src/blk.c
@@ -0,0 +1,244 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/src/blk.c
+ * \brief 512 byte memory blocks.
+ * \ingroup lib
+ *
+ * \todo This is a temporary implementation using malloc and no optimisations.
+ */
+#include "common/std.h"
+
+#include "lib/blk.h"
+#include "hal/arch/arch.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define REFCNT(blk) ((int *) ((u8 *) (blk) - BLK_REFCNT_SIZE))
+#define TO_BLK(data) ((blk_t *) ((u8 *) (data) + BLK_SIZE + BLK_REFCNT_SIZE))
+
+/** Structure to accumulate the several actions type on blocks. */
+struct blocks_t
+{
+ /** Incremented when a new blocks has been allocated. */
+ uint allocated;
+ /** Incremented when a block has been freed. */
+ uint freed;
+ /** Incremented when a new reference on a block has been added. */
+ uint referenced;
+ /** Incremented when a release action on a block has been done. */
+ uint released;
+};
+typedef struct blocks_t blocks_t;
+
+blocks_t blocks;
+
+enum {
+ /** Magic code used for destructor-less allocations.
+ * 'o', 'b', 'j', <odd number>. This magic should be odd to not collide
+ * with a pointer. */
+ BLK_OBJ_MAGIC = 0x6f626aa5
+};
+
+/** Block descriptor for descriptor-less allocations. */
+struct blk_obj_t
+{
+ /** Magic code in place of next pointer. */
+ u32 magic;
+ /** Pointer to data. */
+ u8 *data;
+ /** Destructor function pointer or NULL. */
+ blk_destructor_t destructor;
+ /** Reserved for future usage. */
+ u32 reserved;
+};
+typedef struct blk_obj_t blk_obj_t;
+
+blk_t *
+blk_alloc_desc_ (void_FL)
+{
+ u8 *data = malloc (BLK_SIZE + BLK_REFCNT_SIZE + BLK_DESC_SIZE);
+ if (!data)
+ dbg_fatal ("exhausted virtual memory");
+ blk_t *blk = TO_BLK (data);
+ dbg_invalid_ptr (blk->next);
+ blk->data = data;
+ *REFCNT(blk) = 1;
+ blocks.allocated++;
+ blocks.referenced++;
+ restrack_create (NULL, blk, _fl_, 1);
+ return blk;
+}
+
+blk_t *
+blk_alloc_desc_range_ (uint n, blk_t **last __FL)
+{
+ blk_t *first, *b;
+ dbg_assert (n);
+ dbg_assert_ptr (last);
+ first = b = blk_alloc_desc_ (_fl);
+ for (n--; n; n--)
+ {
+ b->next = blk_alloc_desc_ (_fl);
+ b = b->next;
+ }
+ *last = b;
+ return first;
+}
+
+static void
+blk_free_desc_ (blk_t *blk __FL)
+{
+ dbg_assert_ptr (blk);
+ dbg_assert (TO_BLK (blk->data) == blk);
+ restrack_destroy (NULL, blk, _fl_, 0);
+ blocks.freed++;
+ free (blk->data);
+}
+
+void
+blk_addref_desc_ (blk_t *blk __FL)
+{
+ dbg_assert_ptr (blk);
+ dbg_assert (TO_BLK (blk->data) == blk);
+ arch_atomic_add (REFCNT (blk), 1);
+ restrack_update (NULL, blk, _fl_, 1);
+ blocks.referenced++;
+}
+
+void
+blk_addref_desc_range_ (blk_t *first, blk_t *last __FL)
+{
+ blk_t *b;
+ for (b = first; b != last; b = b->next)
+ {
+ blk_addref_desc_ (b __fl);
+ }
+ blk_addref_desc_ (b __fl);
+}
+
+void
+blk_addref_desc_range_nb_ (blk_t *first, uint n __FL)
+{
+ dbg_assert (n);
+ blk_t *b;
+ uint i;
+ for (b = first, i = n; i; b = b->next, i--)
+ {
+ blk_addref_desc_ (b __fl);
+ }
+}
+
+void
+blk_release_desc_ (blk_t *blk __FL)
+{
+ dbg_assert_ptr (blk);
+ dbg_assert (TO_BLK (blk->data) == blk);
+ dbg_assert (((blk_obj_t *) blk)->magic != BLK_OBJ_MAGIC);
+ dbg_assert (REFCNT (blk) != 0);
+ restrack_update (NULL, blk, _fl_, -1);
+ blocks.released++;
+ if (arch_atomic_add (REFCNT (blk), -1) == 0)
+ {
+ blk_free_desc_ (blk __fl);
+ }
+}
+
+void
+blk_release_desc_range_ (blk_t *first, blk_t *last __FL)
+{
+ blk_t *b, *bn;
+ for (b = first; b != last; b = bn)
+ {
+ bn = b->next;
+ blk_release_desc_ (b __fl);
+ }
+ blk_release_desc_ (b __fl);
+}
+
+void
+blk_release_desc_range_nb_ (blk_t *first, uint n __FL)
+{
+ dbg_assert (n);
+ blk_t *b, *bn;
+ uint i;
+ for (b = first, i = n; i; b = bn, i--)
+ {
+ bn = b->next;
+ blk_release_desc_ (b __fl);
+ }
+}
+
+void *
+blk_alloc_ (void_FL)
+{
+ return blk_new_ (NULL __fl);
+}
+
+void *
+blk_new_ (blk_destructor_t destructor __FL)
+{
+ blk_t *blk = blk_alloc_desc_ (_fl);
+ blk_obj_t *obj = (blk_obj_t *) blk;
+ obj->magic = BLK_OBJ_MAGIC;
+ obj->destructor = destructor;
+ return blk->data;
+}
+
+void *
+blk_alloc_zero_ (void_FL)
+{
+ void *data = blk_alloc_ (_fl);
+ memset (data, 0, BLK_SIZE);
+ return data;
+}
+
+void
+blk_addref_ (void *data __FL)
+{
+ dbg_assert_ptr (data);
+ blk_t *blk = TO_BLK (data);
+ dbg_assert (((blk_obj_t *) blk)->magic == BLK_OBJ_MAGIC);
+ blk_addref_desc_ (blk __fl);
+}
+
+void
+blk_release_ (void *data __FL)
+{
+ dbg_assert_ptr (data);
+ blk_obj_t *obj = (blk_obj_t *) TO_BLK (data);
+ dbg_assert_ptr (obj);
+ dbg_assert (obj->magic == BLK_OBJ_MAGIC);
+ restrack_update (NULL, obj, _fl_, -1);
+ blocks.released++;
+ if (arch_atomic_add (REFCNT (obj), -1) == 0)
+ {
+ if (obj->destructor)
+ obj->destructor (data);
+ blk_free_desc_ ((blk_t *) obj __fl);
+ }
+}
+
+bool
+blk_check_memory (void)
+{
+ return restrack_check ()
+ && blocks.allocated == blocks.freed
+ && blocks.referenced == blocks.released;
+}
+
+void
+blk_print_memory (void)
+{
+ fprintf (stderr, "[MEM STATE] Allocated : %d\t Freed : %d\t Referenced : %d\t Released : %d\n",
+ blocks.allocated, blocks.freed,
+ blocks.referenced, blocks.released
+ );
+}
diff --git a/cesar/lib/src/circular_buffer.c b/cesar/lib/src/circular_buffer.c
new file mode 100644
index 0000000000..1f5a1851e9
--- /dev/null
+++ b/cesar/lib/src/circular_buffer.c
@@ -0,0 +1,101 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/src/circular_buffer.c
+ * \brief Circular buffer list.
+ * \ingroup lib
+ *
+ * Provides a circular buffer list API.
+ * Reserve the real size of the buffer just after the declaration of the
+ * circular buffer to not have some memory problems.
+ */
+#include "common/std.h"
+#include "lib/circular_buffer.h"
+
+/**
+ * Initialize the buffer address list
+ *
+ * \param list the buffer address list to initiliaze
+ * \param buffer the circular buffer to use.
+ * \param number_slots the quantity of slots.
+ */
+void
+circular_buffer_init (circular_buffer_t *list, void *buffer, uint number_slots)
+{
+ dbg_assert (list);
+
+ list->num_slots = number_slots;
+ list->buffer = buffer;
+ list->head = 0;
+ list->tail = 0;
+ list->nb_elements = 0;
+}
+
+/**
+ * Add an address to the buffer address buffer list
+ *
+ * \param ctx the ctx containing the list.
+ * \param address the address to add to the list
+ * \param number_of_slots the quantity of address it can keep in the list.
+ *
+ * \return true if the buffer had been added, false otherwise
+ */
+bool
+circular_buffer_add (circular_buffer_t *ctx, void *address)
+{
+ dbg_assert (ctx);
+
+ if (ctx->nb_elements < ctx->num_slots)
+ {
+ ctx->buffer[ctx->tail] = address;
+ ctx->tail ++;
+ ctx->nb_elements ++;
+ if (ctx->tail > ctx->num_slots - 1)
+ {
+ ctx->tail = 0;
+ }
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Peek the first element of the list without removing it.
+ *
+ * \param ctx the context.
+ */
+void*
+circular_buffer_peek (circular_buffer_t *ctx)
+{
+ return ctx->buffer[ctx->head];
+}
+
+/**
+ * Get the current address and go to the next one.
+ *
+ * \param ctx the ctx containing the list.
+ * \param number_of_slots the quantity of address it can keep in the list.
+ */
+void*
+circular_buffer_get (circular_buffer_t *ctx)
+{
+ void *buffer = NULL;
+
+ if (ctx->nb_elements != 0)
+ {
+ buffer = ctx->buffer[ctx->head];
+ ctx->head ++;
+ ctx->nb_elements --;
+ if (ctx->head > ctx->num_slots - 1)
+ {
+ ctx->head = 0;
+ }
+ }
+ return buffer;
+}
+
diff --git a/cesar/lib/src/crc.c b/cesar/lib/src/crc.c
new file mode 100644
index 0000000000..df509c4d38
--- /dev/null
+++ b/cesar/lib/src/crc.c
@@ -0,0 +1,193 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/src/crc.c
+ * \brief General Cyclic Redundancy Code utilities.
+ * \ingroup lib
+ */
+#include "common/std.h"
+
+#include "lib/crc.h"
+
+/**
+ * Reflect the width lowest significant bits in word.
+ * \param word the word to reflect
+ * \param width the number of bits
+ * \return the reflected word
+ */
+extern inline
+u32
+crc_reflect (u32 word, uint width)
+{
+ u32 newword;
+ uint i;
+ /* Please compiler, optimise and inline this or I will have to do it
+ * myself: */
+ newword = 0;
+ for (i = 0; i < width; i++)
+ {
+ if (word & (1 << i))
+ newword |= 1 << (width - i - 1);
+ }
+ return newword;
+}
+
+void
+crc_init (crc_t *ctx)
+{
+ /* OK, for the moment, only support a subset of the general model. */
+ dbg_assert_print ((ctx->width == 32 || ctx->width == 24
+ || ctx->width == 16 || ctx->width == 8)
+ && (ctx->refin == true || ctx->refin == false)
+ && (ctx->refout == true || ctx->refout == false),
+ "unsupported model values");
+ dbg_assert (ctx->generator);
+ dbg_assert (ctx->table.t32);
+ /* Compute initial register value. */
+ u32 generator = ctx->generator;
+ u32 reg_init = ctx->init;
+ if (ctx->refin)
+ {
+ generator = crc_reflect (generator, ctx->width);
+ reg_init = crc_reflect (reg_init, ctx->width);
+ }
+ ctx->reg_init = reg_init;
+ /* Generate table. */
+ uint i, b;
+ u32 reg;
+ u32 top = 1 << (ctx->width - 1);
+ for (i = 0; i < 256; i++)
+ {
+ if (ctx->refin)
+ {
+ reg = i;
+ for (b = 0; b < 8; b++)
+ {
+ if (reg & 1)
+ reg = (reg >> 1) ^ generator;
+ else
+ reg >>= 1;
+ }
+ }
+ else
+ {
+ reg = i << (ctx->width - 8);
+ for (b = 0; b < 8; b++)
+ {
+ if (reg & top)
+ reg = (reg << 1) ^ generator;
+ else
+ reg <<= 1;
+ }
+ reg &= (1 << (ctx->width - 1) << 1) - 1;
+ }
+ switch (ctx->width)
+ {
+ case 32:
+ case 24:
+ ctx->table.t32[i] = reg;
+ break;
+ case 16:
+ ctx->table.t16[i] = reg;
+ break;
+ case 8:
+ ctx->table.t8[i] = reg;
+ break;
+ }
+ }
+}
+
+u32
+crc_compute_block (const crc_t *ctx, const u8 *block, uint block_size)
+{
+ dbg_assert (ctx);
+ dbg_assert (block || block_size == 0);
+ u32 reg;
+ reg = crc_compute_begin (ctx);
+ reg = crc_compute_continue_block (ctx, reg, block, block_size);
+ reg = crc_compute_end (ctx, reg);
+ return reg;
+}
+
+u32
+crc_compute_begin (const crc_t *ctx)
+{
+ dbg_assert (ctx);
+ return ctx->reg_init;
+}
+
+u32
+crc_compute_continue_block (const crc_t *ctx, u32 reg, const u8 *block,
+ uint block_size)
+{
+ const u32 *t32;
+ const u16 *t16;
+ const u8 *t8;
+ dbg_assert (ctx);
+ dbg_assert (block || block_size == 0);
+ if (ctx->refin)
+ {
+ switch (ctx->width)
+ {
+ case 32:
+ case 24:
+ t32 = ctx->table.t32;
+ while (block_size--)
+ reg = (reg >> 8) ^ t32[(reg ^ *block++) & 0xff];
+ break;
+ case 16:
+ t16 = ctx->table.t16;
+ while (block_size--)
+ reg = ((reg >> 8) ^ t16[(reg ^ *block++) & 0xff]) & 0xffff;
+ break;
+ case 8:
+ t8 = ctx->table.t8;
+ while (block_size--)
+ reg = t8[reg ^ *block++];
+ break;
+ }
+ }
+ else
+ {
+ switch (ctx->width)
+ {
+ case 32:
+ t32 = ctx->table.t32;
+ while (block_size--)
+ reg = (reg << 8) ^ t32[(reg >> 24) ^ *block++];
+ break;
+ case 24:
+ t32 = ctx->table.t32;
+ while (block_size--)
+ reg = ((reg << 8) ^ t32[(reg >> 16) ^ *block++]) & 0xffffff;
+ break;
+ case 16:
+ t16 = ctx->table.t16;
+ while (block_size--)
+ reg = ((reg << 8) ^ t16[(reg >> 8) ^ *block++]) & 0xffff;
+ break;
+ case 8:
+ t8 = ctx->table.t8;
+ while (block_size--)
+ reg = t8[reg ^ *block++];
+ break;
+ }
+ }
+ return reg;
+}
+
+u32
+crc_compute_end (const crc_t *ctx, u32 reg)
+{
+ dbg_assert (ctx);
+ if (ctx->refin != ctx->refout)
+ return crc_reflect (reg, ctx->width) ^ ctx->xorout;
+ else
+ return reg ^ ctx->xorout;
+}
+
diff --git a/cesar/lib/src/dbg.c b/cesar/lib/src/dbg.c
new file mode 100644
index 0000000000..f4a932dc38
--- /dev/null
+++ b/cesar/lib/src/dbg.c
@@ -0,0 +1,71 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/src/dbg.c
+ * \brief Debug functions.
+ * \ingroup lib
+ */
+#include "common/std.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+#if DEBUG
+
+# if CONFIG_DEBUG_FATAL_CATCH
+int dbg_fatal_try_level_;
+char dbg_fatal_text_[2048];
+# endif
+
+void
+dbg_assert_fail (const char *assertion, const char *file, uint line,
+ const char *function)
+{
+ dbg_fatal (DBG_ASSERT_FMT_ "%s", file, line, function,
+ assertion);
+}
+
+void
+dbg_assert_print_fail (const char *fmt, ...)
+{
+ va_list ap;
+ va_start (ap, fmt);
+ dbg_vfatal (fmt, ap);
+ va_end (ap);
+}
+
+#endif /* DEBUG */
+
+void
+dbg_fatal (const char *fmt, ...)
+{
+ va_list ap;
+ va_start (ap, fmt);
+ dbg_vfatal (fmt, ap);
+ va_end (ap);
+}
+
+void
+dbg_vfatal (const char *fmt, va_list ap)
+{
+#if DEBUG && CONFIG_DEBUG_FATAL_CATCH
+ if (dbg_fatal_try_level_)
+ {
+ vsnprintf (dbg_fatal_text_, sizeof (dbg_fatal_text_), fmt, ap);
+ try_throw (TRY_CODE_FATAL);
+ }
+ else
+#endif
+ {
+ vfprintf (stderr, fmt, ap);
+ fputc ('\n', stderr);
+ abort ();
+ }
+}
+
diff --git a/cesar/lib/src/heap.c b/cesar/lib/src/heap.c
new file mode 100644
index 0000000000..af8c83f2ca
--- /dev/null
+++ b/cesar/lib/src/heap.c
@@ -0,0 +1,62 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/src/heap.c
+ * \brief Heap common functions.
+ * \ingroup lib
+ *
+ * Provide common utilities functions for heaps.
+ */
+#include "common/std.h"
+
+#include "lib/heap.h"
+
+void
+heap_init (heap_t *heap, heap_node_less_t less)
+{
+ dbg_assert (heap);
+ heap->root = NULL;
+ heap->less = less;
+}
+
+void
+heap_adjust (heap_t *heap, heap_node_t *node)
+{
+ dbg_assert (heap);
+ dbg_assert (node);
+ /* If position should actually change. */
+ if ((node->left && heap->less (node->left, node))
+ || (node->right && heap->less (node->right, node))
+ || (node->father && heap->less (node, node->father)))
+ {
+ heap_remove (heap, node);
+ heap_insert (heap, node);
+ }
+}
+
+void
+heap_merge (heap_t *heap_to, heap_t *heap_from)
+{
+ dbg_assert (heap_to && heap_to->less);
+ dbg_assert (heap_from && heap_from->less);
+ dbg_assert_print (heap_to->less == heap_from->less, "incompatible heaps");
+ heap_to->root = heap_node_merge (heap_to->root, heap_from->root,
+ heap_to->less);
+ heap_from->root = NULL;
+}
+
+bool
+heap_node_u32_less_mod2p32 (heap_node_t *left, heap_node_t *right)
+{
+ dbg_assert (left);
+ dbg_assert (right);
+ heap_node_u32_t *l = PARENT_OF (heap_node_u32_t, node, left);
+ heap_node_u32_t *r = PARENT_OF (heap_node_u32_t, node, right);
+ return less_mod2p32 (l->key, r->key);
+}
+
diff --git a/cesar/lib/src/leftheap.c b/cesar/lib/src/leftheap.c
new file mode 100644
index 0000000000..8f7c6d3ad8
--- /dev/null
+++ b/cesar/lib/src/leftheap.c
@@ -0,0 +1,159 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/src/leftheap.c
+ * \brief Leftist heaps.
+ * \ingroup lib
+ */
+#include "common/std.h"
+
+#include "lib/heap.h"
+
+void
+heap_node_init (heap_node_t *node)
+{
+ node->father = NULL;
+ node->left = node->right = NULL;
+ node->null_path_length = 1;
+}
+
+heap_node_t *
+heap_node_merge (heap_node_t *root1, heap_node_t *root2,
+ heap_node_less_t less)
+{
+ heap_node_t *h, *h2, *root;
+ dbg_assert (!root1 || !root1->father);
+ dbg_assert (!root2 || !root2->father);
+ dbg_assert (less);
+ /* Trivial cases. */
+ if (!root1)
+ return root2;
+ else if (!root2)
+ return root1;
+ /* Initialise. */
+ if (less (root1, root2))
+ {
+ h = root1;
+ h2 = root2;
+ }
+ else
+ {
+ h = root2;
+ h2 = root1;
+ }
+ root = h;
+ /* Merge along the right paths. */
+ while (h2)
+ {
+ if (!h->right || less (h2, h->right))
+ {
+ XCH (h2, h->right);
+ h->right->father = h;
+ }
+ h = h->right;
+ }
+ /* Now walk up the path to fix balance. */
+ dbg_assert (h);
+ for (; h; h = h->father)
+ {
+ uint lnpl = h->left ? h->left->null_path_length : 0;
+ uint rnpl = h->right ? h->right->null_path_length : 0;
+ if (lnpl < rnpl)
+ {
+ XCH (h->left, h->right);
+ }
+ h->null_path_length = 1 + MIN (lnpl, rnpl);
+ }
+ return root;
+}
+
+void
+heap_insert (heap_t *heap, heap_node_t *node)
+{
+ dbg_assert (heap);
+ dbg_assert (node);
+ heap->root = heap_node_merge (heap->root, node, heap->less);
+}
+
+void
+heap_remove_root (heap_t *heap)
+{
+ heap_node_t *root;
+ dbg_assert (heap);
+ dbg_assert (!heap_empty (heap));
+ root = heap->root;
+ if (root->left)
+ root->left->father = NULL;
+ if (root->right)
+ root->right->father = NULL;
+ heap->root = heap_node_merge (root->left, root->right, heap->less);
+ root->father = root->left = root->right = NULL;
+ root->null_path_length = 1;
+}
+
+void
+heap_remove (heap_t *heap, heap_node_t *node)
+{
+ heap_node_t **r;
+ dbg_assert (heap);
+ dbg_assert (!heap_empty (heap));
+ dbg_assert (node);
+ /* Where to store the merged tree? */
+ if (!node->father)
+ {
+ dbg_assert (node == heap->root);
+ r = &heap->root;
+ }
+ else if (node->father->right == node)
+ {
+ r = &node->father->right;
+ }
+ else
+ {
+ dbg_assert (node->father->left == node);
+ r = &node->father->left;
+ }
+ /* Need NULL father pointer. */
+ if (node->left)
+ node->left->father = NULL;
+ if (node->right)
+ node->right->father = NULL;
+ /* Merge left and right subtree. */
+ *r = heap_node_merge (node->left, node->right, heap->less);
+ if (*r)
+ (*r)->father = node->father;
+ /**
+ * We can not just replace the removed node with a merge of its right and
+ * left subtrees because this may change null_path_length. There is
+ * several solutions:
+ * - walk up the tree to fix balance,
+ * - instead of one merge, do two merges, first with left subtree, then
+ * right subtree,
+ * - ignore this structure break...
+ *
+ * Here the first solution is chosen.
+ */
+ heap_node_t *h;
+ for (h = node->father; h; h = h->father)
+ {
+ uint lnpl = h->left ? h->left->null_path_length : 0;
+ uint rnpl = h->right ? h->right->null_path_length : 0;
+ if (lnpl < rnpl)
+ {
+ XCH (h->left, h->right);
+ }
+ uint nnpl = 1 + MIN (lnpl, rnpl);
+ if (h->null_path_length == nnpl)
+ break;
+ h->null_path_length = nnpl;
+ }
+ /* Detach the removed node. */
+ node->father = node->left = node->right = NULL;
+ node->null_path_length = 1;
+}
+
diff --git a/cesar/lib/src/list.c b/cesar/lib/src/list.c
new file mode 100644
index 0000000000..61771b2c53
--- /dev/null
+++ b/cesar/lib/src/list.c
@@ -0,0 +1,181 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/src/list.c
+ * \brief Double linked list.
+ * \ingroup lib
+ */
+#include "common/std.h"
+#include "lib/list.h"
+
+void
+list_init (list_t *list)
+{
+ dbg_assert (list);
+ list_init_node (&list->nil);
+}
+
+void
+list_init_node (list_node_t *node)
+{
+ dbg_assert (node);
+ node->next = node->prev = node;
+}
+
+list_node_t *
+list_begin (list_t *list)
+{
+ dbg_assert (list);
+ return list->nil.next;
+}
+
+list_node_t *
+list_end (list_t *list)
+{
+ dbg_assert (list);
+ return &list->nil;
+}
+
+list_node_t *
+list_rbegin (list_t *list)
+{
+ dbg_assert (list);
+ return list->nil.prev;
+}
+
+list_node_t *
+list_rend (list_t *list)
+{
+ dbg_assert (list);
+ return &list->nil;
+}
+
+list_node_t *
+list_next (list_node_t *node)
+{
+ dbg_assert (node);
+ return node->next;
+}
+
+list_node_t *
+list_prev (list_node_t *node)
+{
+ dbg_assert (node);
+ return node->prev;
+}
+
+bool
+list_empty (list_t *list)
+{
+ dbg_assert (list);
+ return list->nil.next == &list->nil;
+}
+
+void
+list_push (list_t *list, list_node_t *node)
+{
+ dbg_assert (list);
+ dbg_assert (node && node->next == node && node->prev == node);
+ node->prev = list->nil.prev;
+ node->next = &list->nil;
+ list->nil.prev->next = node;
+ list->nil.prev = node;
+}
+
+void
+list_unshift (list_t *list, list_node_t *node)
+{
+ dbg_assert (list);
+ dbg_assert (node && node->next == node && node->prev == node);
+ node->next = list->nil.next;
+ node->prev = &list->nil;
+ list->nil.next->prev = node;
+ list->nil.next = node;
+}
+
+list_node_t *
+list_pop (list_t *list)
+{
+ list_node_t *node;
+ dbg_assert (list && !list_empty (list));
+ node = list->nil.prev;
+ dbg_assert (node && node->prev && node->next == &list->nil);
+ list->nil.prev = node->prev;
+ node->prev->next = &list->nil;
+ node->next = node->prev = node;
+ return node;
+}
+
+list_node_t *
+list_shift (list_t *list)
+{
+ list_node_t *node;
+ dbg_assert (list && !list_empty (list));
+ node = list->nil.next;
+ dbg_assert (node && node->next && node->prev == &list->nil);
+ list->nil.next = node->next;
+ node->next->prev = &list->nil;
+ node->next = node->prev = node;
+ return node;
+}
+
+void
+list_remove (list_t *list, list_node_t *node)
+{
+ dbg_assert (list && !list_empty (list));
+ dbg_assert (node && node->next && node->next != node
+ && node->prev && node->prev != node);
+ node->prev->next = node->next;
+ node->next->prev = node->prev;
+ node->next = node->prev = node;
+}
+
+void
+list_insert (list_t *list, list_node_t *before, list_node_t *node)
+{
+ dbg_assert (list);
+ dbg_assert (before && before->prev);
+ dbg_assert (node && node->next == node && node->prev == node);
+ node->next = before;
+ node->prev = before->prev;
+ before->prev->next = node;
+ before->prev = node;
+}
+
+void
+list_push_range (list_t *to, list_t *from,
+ list_node_t *first, list_node_t *last)
+{
+ dbg_assert (to);
+ list_insert_range (to, from, &to->nil, first, last);
+}
+
+void
+list_unshift_range (list_t *to, list_t *from,
+ list_node_t *first, list_node_t *last)
+{
+ dbg_assert (to);
+ list_insert_range (to, from, to->nil.next, first, last);
+}
+
+void
+list_insert_range (list_t *to, list_t *from, list_node_t *before,
+ list_node_t *first, list_node_t *last)
+{
+ list_node_t *before_last;
+ dbg_assert (to && from && !list_empty (from));
+ dbg_assert (before && first && last);
+ first->prev->next = last;
+ before_last = last->prev;
+ last->prev = first->prev;
+ first->prev = before->prev;
+ before_last->next = before;
+ before->prev->next = first;
+ before->prev = before_last;
+}
+
diff --git a/cesar/lib/src/mt19937ar.c b/cesar/lib/src/mt19937ar.c
new file mode 100644
index 0000000000..2268a6ed2d
--- /dev/null
+++ b/cesar/lib/src/mt19937ar.c
@@ -0,0 +1,260 @@
+/* Cesar project {{{
+ *
+ * THIS FILE is Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji
+ * Nishimura. Please see below for more information.
+ *
+ * Include modification by Spidcom for constant time calls.
+ *
+ * }}} */
+/**
+ * \file lib/src/mt19937ar.c
+ * \brief Random Number Generator implemented by MT19937.
+ * \ingroup lib
+ *
+ * Please do not update formating or indent so that diffing is easy.
+ */
+
+/*
+ A C-program for MT19937, with initialization improved 2002/1/26.
+ Coded by Takuji Nishimura and Makoto Matsumoto.
+
+ Before using, initialize the state by using init_genrand(seed)
+ or init_by_array(init_key, key_length).
+
+ Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. 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.
+
+ 3. The names of its contributors may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "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 THE COPYRIGHT OWNER OR
+ CONTRIBUTORS 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.
+
+
+ Any feedback is very welcome.
+ http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
+ email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
+*/
+#include "common/std.h"
+#include "lib/rnd.h"
+
+/* Do not generate N words at one time in order to limit maximum latency. */
+#define LIB_MT_BURST 0
+
+/* Period parameters */
+#define N LIB_MT_N
+#define M 397
+#define MATRIX_A 0x9908b0dfUL /* constant vector a */
+#define UPPER_MASK 0x80000000UL /* most significant w-r bits */
+#define LOWER_MASK 0x7fffffffUL /* least significant r bits */
+
+/* Use context instead of global variables. */
+#define mt (ctx->state)
+#define mti (ctx->state_index)
+
+/**
+ * Initialise a random number generator context.
+ * \param ctx the rnd context to initialise.
+ * \param seed 32 bit random seed.
+ */
+void
+lib_rnd_init (lib_rnd_t *ctx, u32 seed)
+{
+ dbg_assert (ctx);
+ mt[0]= seed & 0xffffffffUL;
+ for (mti=1; mti<N; mti++) {
+ mt[mti] =
+ (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
+ /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
+ /* In the previous versions, MSBs of the seed affect */
+ /* only MSBs of the array mt[]. */
+ /* 2002/01/09 modified by Makoto Matsumoto */
+ mt[mti] &= 0xffffffffUL;
+ /* for >32 bit machines */
+ }
+}
+
+/**
+ * Initialise a random number generator context using an array in order to
+ * use a greater initialisation space.
+ * \param ctx the rnd context to initialise.
+ * \param init_key the array.
+ * \param key_length the array length.
+ */
+void
+lib_rnd_init_by_array (lib_rnd_t *ctx, const u32 init_key[], int key_length)
+{
+ int i, j, k;
+ dbg_assert (ctx);
+ dbg_assert (init_key);
+ dbg_assert (key_length > 0);
+ lib_rnd_init(ctx, 19650218UL);
+ i=1; j=0;
+ k = (N>key_length ? N : key_length);
+ for (; k; k--) {
+ mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL))
+ + init_key[j] + j; /* non linear */
+ mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
+ i++; j++;
+ if (i>=N) { mt[0] = mt[N-1]; i=1; }
+ if (j>=key_length) j=0;
+ }
+ for (k=N-1; k; k--) {
+ mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL))
+ - i; /* non linear */
+ mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
+ i++;
+ if (i>=N) { mt[0] = mt[N-1]; i=1; }
+ }
+
+ mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */
+}
+
+/**
+ * Generates a random number on [0,0xffffffff]-interval.
+ * \param ctx the rnd context.
+ * \return the random number.
+ */
+u32
+lib_rnd32 (lib_rnd_t *ctx)
+{
+ unsigned long y;
+ static const unsigned long mag01[2]={0x0UL, MATRIX_A};
+ /* mag01[x] = x * MATRIX_A for x=0,1 */
+
+ dbg_assert (ctx);
+
+#if LIB_MT_BURST
+ if (mti >= N) { /* generate N words at one time */
+ int kk;
+
+ if (mti == N+1) /* if init_genrand() has not been called, */
+ init_genrand(5489UL); /* a default initial seed is used */
+
+ for (kk=0;kk<N-M;kk++) {
+ y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
+ mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
+ }
+ for (;kk<N-1;kk++) {
+ y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
+ mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
+ }
+ y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
+ mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
+
+ mti = 0;
+ }
+#else
+ if (mti >= N)
+ mti = 0;
+ if (mti < N - M)
+ {
+ y = (mt[mti]&UPPER_MASK)|(mt[mti+1]&LOWER_MASK);
+ mt[mti] = mt[mti+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
+ }
+ else if (mti < N - 1)
+ {
+ y = (mt[mti]&UPPER_MASK)|(mt[mti+1]&LOWER_MASK);
+ mt[mti] = mt[mti+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
+ }
+ else
+ {
+ y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
+ mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
+ }
+#endif
+
+ y = mt[mti++];
+
+ /* Tempering */
+ y ^= (y >> 11);
+ y ^= (y << 7) & 0x9d2c5680UL;
+ y ^= (y << 15) & 0xefc60000UL;
+ y ^= (y >> 18);
+
+ return y;
+}
+
+/* End of MT19937 code. */
+#include "config/rnd/buffer/optimise.h"
+
+/**
+ * Generates a random number on [0,bound-1]-interval.
+ * \param ctx the rnd context.
+ * \param bound upper bound.
+ * \return the random number.
+ */
+uint
+lib_rnd_uniform (lib_rnd_t *ctx, uint bound)
+{
+ uint up;
+ uint n;
+ dbg_assert (ctx);
+ dbg_assert (bound != 0);
+ /* This is not optimal if bound is a power of two, but it is harder to
+ * divide 2^32. */
+ up = 0xffffffff - (0xffffffff % bound);
+ do {
+ n = lib_rnd32 (ctx);
+ } while (n > up);
+ return n % bound;
+}
+
+/**
+ * Fill a buffer with random data.
+ * \param ctx the rnd context
+ * \param buf buffer to fill
+ * \param buf_size buffer size
+ *
+ * The buffer need not to be word aligned.
+ *
+ * This will generate a reproducible buffer over big and little endian
+ * machines.
+ */
+void
+lib_rnd_buffer (lib_rnd_t *ctx, u8 *buf, uint buf_size)
+{
+ dbg_assert (ctx);
+ dbg_assert_ptr (buf);
+#if CONFIG_RND_BUFFER_OPTIMISE && !DEFS_BIG_ENDIAN
+ /* Not needed yet. */
+ dbg_assert_print (0, "not implemented");
+#else /* !(CONFIG_RND_BUFFER_OPTIMISE && !DEFS_BIG_ENDIAN) */
+ u32 r = 0;
+ uint rb = 0;
+ u8 *p = buf;
+ u8 *pend = buf + buf_size;
+ while (p != pend)
+ {
+ if (rb == 0)
+ {
+ r = lib_rnd32 (ctx);
+ rb = 4;
+ }
+ *p++ = r & 0xff;
+ r >>= 8;
+ rb--;
+ }
+#endif /* !(CONFIG_RND_BUFFER_OPTIMISE && !DEFS_BIG_ENDIAN) */
+}
diff --git a/cesar/lib/src/read_word.c b/cesar/lib/src/read_word.c
new file mode 100644
index 0000000000..27145c91af
--- /dev/null
+++ b/cesar/lib/src/read_word.c
@@ -0,0 +1,129 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/src/read_word.c
+ * \brief Read a word from the memory aligned on an integer address.
+ * \ingroup lib
+ *
+ * Allows the system to get a value from the memory reading it word by word
+ * and returning the value request from the user.
+ *
+ * Exemple : we need to get a 4 bytes word from the address 503 on the
+ * memory it will calculate the address from the one it should start reading
+ * the data to be aligned.
+ * So it will read a word from the address 500 and the next one from the @
+ * 504, it will take the last byte of the first word and concatante it with
+ * the three bytes in the last word.
+ * result = word2 << 24 | word1
+ *
+ */
+
+/**
+ * Read the necessary words from the memory and return the data requested.
+ * Aware : if less than a word is request, it will need to be masqued to
+ * desable the bytes which are note necessary.
+ * Example : if you only need the two first bytes you should request:
+ * read_bytes_from_word (addr, 2) & 0xFFFF
+ */
+
+#include "common/std.h"
+#include "lib/read_word.h"
+
+/**
+ * Read u64 from two words.
+ *
+ * \param addr the address to read the next two 48 bits.
+ * \return u64 masked on 48 bits.
+ */
+u64 read_u64_from_word (u8 *addr)
+{
+ u64 data;
+
+ data = read_u32_from_word (addr)
+ | ((u64)read_u32_from_word(addr + sizeof(uint)) << 32);
+
+ return data;
+}
+
+
+/**
+ * Read u56 from two words.
+ *
+ * \param addr the address to read the next two 48 bits.
+ * \return u64 masked on 48 bits.
+ */
+u64 read_u56_from_word (u8 *addr)
+{
+ u64 data;
+
+ data = read_u32_from_word (addr)
+ | ((u64)read_u24_from_word(addr + sizeof(uint)) << 32);
+
+ return data;
+}
+
+
+/**
+ * Read u48 from two words.
+ *
+ * \param addr the address to read the next two 48 bits.
+ * \return u64 masked on 48 bits.
+ */
+u64 read_u48_from_word (u8 *addr)
+{
+ u64 data;
+
+ data = read_u32_from_word (addr)
+ | ((u64)read_u16_from_word(addr + sizeof(uint)) << 32);
+
+ return data;
+}
+
+/**
+ * Read 32 bits from the word.
+ *
+ * \param addr the address from the one the value should be read.
+ * \return the u32
+ */
+uint read_u32_from_word (u8 *addr)
+{
+ return read_bytes_from_word(addr, 4);
+}
+
+/**
+ * Reads 24 bits from the word.
+ *
+ * \param addr the address from the one the value should be read.
+ * \return the u32 with the last byte set to 0
+ */
+uint read_u24_from_word (u8 *addr)
+{
+ return read_bytes_from_word (addr, 3) & 0x00FFFFFF;
+}
+
+/**
+ * Read 16 bits from the word.
+ *
+ * \param addr the address from the one the value should be read.
+ * \return the u32 with the last byte set to 0
+ */
+uint read_u16_from_word (u8 *addr)
+{
+ return read_bytes_from_word (addr, 2) & 0x0000FFFF;
+}
+
+/**
+ * Read 8 bits from the word.
+ *
+ * \param addr the address from the one the value should be read.
+ * \return uint with only one byte filled.
+ */
+uint read_u8_from_word (u8 *addr)
+{
+ return read_bytes_from_word (addr, 1) & 0x000000FF;
+}
diff --git a/cesar/lib/src/restrack.c b/cesar/lib/src/restrack.c
new file mode 100644
index 0000000000..2c85e66172
--- /dev/null
+++ b/cesar/lib/src/restrack.c
@@ -0,0 +1,353 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/src/restrack.c
+ * \brief Resources tracker implementation.
+ * \ingroup lib
+ */
+#include "common/std.h"
+
+#include "lib/restrack.h"
+#include "lib/set.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+/** Recorded change for a resource. */
+struct restrack_resource_change_t
+{
+ /** Set node for set of change. */
+ set_node_t node;
+ /** Function doing the change. */
+ const char *function;
+ /** Corresponding source line. */
+ int line;
+ /** Accumulated change. */
+ int change;
+};
+typedef struct restrack_resource_change_t restrack_resource_change_t;
+
+/** Information about a resource. */
+struct restrack_resource_t
+{
+ /** Set node for set of resources. */
+ set_node_t node;
+ /** Resource pointer. */
+ void *resource;
+ /** Current reference counter value. */
+ int references;
+ /** Creator function. */
+ const char *creator_function;
+ /** Creator corresponding source line. */
+ int creator_line;
+ /** Set of recorded changes. */
+ set_t changes_set;
+};
+typedef struct restrack_resource_t restrack_resource_t;
+
+/** Resources tracker context. */
+struct restrack_t
+{
+ /** Set of tracked resources. */
+ set_t resources_set;
+ /** Automatic initialisation depends on this to be initialised to zero by
+ * the compiler. */
+ bool inited;
+ /** Should the clean up function be registered? */
+ bool atexit_done;
+};
+typedef struct restrack_t restrack_t;
+
+/** Global context. */
+restrack_t restrack_global;
+
+/** Set node comparison function for changes. */
+static bool
+restrack_resource_change_less (set_node_t *left, set_node_t *right)
+{
+ dbg_assert_ptr (left);
+ dbg_assert_ptr (right);
+ restrack_resource_change_t *l, *r;
+ l = PARENT_OF (restrack_resource_change_t, node, left);
+ r = PARENT_OF (restrack_resource_change_t, node, right);
+ /* Function strings are compared by address. This is a feature as the
+ * provided function string is supposed to always have the same address at
+ * each call. */
+ return l->function == r->function
+ ? l->line < r->line
+ : l->function < r->function;
+}
+
+/** Set node comparison function for resources. */
+static bool
+restrack_resource_less (set_node_t *left, set_node_t *right)
+{
+ dbg_assert_ptr (left);
+ dbg_assert_ptr (right);
+ restrack_resource_t *l, *r;
+ l = PARENT_OF (restrack_resource_t, node, left);
+ r = PARENT_OF (restrack_resource_t, node, right);
+ return l->resource < r->resource;
+}
+
+/**
+ * Get and eventually initialise global context.
+ * \return unique instance pointer
+ */
+static restrack_t *
+restrack_get_instance (void)
+{
+ restrack_t *ctx = &restrack_global;
+ if (!ctx->inited)
+ {
+ set_init (&ctx->resources_set, restrack_resource_less);
+ ctx->inited = true;
+ }
+ if (!ctx->atexit_done)
+ {
+ atexit (restrack_uninit);
+ ctx->atexit_done = true;
+ }
+ return ctx;
+}
+
+static restrack_resource_t *
+restrack_resource_new (void *resource, const char *function, int line)
+{
+ dbg_assert_ptr (resource);
+ restrack_resource_t *r;
+ /* Malloc should be replaced with a slab allocator. */
+ r = malloc (sizeof (*r));
+ if (!r)
+ dbg_fatal ("exhausted virtual memory");
+ set_node_init (&r->node);
+ r->resource = resource;
+ r->references = 0;
+ r->creator_function = function;
+ r->creator_line = line;
+ set_init (&r->changes_set, restrack_resource_change_less);
+ return r;
+}
+
+static void
+restrack_resource_delete (restrack_resource_t *r)
+{
+ dbg_assert_ptr (r);
+ set_node_t *i, *last, *in;
+ /* Remove all changes node. */
+ for (i = set_begin (&r->changes_set), last = set_end (&r->changes_set);
+ i != last;
+ i = in)
+ {
+ in = set_next (&r->changes_set, i);
+ set_remove (&r->changes_set, i);
+ free (PARENT_OF (restrack_resource_t, node, i));
+ }
+ dbg_assert (set_empty (&r->changes_set));
+ free (r);
+}
+
+/**
+ * Dump a resource.
+ * \param r resource information structure
+ */
+static void
+restrack_resource_dump (restrack_resource_t *r)
+{
+ dbg_assert_ptr (r);
+ fprintf (stderr, "[%#8x] %3d (created: %s:%d)\n", (u32) r->resource,
+ r->references, r->creator_function, r->creator_line);
+ set_node_t *i, *last;
+ for (i = set_begin (&r->changes_set), last = set_end (&r->changes_set);
+ i != last;
+ i = set_next (&r->changes_set, i))
+ {
+ restrack_resource_change_t *c =
+ PARENT_OF (restrack_resource_change_t, node, i);
+ fprintf (stderr, " %s:%d: %3d\n", c->function, c->line, c->change);
+ }
+}
+
+void
+restrack_create (void *owner, void *resource, const char *function, int line,
+ int initial)
+{
+ dbg_assert_ptr (resource);
+ restrack_t *ctx = restrack_get_instance ();
+ restrack_resource_t *r;
+ set_node_t *n;
+ /* Check for duplicates. */
+ r = restrack_resource_new (resource, function, line);
+ n = set_find (&ctx->resources_set, &r->node);
+ if (n)
+ {
+ fprintf (stderr, "!! Duplicate resource creation\n");
+ restrack_resource_dump (PARENT_OF (restrack_resource_t, node, n));
+ fputc ('\n', stderr);
+ restrack_resource_delete (r);
+ }
+ else
+ {
+ /* No duplicates, insert the new node. */
+ dbg_check (set_insert (&ctx->resources_set, &r->node));
+ }
+ /* In all cases, update the node. */
+ restrack_update (owner, resource, function, line, initial);
+}
+
+void
+restrack_update (void *owner, void *resource, const char *function, int line,
+ int change)
+{
+ dbg_assert_ptr (resource);
+ if (change == 0)
+ return;
+ restrack_t *ctx = restrack_get_instance ();
+ set_node_t *n;
+ /* Look up the specified resource. */
+ restrack_resource_t k;
+ set_node_init (&k.node);
+ k.resource = resource;
+ n = set_find (&ctx->resources_set, &k.node);
+ /* If not found, this is a fatal error. */
+ if (!n)
+ {
+ dbg_fatal ("!! Unknown resource update\n"
+ " %s:%d: %3d\n", function, line, change);
+ }
+ else
+ {
+ /* Else, update. */
+ restrack_resource_t *r = PARENT_OF (restrack_resource_t, node, n);
+ r->references += change;
+ restrack_resource_change_t ck;
+ set_node_init (&ck.node);
+ ck.function = function;
+ ck.line = line;
+ n = set_find (&r->changes_set, &ck.node);
+ /* Update an entry or create a new one. */
+ if (n)
+ {
+ PARENT_OF (restrack_resource_change_t, node, n)->change += change;
+ }
+ else
+ {
+ restrack_resource_change_t *c;
+ /* Malloc should be replaced with a slab allocator. */
+ c = malloc (sizeof (*c));
+ if (!c)
+ dbg_fatal ("exhausted virtual memory");
+ set_node_init (&c->node);
+ c->function = function;
+ c->line = line;
+ c->change = change;
+ dbg_check (set_insert (&r->changes_set, &c->node));
+ }
+ /* Test for too many releases. */
+ if (r->references < 0)
+ {
+ fprintf (stderr, "!! Negative resource reference count\n"
+ " %s:%d: %3d\n", function, line, change);
+ restrack_resource_dump (r);
+ fputc ('\n', stderr);
+ }
+ }
+}
+
+void
+restrack_destroy (void *owner, void *resource, const char *function, int line,
+ int change)
+{
+ dbg_assert_ptr (resource);
+ restrack_t *ctx = restrack_get_instance ();
+ set_node_t *n;
+ /* Look up the specified resource. */
+ restrack_resource_t k;
+ set_node_init (&k.node);
+ k.resource = resource;
+ n = set_find (&ctx->resources_set, &k.node);
+ /* If not found, this is a fatal error. */
+ if (!n)
+ {
+ dbg_fatal ("!! Unknown resource destruction\n"
+ " %s:%d: %3d\n", function, line, change);
+ }
+ else
+ {
+ /* Else, update the entry... */
+ restrack_update (owner, resource, function, line, change);
+#if !CONFIG_RESTRACK_KEEP
+ /* ...and remove it. */
+ set_remove (&ctx->resources_set, n);
+ restrack_resource_t *r = PARENT_OF (restrack_resource_t, node, n);
+ if (r->references != 0)
+ {
+ fprintf (stderr, "!! Unbalanced resource destructed\n"
+ " %s:%d: %3d\n", function, line, change);
+ restrack_resource_dump (r);
+ fputc ('\n', stderr);
+ }
+ restrack_resource_delete (r);
+#endif /* !CONFIG_RESTRACK_KEEP */
+ }
+}
+
+bool
+restrack_check (void)
+{
+ restrack_t *ctx = restrack_get_instance ();
+ set_node_t *i, *last;
+ bool errors = false;
+ /* Travel the resources set and bark if unbalanced resources are found. */
+ for (i = set_begin (&ctx->resources_set),
+ last = set_end (&ctx->resources_set);
+ i != last;
+ i = set_next (&ctx->resources_set, i))
+ {
+ restrack_resource_t *r = PARENT_OF (restrack_resource_t, node, i);
+ if (r->references != 0)
+ {
+ if (!errors)
+ {
+ errors = true;
+ fprintf (stderr, "!! Unbalanced resources follow:\n");
+ }
+ restrack_resource_dump (r);
+ }
+ }
+ if (errors)
+ fputc ('\n', stderr);
+ return !errors;
+}
+
+void
+restrack_uninit (void)
+{
+ restrack_t *ctx = &restrack_global;
+ if (ctx->inited)
+ {
+ /* First check for leaks. */
+ restrack_check ();
+ /* Remove all resources nodes. */
+ set_node_t *i, *last, *in;
+ for (i = set_begin (&ctx->resources_set),
+ last = set_end (&ctx->resources_set);
+ i != last;
+ i = in)
+ {
+ in = set_next (&ctx->resources_set, i);
+ set_remove (&ctx->resources_set, i);
+ restrack_resource_t *r = PARENT_OF (restrack_resource_t, node, i);
+ restrack_resource_delete (r);
+ }
+ /* Prepare for an eventual reinitialisation. */
+ dbg_assert (set_empty (&ctx->resources_set));
+ ctx->inited = false;
+ }
+}
+
diff --git a/cesar/lib/src/skewheap.c b/cesar/lib/src/skewheap.c
new file mode 100644
index 0000000000..6da16d597e
--- /dev/null
+++ b/cesar/lib/src/skewheap.c
@@ -0,0 +1,138 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/src/skewheap.c
+ * \brief Skew heaps.
+ * \ingroup lib
+ */
+#include "common/std.h"
+
+#include "lib/heap.h"
+
+void
+heap_node_init (heap_node_t *node)
+{
+ node->father = NULL;
+ node->left = node->right = NULL;
+}
+
+heap_node_t *
+heap_node_merge (heap_node_t *root1, heap_node_t *root2,
+ heap_node_less_t less)
+{
+ heap_node_t *h1, *h2, *h, *root;
+ dbg_assert (!root1 || !root1->father);
+ dbg_assert (!root2 || !root2->father);
+ dbg_assert (less);
+ /* Trivial cases. */
+ if (!root1)
+ return root2;
+ else if (!root2)
+ return root1;
+ h1 = root1;
+ h2 = root2;
+ /* Skew merge root.
+ * h1 and h2: current "read" node.
+ * h: current "write" node.
+ * h->left: where the next node will be put. */
+ if (less (h1, h2))
+ {
+ h = h1;
+ h1 = h1->right;
+ }
+ else
+ {
+ h = h2;
+ h2 = h2->right;
+ }
+ root = h;
+ h->right = h->left;
+ /* Skew merge loop. */
+ while (h1 || h2)
+ {
+ if (!h2 || (h1 && less (h1, h2)))
+ {
+ h1->father = h;
+ h->left = h1;
+ h = h1;
+ h1 = h1->right;
+ }
+ else
+ {
+ h2->father = h;
+ h->left = h2;
+ h = h2;
+ h2 = h2->right;
+ }
+ h->right = h->left;
+ }
+ h->left = NULL;
+ return root;
+}
+
+void
+heap_insert (heap_t *heap, heap_node_t *node)
+{
+ dbg_assert (heap && heap->less);
+ dbg_assert (node);
+ heap->root = heap_node_merge (heap->root, node, heap->less);
+}
+
+void
+heap_remove_root (heap_t *heap)
+{
+ heap_node_t *root;
+ dbg_assert (heap);
+ dbg_assert (!heap_empty (heap));
+ root = heap->root;
+ if (root->left)
+ root->left->father = NULL;
+ if (root->right)
+ root->right->father = NULL;
+ heap->root = heap_node_merge (root->left, root->right, heap->less);
+ root->father = root->left = root->right = NULL;
+}
+
+void
+heap_remove (heap_t *heap, heap_node_t *node)
+{
+ heap_node_t **r;
+ dbg_assert (heap);
+ dbg_assert (!heap_empty (heap));
+ dbg_assert (node);
+ /* Where to store the merged tree? */
+ if (!node->father)
+ {
+ dbg_assert (node == heap->root);
+ r = &heap->root;
+ }
+ else if (node->father->right == node)
+ {
+ r = &node->father->right;
+ }
+ else
+ {
+ dbg_assert (node->father->left == node);
+ r = &node->father->left;
+ }
+ /* Need NULL father pointer. */
+ if (node->left)
+ node->left->father = NULL;
+ if (node->right)
+ node->right->father = NULL;
+ /* Merge left and right subtree. */
+ *r = heap_node_merge (node->left, node->right, heap->less);
+ if (*r)
+ (*r)->father = node->father;
+ /* Swap father children. */
+ if (node->father)
+ XCH (node->father->left, node->father->right);
+ /* Detach the removed node. */
+ node->father = node->left = node->right = NULL;
+}
+
diff --git a/cesar/lib/src/swap.c b/cesar/lib/src/swap.c
new file mode 100644
index 0000000000..cff0a9473f
--- /dev/null
+++ b/cesar/lib/src/swap.c
@@ -0,0 +1,31 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/src/swap.c
+ * \brief generic swap functions
+ * \ingroup lib
+ */
+#include "common/std.h"
+#include "lib/swap.h"
+
+/** swap an unsigned short */
+u16 swap16(u16 x)
+{
+ return (u16)( (((u16)(x) & (u16)0x00ff) << 8) |
+ (((u16)(x) & (u16)0xff00) >> 8) );
+}
+
+/** swap an unsigned long */
+u32 swap32(u32 x)
+{
+ return (u32)( (((u32)(x) & (u32)0x000000ff) << 24) |
+ (((u32)(x) & (u32)0x0000ff00) << 8) |
+ (((u32)(x) & (u32)0x00ff0000) >> 8) |
+ (((u32)(x) & (u32)0xff000000) >> 24) );
+}
+
diff --git a/cesar/lib/src/test.c b/cesar/lib/src/test.c
new file mode 100644
index 0000000000..13a14f3b19
--- /dev/null
+++ b/cesar/lib/src/test.c
@@ -0,0 +1,138 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/src/test.c
+ * \brief Test infrastructure.
+ * \ingroup lib
+ *
+ * For the moment, only stdio implementation.
+ */
+#include "common/std.h"
+
+#include "lib/test.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <signal.h>
+
+void
+test_sig_handler (int sig)
+{
+ signal (sig, test_sig_handler);
+ dbg_fatal ("Caught signal %d", sig);
+}
+
+void
+test_init (test_t t, int argc, char **argv)
+{
+ int i;
+ test_init_basic (t, 2);
+ /* Parse command line. */
+ for (i = 1; i < argc; i++)
+ {
+ if (argv[i][0] == '-')
+ {
+ const char *s = argv[i] + 1;
+ while (*s)
+ {
+ if (*s == 'v')
+ t->verbose++;
+ else if (*s == 'q')
+ t->verbose = 0;
+ s++;
+ }
+ }
+ }
+ /* Install signal handler. */
+ signal (SIGBUS, test_sig_handler);
+ signal (SIGILL, test_sig_handler);
+ signal (SIGFPE, test_sig_handler);
+ signal (SIGSEGV, test_sig_handler);
+}
+
+void
+test_init_basic (test_t t, uint verbose)
+{
+ t->current_test_suite = NULL;
+ t->current_test_case = NULL;
+ t->current_test = NULL;
+ t->test_nb = 0;
+ t->fail_nb = 0;
+ t->verbose = verbose;
+}
+
+void
+test_result (test_t t)
+{
+ int percent;
+ if (t->verbose >= 1)
+ {
+ percent = t->test_nb == 0 ? 100
+ : 100 * (t->test_nb - t->fail_nb) / t->test_nb;
+ fprintf (stderr, "%d%%, tests: %d, failures: %d\n", percent,
+ t->test_nb, t->fail_nb);
+ }
+}
+
+void
+test_suite_begin (test_t t, const char *name)
+{
+ t->current_test_suite = name;
+ if (t->verbose >= 2)
+ fprintf (stderr, "running suite: %s\n", name);
+}
+
+void
+test_case_begin (test_t t, const char *name)
+{
+ t->current_test_case = name;
+}
+
+void
+test_failled (void)
+{
+}
+
+void
+test_format_ (test_t t, const char *file, int line, char type,
+ const char *ufmt, const char *fmt, ...)
+{
+ if (type == 'F')
+ test_failled ();
+ if (t->verbose >= 4
+ || (t->verbose >= 3 && type == 'P')
+ || (t->verbose >= 2 && type == 'F'))
+ {
+ fprintf (stderr, "%s:%d:%c:%s:%s: ", file, line, type,
+ t->current_test_case ? t->current_test_case : "unknown",
+ t->current_test);
+ if (fmt)
+ {
+ va_list ap;
+ va_start (ap, fmt);
+ vfprintf (stderr, fmt, ap);
+ va_end (ap);
+ fputc ('\n', stderr);
+ }
+ else
+ {
+ fprintf (stderr, "%s\n", ufmt);
+ }
+ }
+}
+
+void
+test_debug_print (const char *msg, ...)
+{
+ va_list ap;
+ va_start (ap, msg);
+ vfprintf (stderr, msg, ap);
+ va_end (ap);
+ fputc ('\n', stderr);
+}
+
diff --git a/cesar/lib/src/trace.c b/cesar/lib/src/trace.c
new file mode 100644
index 0000000000..48cca1fa73
--- /dev/null
+++ b/cesar/lib/src/trace.c
@@ -0,0 +1,655 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/src/trace.c
+ * \brief Trace system.
+ * \ingroup lib
+ */
+#include "common/std.h"
+
+#include "lib/trace.h"
+#include "hal/arch/arch.h"
+#include "hal/arch/io.h"
+
+#include <stdio.h>
+
+#define TRACE_ALIGN (sizeof (u32))
+
+/** Trace system context. */
+struct trace_t
+{
+ /** List of buffers. */
+ list_t buffers;
+};
+
+static trace_t trace_global;
+
+void
+trace_init (void)
+{
+ trace_t * const ctx = &trace_global;
+ list_init (&ctx->buffers);
+}
+
+void
+trace_uninit (void)
+{
+ trace_t * const ctx = &trace_global;
+ dbg_assert (list_empty (&ctx->buffers));
+}
+
+bool
+trace_drop_chunks (uint n)
+{
+ dbg_assert (n > 0);
+ trace_t * const ctx = &trace_global;
+ /* Can not help if no trace buffers. */
+ if (list_empty (&ctx->buffers))
+ return false;
+ while (n)
+ {
+ /* Search the biggest buffer, taking drop level into account. */
+ trace_buffer_t *bigest_buf = NULL;
+ uint bigest_buf_size = 0, second_buf_size = 0;
+ list_node_t *i, *end;
+ i = list_begin (&ctx->buffers);
+ end = list_end (&ctx->buffers);
+ for (; i != end; i = list_next (i))
+ {
+ trace_buffer_t *buf = PARENT_OF (trace_buffer_t, node, i);
+ if (!buf->locked)
+ {
+ uint buf_size_shifted = buf->chunks_nb > buf->preload
+ ? (buf->chunks_nb - buf->preload) << buf->drop_level
+ : 0;
+ if (buf_size_shifted > bigest_buf_size)
+ {
+ second_buf_size = bigest_buf_size;
+ bigest_buf_size = buf_size_shifted;
+ bigest_buf = buf;
+ }
+ }
+ }
+ /* Drop as many block as possible to satisfy drop request. */
+ if (bigest_buf_size == 0)
+ return false;
+ uint i_can_drop = MIN (n, ((bigest_buf_size - second_buf_size +
+ (1 << bigest_buf->drop_level) - 1)
+ >> bigest_buf->drop_level));
+ trace_chunk_t *hdrop, *tdrop;
+ hdrop = bigest_buf->head;
+ tdrop = hdrop;
+ n -= i_can_drop;
+ arch_atomic_add ((int *) &bigest_buf->chunks_nb, -i_can_drop);
+ while (--i_can_drop)
+ tdrop = tdrop->next;
+ bigest_buf->head = tdrop->next;
+ blk_release_desc_range ((blk_t *) hdrop, (blk_t *) tdrop);
+ }
+ return true;
+}
+
+static int
+trace_format_bool (char *text, uint text_size, int data)
+{
+ const char *t;
+ uint ts;
+ if (!data)
+ {
+ t = "false"; ts = 5;
+ }
+ else
+ {
+ t = "true"; ts = 4;
+ }
+ if (ts > text_size)
+ return -1;
+ else
+ {
+ memcpy (text, t, ts);
+ return ts;
+ }
+}
+
+static int
+trace_format_decimal (char *text, uint text_size, int data)
+{
+ int ret = snprintf (text, text_size, "%d", data);
+ return ret < (int) text_size ? ret : -1;
+}
+
+static int
+trace_format_unsigned (char *text, uint text_size, int data)
+{
+ int ret = snprintf (text, text_size, "%u", data);
+ return ret < (int) text_size ? ret : -1;
+}
+
+static int
+trace_format_hexa (char *text, uint text_size, int data)
+{
+ int ret = snprintf (text, text_size, "0x%08x", data);
+ return ret < (int) text_size ? ret : -1;
+}
+
+static const char trace_format_hexdigits[] = "0123456789abcdef";
+
+static int
+trace_format_mac (char *text, uint text_size, u64 data)
+{
+ const uint size = 3 * 6 - 1;
+ if (text_size < size)
+ return -1;
+ else
+ {
+ uint i;
+ u64 v;
+ v = data;
+ for (i = 5; i; i--)
+ {
+ *text++ = trace_format_hexdigits[(v >> 1*4) & 0xf];
+ *text++ = trace_format_hexdigits[(v >> 0*4) & 0xf];
+ *text++ = ':';
+ v >>= 8;
+ }
+ *text++ = trace_format_hexdigits[(v >> 1*4) & 0xf];
+ *text++ = trace_format_hexdigits[(v >> 0*4) & 0xf];
+ return size;
+ }
+}
+
+void
+trace_namespace_init (trace_namespace_t *ns,
+ const trace_event_id_t *event_ids, uint event_ids_nb)
+{
+ uint i;
+ dbg_assert (ns);
+ /* Initialise fields. */
+ ns->event_ids = event_ids;
+ ns->event_ids_nb = event_ids_nb;
+ for (i = 0; i < COUNT (ns->formats); i++)
+ ns->formats[i].size = 0;
+ /* Provide default useful formats. */
+ trace_namespace_register_format (ns, 'b', trace_format_bool);
+ trace_namespace_register_format (ns, 'd', trace_format_decimal);
+ trace_namespace_register_format (ns, 'u', trace_format_unsigned);
+ trace_namespace_register_format (ns, 'x', trace_format_hexa);
+ trace_namespace_register_format_u64 (ns, 'm', trace_format_mac);
+}
+
+void
+trace_namespace_register_format (trace_namespace_t *ns, char code,
+ trace_format_u32_t callback)
+{
+ dbg_assert (ns);
+ dbg_assert ((code >= 'A' && code <= 'Z') || (code >= 'a' && code <= 'z'));
+ dbg_assert (callback);
+ ns->formats[code - 'A'].callback.format_u32 = callback;
+ ns->formats[code - 'A'].size = 1;
+}
+
+void
+trace_namespace_register_format_u64 (trace_namespace_t *ns, char code,
+ trace_format_u64_t callback)
+{
+ dbg_assert (ns);
+ dbg_assert ((code >= 'A' && code <= 'Z') || (code >= 'a' && code <= 'z'));
+ dbg_assert (callback);
+ ns->formats[code - 'A'].callback.format_u64 = callback;
+ ns->formats[code - 'A'].size = 2;
+}
+
+void
+trace_buffer_add (trace_buffer_t *buf, const char *name, uint drop_level,
+ uint preload, bool locked, trace_namespace_t *namespace)
+{
+ dbg_assert (buf);
+ dbg_assert (name);
+ dbg_assert (preload > 0);
+ trace_t * const ctx = &trace_global;
+ /* Initialise trace buffer. */
+ list_init_node (&buf->node);
+ buf->chunks_nb = preload;
+ buf->drop_level = drop_level;
+ buf->preload = preload;
+ buf->locked = locked;
+ buf->namespace = namespace;
+ /* Allocate chunks. */
+ blk_t *tail;
+ buf->head = (trace_chunk_t *) blk_alloc_desc_range (preload, &tail);
+ buf->tail = (trace_chunk_t *) tail;
+ /* Initialise chunks. */
+ trace_chunk_t *i = buf->head;
+ do
+ {
+ i->data_end = i->data;
+ i->chunk_end = i->data + BLK_SIZE / TRACE_ALIGN;
+ if (i == buf->tail)
+ break;
+ i = i->next;
+ } while (1);
+ /* Add it to context. */
+ list_push (&ctx->buffers, &buf->node);
+}
+
+void
+trace_buffer_remove (trace_buffer_t *buf)
+{
+ dbg_assert (buf);
+ trace_t * const ctx = &trace_global;
+ /* Remove from context. */
+ list_remove (&ctx->buffers, &buf->node);
+ /* Release chunks. */
+ blk_release_desc_range ((blk_t *) buf->head, (blk_t *) buf->tail);
+}
+
+static int
+trace_buffer_dump_event (char *text, char *text_end,
+ trace_namespace_t *namespace,
+ uint **data, uint *data_end)
+{
+ dbg_assert (text && text_end && text < text_end);
+ dbg_assert (namespace);
+ dbg_assert (data && *data && data_end && *data < data_end);
+ /* Read event ID. */
+ uint id = **data;
+ uint args = id & 0xff;
+ id >>= 8;
+ uint oargs = args;
+ int *parg = (int *) *data + 1;
+ dbg_assert (parg + args <= (int *) data_end);
+ dbg_assert (id < namespace->event_ids_nb);
+ const trace_event_id_t *ei = &namespace->event_ids[id];
+ dbg_assert (ei->format_string);
+ char *p = text;
+ /* Print time stamp. */
+ if (ei->timestamp)
+ {
+ dbg_assert (args);
+ args--;
+ int ret = snprintf (p, text_end - p, "[0x%08x] ", *parg++);
+ if (ret >= text_end - p)
+ return -1;
+ p += ret;
+ }
+ else
+ {
+ int ret = snprintf (p, text_end - p, "[.] ");
+ if (ret >= text_end - p)
+ return -1;
+ p += ret;
+ }
+ /* Decode format string. */
+ const char *fp;
+ for (fp = ei->format_string; *fp; fp++)
+ {
+ if (*fp == '%' && *++fp != '%')
+ {
+ dbg_assert (((*fp >= 'A' && *fp <= 'Z')
+ || (*fp >= 'a' && *fp <= 'z'))
+ && namespace->formats[*fp - 'A'].size);
+ int ret;
+ if (namespace->formats[*fp - 'A'].size == 1)
+ {
+ dbg_assert (args);
+ args--;
+ ret = namespace->formats[*fp - 'A'].callback.format_u32 (
+ p, text_end - p, *parg++);
+ }
+ else
+ {
+ dbg_assert (args >= 2);
+ args -= 2;
+ u64 arg = (u64) parg[1] << 32 | parg[0];
+ ret = namespace->formats[*fp - 'A'].callback.format_u64 (
+ p, text_end - p, arg);
+ parg += 2;
+ }
+ if (ret == -1)
+ return -1;
+ p += ret;
+ }
+ else
+ {
+ /* No room left, cancel the dump of this event. */
+ if (p == text_end)
+ return -1;
+ *p++ = *fp;
+ }
+ }
+ dbg_assert (args == 0);
+ /* No room left for the trailing new line, cancel the dump of this
+ * event. */
+ if (p == text_end)
+ return -1;
+ *p++ = '\n';
+ *data += 1 + oargs;
+ return p - text;
+}
+
+int
+trace_buffer_dump (trace_buffer_t *buf, trace_dump_callback_t cb, void *user)
+{
+#define DUMP_TEXT_SLACK 20
+ char text[2000];
+ int text_size = 0;
+ trace_chunk_t *head, *tail;
+ u32 *data, *data_end;
+ int sum = 0;
+ /* TODO: acquire lock, increment reference counter. */
+ tail = buf->tail;
+ head = buf->head;
+ /* Loop for each chunks. */
+ do
+ {
+ data = head->data;
+ data_end = head->data_end;
+ /* Loop on this chunk. */
+ while (data < data_end)
+ {
+ int ret = trace_buffer_dump_event (
+ text + text_size, text + COUNT (text),
+ buf->namespace, &data, data_end);
+ if (ret != -1)
+ text_size += ret;
+ if (ret == -1
+ || text_size + DUMP_TEXT_SLACK >= (int) COUNT (text))
+ {
+ dbg_assert (text_size != 0);
+ if (cb (user, text, text_size) != text_size)
+ {
+ /* Get out. */
+ sum = -1;
+ break;
+ }
+ sum += text_size;
+ text_size = 0;
+ }
+ }
+ if (sum == -1 || head == tail)
+ break;
+ head = head->next;
+ } while (1);
+ /* Final text. */
+ if (sum != -1 && text_size)
+ {
+ if (cb (user, text, text_size) != text_size)
+ sum = -1;
+ else
+ sum += text_size;
+ }
+ return sum;
+}
+
+static int
+trace_buffer_dbg_dump_callback (void *user, char *text, uint text_size)
+{
+ dbg_assert (text && text_size);
+ arch_io_write (text, text_size);
+ return text_size;
+}
+
+void
+trace_buffer_dbg_dump (trace_buffer_t *buf)
+{
+ trace_buffer_dump (buf, trace_buffer_dbg_dump_callback, NULL);
+}
+
+static void
+trace_printn_prepare (trace_buffer_t *buf, uint count)
+{
+ dbg_assert (buf && buf->tail);
+ trace_chunk_t *tail = buf->tail;
+ if (DEBUG_MORE)
+ dbg_assert (tail->data <= tail->data_end
+ && tail->data_end <= tail->chunk_end);
+ if (tail->data_end + count > tail->chunk_end)
+ {
+ /* No room left, allocate a new chunk. */
+ dbg_assert (!buf->locked);
+ trace_chunk_t *c = (trace_chunk_t *) blk_alloc_desc ();
+ c->data_end = c->data;
+ c->chunk_end = c->data + BLK_SIZE / TRACE_ALIGN;
+ tail->next = c;
+ REORDER_BARRIER ();
+ buf->tail = c;
+ REORDER_BARRIER ();
+ arch_atomic_add ((int *) &buf->chunks_nb, 1);
+ REORDER_BARRIER ();
+ }
+}
+
+void
+trace_print0 (trace_buffer_t *buf, uint id)
+{
+ trace_printn_prepare (buf, 1);
+ trace_fast_print0 (buf, id);
+}
+
+void
+trace_print1 (trace_buffer_t *buf, uint id, int arg0)
+{
+ trace_printn_prepare (buf, 2);
+ trace_fast_print1 (buf, id, arg0);
+}
+
+void
+trace_print2 (trace_buffer_t *buf, uint id, int arg0, int arg1)
+{
+ trace_printn_prepare (buf, 3);
+ trace_fast_print2 (buf, id, arg0, arg1);
+}
+
+void
+trace_print3 (trace_buffer_t *buf, uint id, int arg0, int arg1, int arg2)
+{
+ trace_printn_prepare (buf, 4);
+ trace_fast_print3 (buf, id, arg0, arg1, arg2);
+}
+
+void
+trace_print4 (trace_buffer_t *buf, uint id, int arg0, int arg1, int arg2,
+ int arg3)
+{
+ trace_printn_prepare (buf, 5);
+ trace_fast_print4 (buf, id, arg0, arg1, arg2, arg3);
+}
+
+void
+trace_print5 (trace_buffer_t *buf, uint id, int arg0, int arg1, int arg2,
+ int arg3, int arg4)
+{
+ trace_printn_prepare (buf, 6);
+ trace_fast_print5 (buf, id, arg0, arg1, arg2, arg3, arg4);
+}
+
+void
+trace_print6 (trace_buffer_t *buf, uint id, int arg0, int arg1, int arg2,
+ int arg3, int arg4, int arg5)
+{
+ trace_printn_prepare (buf, 7);
+ trace_fast_print6 (buf, id, arg0, arg1, arg2, arg3, arg4, arg5);
+}
+
+void
+trace_print7 (trace_buffer_t *buf, uint id, int arg0, int arg1, int arg2,
+ int arg3, int arg4, int arg5, int arg6)
+{
+ trace_printn_prepare (buf, 8);
+ trace_fast_print7 (buf, id, arg0, arg1, arg2, arg3, arg4, arg5, arg6);
+}
+
+void
+trace_print8 (trace_buffer_t *buf, uint id, int arg0, int arg1, int arg2,
+ int arg3, int arg4, int arg5, int arg6, int arg7)
+{
+ trace_printn_prepare (buf, 9);
+ trace_fast_print8 (buf, id, arg0, arg1, arg2, arg3, arg4, arg5, arg6,
+ arg7);
+}
+
+extern inline u32 *
+trace_fast_printn_prepare (trace_buffer_t *buf, uint count)
+{
+ /* "Fast" means no allocation. */
+ if (DEBUG_MORE)
+ dbg_assert (buf && buf->tail);
+ trace_chunk_t *tail = buf->tail;
+ if (DEBUG_MORE)
+ dbg_assert (tail->data <= tail->data_end
+ && tail->data_end <= tail->chunk_end);
+ u32 *data_end = tail->data_end;
+ if (data_end + count > tail->chunk_end)
+ {
+ /* No room left, use the oldest chunk for the new chunk. */
+ if (DEBUG_MORE)
+ dbg_assert (buf->head && buf->locked);
+ trace_chunk_t *head = buf->head;
+ tail->next = head;
+ buf->tail = head;
+ buf->head = head->next;
+ tail = head;
+ data_end = tail->data;
+ tail->data_end = data_end;
+ tail->chunk_end = data_end + BLK_SIZE / TRACE_ALIGN;
+ }
+ /* Dump to buffer. */
+ return data_end;
+}
+
+void
+trace_fast_print0 (trace_buffer_t *buf, uint id)
+{
+ u32 *p = trace_fast_printn_prepare (buf, 1);
+ *p++ = id << 8 | 0;
+ trace_chunk_t *tail = buf->tail;
+ REORDER_BARRIER ();
+ tail->data_end = p;
+}
+
+void
+trace_fast_print1 (trace_buffer_t *buf, uint id, int arg0)
+{
+ u32 *p = trace_fast_printn_prepare (buf, 2);
+ *p++ = id << 8 | 1;
+ *p++ = arg0;
+ trace_chunk_t *tail = buf->tail;
+ REORDER_BARRIER ();
+ tail->data_end = p;
+}
+
+void
+trace_fast_print2 (trace_buffer_t *buf, uint id, int arg0, int arg1)
+{
+ u32 *p = trace_fast_printn_prepare (buf, 3);
+ *p++ = id << 8 | 2;
+ *p++ = arg0;
+ *p++ = arg1;
+ trace_chunk_t *tail = buf->tail;
+ REORDER_BARRIER ();
+ tail->data_end = p;
+}
+
+void
+trace_fast_print3 (trace_buffer_t *buf, uint id, int arg0, int arg1, int arg2)
+{
+ u32 *p = trace_fast_printn_prepare (buf, 4);
+ *p++ = id << 8 | 3;
+ *p++ = arg0;
+ *p++ = arg1;
+ *p++ = arg2;
+ trace_chunk_t *tail = buf->tail;
+ REORDER_BARRIER ();
+ tail->data_end = p;
+}
+
+void
+trace_fast_print4 (trace_buffer_t *buf, uint id, int arg0, int arg1, int arg2,
+ int arg3)
+{
+ u32 *p = trace_fast_printn_prepare (buf, 5);
+ *p++ = id << 8 | 4;
+ *p++ = arg0;
+ *p++ = arg1;
+ *p++ = arg2;
+ *p++ = arg3;
+ trace_chunk_t *tail = buf->tail;
+ REORDER_BARRIER ();
+ tail->data_end = p;
+}
+
+void
+trace_fast_print5 (trace_buffer_t *buf, uint id, int arg0, int arg1, int arg2,
+ int arg3, int arg4)
+{
+ u32 *p = trace_fast_printn_prepare (buf, 6);
+ *p++ = id << 8 | 5;
+ *p++ = arg0;
+ *p++ = arg1;
+ *p++ = arg2;
+ *p++ = arg3;
+ *p++ = arg4;
+ trace_chunk_t *tail = buf->tail;
+ REORDER_BARRIER ();
+ tail->data_end = p;
+}
+
+void
+trace_fast_print6 (trace_buffer_t *buf, uint id, int arg0, int arg1, int arg2,
+ int arg3, int arg4, int arg5)
+{
+ u32 *p = trace_fast_printn_prepare (buf, 7);
+ *p++ = id << 8 | 6;
+ *p++ = arg0;
+ *p++ = arg1;
+ *p++ = arg2;
+ *p++ = arg3;
+ *p++ = arg4;
+ *p++ = arg5;
+ trace_chunk_t *tail = buf->tail;
+ REORDER_BARRIER ();
+ tail->data_end = p;
+}
+
+void
+trace_fast_print7 (trace_buffer_t *buf, uint id, int arg0, int arg1, int arg2,
+ int arg3, int arg4, int arg5, int arg6)
+{
+ u32 *p = trace_fast_printn_prepare (buf, 8);
+ *p++ = id << 8 | 7;
+ *p++ = arg0;
+ *p++ = arg1;
+ *p++ = arg2;
+ *p++ = arg3;
+ *p++ = arg4;
+ *p++ = arg5;
+ *p++ = arg6;
+ trace_chunk_t *tail = buf->tail;
+ REORDER_BARRIER ();
+ tail->data_end = p;
+}
+
+void
+trace_fast_print8 (trace_buffer_t *buf, uint id, int arg0, int arg1, int arg2,
+ int arg3, int arg4, int arg5, int arg6, int arg7)
+{
+ u32 *p = trace_fast_printn_prepare (buf, 9);
+ *p++ = id << 8 | 8;
+ *p++ = arg0;
+ *p++ = arg1;
+ *p++ = arg2;
+ *p++ = arg3;
+ *p++ = arg4;
+ *p++ = arg5;
+ *p++ = arg6;
+ *p++ = arg7;
+ trace_chunk_t *tail = buf->tail;
+ REORDER_BARRIER ();
+ tail->data_end = p;
+}
+
diff --git a/cesar/lib/src/try.c b/cesar/lib/src/try.c
new file mode 100644
index 0000000000..37e8a398d5
--- /dev/null
+++ b/cesar/lib/src/try.c
@@ -0,0 +1,17 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/src/try.c
+ * \brief Light exception system.
+ * \ingroup lib
+ */
+#include "common/std.h"
+
+#include "lib/try.h"
+
+jmp_buf *try_state_;
diff --git a/cesar/lib/swap.h b/cesar/lib/swap.h
new file mode 100644
index 0000000000..fbe2a9ffdc
--- /dev/null
+++ b/cesar/lib/swap.h
@@ -0,0 +1,38 @@
+#ifndef lib_swap_h
+#define lib_swap_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/swap.h
+ * \brief generic swap functions
+ * \ingroup lib
+ */
+
+/** swap an unsigned short */
+extern u16 swap16(u16 x);
+
+/** swap an unsigned long */
+extern u32 swap32(u32 x);
+
+#if DEFS_BIG_ENDIAN
+
+#define ntohs(x) (x)
+#define ntohl(x) (x)
+#define htons(x) (x)
+#define htonl(x) (x)
+
+#else
+
+#define ntohs(x) (swap16(x))
+#define ntohl(x) (swap32(x))
+#define htons(x) (swap16(x))
+#define htonl(x) (swap32(x))
+
+#endif
+
+#endif /* lib_swap_h */
diff --git a/cesar/lib/test.h b/cesar/lib/test.h
new file mode 100644
index 0000000000..396a61bfed
--- /dev/null
+++ b/cesar/lib/test.h
@@ -0,0 +1,228 @@
+#ifndef lib_test_h
+#define lib_test_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/test.h
+ * \brief Test infrastructure.
+ * \ingroup lib
+ */
+
+#include "lib/try.h"
+
+/** Test context. */
+struct test_t
+{
+ /** Current test suite. */
+ const char *current_test_suite;
+ /** Current test case name. */
+ const char *current_test_case;
+ /** Current test name. */
+ const char *current_test;
+ /** Number of attempted tests. */
+ uint test_nb;
+ /** Number of failed tests. */
+ uint fail_nb;
+ /** Verbosity, 0 to 3. */
+ uint verbose;
+};
+typedef struct test_t test_t[1];
+
+/**
+ * Initialise the test context.
+ * \param t test context
+ * \param argc program arguments count
+ * \param argv program arguments values
+ *
+ * Does not complain on unrecognised arguments.
+ */
+void
+test_init (test_t t, int argc, char **argv);
+
+/**
+ * Initialise the test context without command line.
+ * \param t test context
+ * \param verbose verbosity, see test_t.
+ */
+void
+test_init_basic (test_t t, uint verbose);
+
+/**
+ * Clean up test context and print a test summary.
+ * \param t test context
+ */
+void
+test_result (test_t t);
+
+/**
+ * Query the number of attempted tests.
+ * \param t test context
+ * \return number of attempted tests
+ */
+extern inline uint
+test_nb_attempted (test_t t)
+{
+ return t->test_nb;
+}
+
+/**
+ * Query the number of failed tests.
+ * \param t test context
+ * \return number of failed tests
+ */
+extern inline uint
+test_nb_failed (test_t t)
+{
+ return t->fail_nb;
+}
+
+/**
+ * Begin a new test suite.
+ * \param t test context
+ * \param name test suite name
+ */
+void
+test_suite_begin (test_t t, const char *name);
+
+/**
+ * Begin a new test case.
+ * \param t test context
+ * \param name test case name
+ */
+void
+test_case_begin (test_t t, const char *name);
+
+/**
+ * Just a empty function to place a breakpoint.
+ */
+void
+test_failled (void);
+
+/**
+ * Format a test related message.
+ * \param t test context
+ * \param file source file name
+ * \param line source file line
+ * \param type message type ('F': fail, 'P': pass, 'V': verbose message)
+ * \param ufmt unformatted message, used if fmt is NULL
+ * \param fmt printf-like formatted message
+ */
+void
+test_format_ (test_t t, const char *file, int line, char type,
+ const char *ufmt, const char *fmt, ...);
+
+/**
+ * Begin a test.
+ * \param t test context
+ * \param name test name
+ *
+ * This macro and its peer \c test_end use a syntax similar to a do { ... }
+ * while (); block. On failure, non volatile local variables have unspecified
+ * value, see \c setjmp for details.
+ */
+#define test_begin(t, name) test_begin_ ((t), (name))
+
+/** End a test, see \c test_begin(). */
+#define test_end test_end_
+
+/**
+ * Use this macro when at the start of a function called within a test.
+ * \param t test context
+ */
+#define test_within(t) test_within_ (t)
+
+#define test_begin_(t, name) \
+{ \
+ struct test_t *please_use_test_begin__ = (t); \
+ please_use_test_begin__->current_test = (name); \
+ please_use_test_begin__->test_nb++; \
+ try_begin \
+ { \
+ dbg_fatal_try_begin \
+ {
+
+#define test_end_ \
+ } \
+ dbg_fatal_try_catch (const char *fatal_msg) \
+ { \
+ test_fail_unless_ (0, NULL, "assertion caught:\n%s", fatal_msg); \
+ } \
+ dbg_fatal_try_end; \
+ test_format_ (please_use_test_begin__, __FILE__, __LINE__, 'P', \
+ "passed", NULL); \
+ } \
+ try_catch (TRY_CODE_TEST_FAILURE) \
+ { \
+ please_use_test_begin__->fail_nb++; \
+ } \
+ try_always \
+ { \
+ please_use_test_begin__->current_test = NULL; \
+ } \
+ try_end; \
+}
+
+#define test_within_(t) \
+ struct test_t *please_use_test_begin__ = (t)
+
+#define test_abort_() \
+ try_throw (TRY_CODE_TEST_FAILURE)
+
+/**
+ * Report the test failure unless the provided expression evaluate to true.
+ * \param expr the assumed truth
+ * \param msg optional printf-like formated message
+ */
+#define test_fail_unless(expr, msg...) \
+ test_fail_unless_ ((expr), "`" #expr "' failed", ## msg)
+
+/**
+ * Report the test failure if the provided expression evaluate to true.
+ * \param expr the fatal expression
+ * \param msg optional printf-like formated message
+ */
+#define test_fail_if(expr, msg...) \
+ test_fail_unless_ (!(expr), "`" #expr "' triggered", ## msg)
+
+/**
+ * Report the test failure unconditionally.
+ * \param msg optional printf-like formated message
+ */
+#define test_fail(msg...) \
+ test_fail_unless_ (0, "failed", ## msg)
+
+#define test_fail_unless_(expr, exprs, msg...) \
+ do { \
+ if (!(expr)) \
+ { \
+ test_format_ (please_use_test_begin__, __FILE__, __LINE__, 'F', \
+ exprs, ##msg, NULL); \
+ test_abort_ (); \
+ } \
+ } while (0)
+
+/**
+ * Print additional information only when very verbose.
+ * \param msg printf-like formated message
+ */
+#define test_verbose_print(msg...) test_verbose_print_ (msg)
+
+#define test_verbose_print_(msg...) \
+ do { \
+ test_format_ (please_use_test_begin__, __FILE__, __LINE__, 'V', \
+ NULL, msg, NULL); \
+ } while (0)
+
+/**
+ * Print debug information.
+ * \param msg printf-like formated message
+ */
+void
+test_debug_print (const char *msg, ...);
+
+#endif /* lib_test_h */
diff --git a/cesar/lib/test/atox/Makefile b/cesar/lib/test/atox/Makefile
new file mode 100644
index 0000000000..3d87a51f03
--- /dev/null
+++ b/cesar/lib/test/atox/Makefile
@@ -0,0 +1,7 @@
+BASE = ../../..
+
+HOST_PROGRAMS = test_atox
+test_atox_SOURCES = test_atox.c
+test_atox_MODULES = lib
+
+include $(BASE)/common/make/top.mk
diff --git a/cesar/lib/test/atox/src/test_atox.c b/cesar/lib/test/atox/src/test_atox.c
new file mode 100644
index 0000000000..25d8ac6170
--- /dev/null
+++ b/cesar/lib/test/atox/src/test_atox.c
@@ -0,0 +1,117 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/test/circular_list/src/test_circular.c
+ * \brief « brief description »
+ * \ingroup « module »
+ *
+ * « long description »
+ */
+#include "common/std.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "lib/test.h"
+#include "lib/atox.h"
+
+#define TEST_VAL_MAX 10
+
+static char buffer[21];
+
+void atox_basic_test_case(test_t test)
+{
+ int fd, i;
+ int i_val, i_res;
+ long l_val, l_res;
+ long long ll_val, ll_res;
+ long ul_val, ul_res;
+ long long ull_val, ull_res;
+
+ fd = open("/dev/urandom", O_RDONLY);
+
+ test_begin (test, "atoi")
+ {
+ for(i=0;i<TEST_VAL_MAX;i++)
+ {
+ read(fd, (void *)&i_val, sizeof(int));
+ sprintf(buffer, "%d", i_val);
+ i_res = atoi(buffer);
+ test_fail_if (i_res != i_val, "Wrong convertion");
+ }
+ }
+ test_end;
+
+ test_begin (test, "atol")
+ {
+ for(i=0;i<TEST_VAL_MAX;i++)
+ {
+ read(fd, (void *)&l_val, sizeof(long));
+ sprintf(buffer, "%ld", l_val);
+ l_res = atol(buffer);
+ test_fail_if (l_res != l_val, "Wrong convertion");
+ }
+ }
+ test_end;
+
+ test_begin (test, "atoll")
+ {
+ for(i=0;i<TEST_VAL_MAX;i++)
+ {
+ read(fd, (void *)&ll_val, sizeof(long long));
+ sprintf(buffer, "%lld", ll_val);
+ ll_res = atoll(buffer);
+ test_fail_if (ll_res != ll_val, "Wrong convertion");
+ }
+ }
+ test_end;
+
+ test_begin (test, "atoul")
+ {
+ for(i=0;i<TEST_VAL_MAX;i++)
+ {
+ read(fd, (void *)&ul_val, sizeof(long));
+ sprintf(buffer, "%lu", ul_val);
+ ul_res = atoul(buffer);
+ test_fail_if (ul_res != ul_val, "Wrong convertion");
+ }
+ }
+ test_end;
+
+ test_begin (test, "atoull")
+ {
+ for(i=0;i<TEST_VAL_MAX;i++)
+ {
+ read(fd, (void *)&ull_val, sizeof(long long));
+ sprintf(buffer, "%llu", ull_val);
+ ull_res = atoull(buffer);
+ test_fail_if (ull_res != ull_val, "Wrong convertion");
+ }
+ }
+ test_end;
+
+ close(fd);
+}
+
+int main (int argc, char **argv)
+{
+ test_t test;
+
+ test_init(test, argc, argv);
+ test_case_begin(test, "Basic");
+
+ atox_basic_test_case(test);
+
+ test_result(test);
+ return test_nb_failed(test) == 0 ? 0 : 1;
+}
+
diff --git a/cesar/lib/test/bitstream/Config b/cesar/lib/test/bitstream/Config
new file mode 100644
index 0000000000..7a62a6fa97
--- /dev/null
+++ b/cesar/lib/test/bitstream/Config
@@ -0,0 +1 @@
+CONFIG_DEBUG = y
diff --git a/cesar/lib/test/bitstream/Makefile b/cesar/lib/test/bitstream/Makefile
new file mode 100644
index 0000000000..e308fb303d
--- /dev/null
+++ b/cesar/lib/test/bitstream/Makefile
@@ -0,0 +1,7 @@
+BASE = ../../..
+
+HOST_PROGRAMS = test_bit
+test_bit_SOURCES = test_bit.c
+test_bit_MODULES = lib
+
+include $(BASE)/common/make/top.mk
diff --git a/cesar/lib/test/bitstream/src/test_bit.c b/cesar/lib/test/bitstream/src/test_bit.c
new file mode 100644
index 0000000000..4c3def84f6
--- /dev/null
+++ b/cesar/lib/test/bitstream/src/test_bit.c
@@ -0,0 +1,222 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/test_bit.c
+ * \brief Bit stream and bit array test.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "lib/bitstream.h"
+#include "lib/test.h"
+
+void
+bitstream_basic_test_case (test_t t)
+{
+ test_case_begin (t, "basic");
+ /* Read tests */
+ test_begin (t, "read")
+ {
+ bitstream_t bsr;
+ u8 bit8 = 0; u16 bit16 = 0; u32 bit32 = 0;
+ static const u32 s[] = { 0x76543210, 0xfedcba98, 0x12345678 };
+
+ bitstream_init (&bsr, (void*)s, sizeof (s), BITSTREAM_READ);
+ test_fail_unless (bitstream_access (&bsr, &bit8, 8)
+ && bit8 == 0x10);
+ test_fail_unless (bitstream_available_bits (&bsr) == 88);
+ test_fail_unless (bitstream_access (&bsr, &bit16, 16)
+ && bit16 == 0x5432);
+ test_fail_unless (bitstream_available_bits (&bsr) == 72);
+ test_fail_unless (bitstream_access (&bsr, &bit8, 4)
+ && bit8 == 0x6);
+ test_fail_unless (bitstream_available_bits (&bsr) == 68);
+ test_fail_unless (bitstream_access (&bsr, &bit16, 12)
+ && bit16 == 0x987);
+ test_fail_unless (bitstream_available_bits (&bsr) == 56);
+ test_fail_unless (bitstream_access (&bsr, &bit32, 32)
+ && bit32 == 0x78fedcba);
+ test_fail_unless (bitstream_available_bits (&bsr) == 24);
+ test_fail_unless (bitstream_access (&bsr, &bit32, 24)
+ && bit32 == 0x123456);
+ test_fail_unless (bitstream_available_bits (&bsr) == 0);
+ } test_end;
+ test_begin (t, "read_large")
+ {
+ u64 bit64 = 0;
+ bitstream_t bsr;
+ static const u32 s[] = { 0x76543210, 0xfedcba98, 0x12345678 };
+ bitstream_init (&bsr, (void*)s, sizeof (s), BITSTREAM_READ);
+ test_fail_unless (bitstream_access (&bsr, &bit64, 48)
+ && bit64 == 0xba9876543210LL);
+ test_fail_unless (bitstream_available_bits (&bsr) == 48);
+ test_fail_unless (bitstream_access (&bsr, &bit64, 24)
+ && bit64 == 0x78fedcLL);
+ test_fail_unless (bitstream_available_bits (&bsr) == 24);
+ test_fail_unless (bitstream_access (&bsr, &bit64, 24)
+ && bit64 == 0x123456LL);
+ test_fail_unless (bitstream_available_bits (&bsr) == 0);
+ } test_end;
+ test_begin (t, "direct_read")
+ {
+ static const u32 s[] = { 0x76543210, 0xfedcba98, 0x12345678 };
+ test_fail_unless (bitstream_direct_read ((void*)s, 0, 8) == 0x10);
+ test_fail_unless (bitstream_direct_read ((void*)s, 8, 16) == 0x5432);
+ test_fail_unless (bitstream_direct_read ((void*)s, 24, 4) == 0x6);
+ test_fail_unless (bitstream_direct_read ((void*)s, 28, 12) == 0x987);
+ test_fail_unless (bitstream_direct_read ((void*)s, 40, 32)
+ == 0x78fedcba);
+ test_fail_unless (bitstream_direct_read ((void*)s, 72, 24)
+ == 0x123456);
+
+ } test_end;
+ test_begin (t, "direct_read_large")
+ {
+ static const u32 s[] = { 0x76543210, 0xfedcba98, 0x12345678 };
+ test_fail_unless (bitstream_direct_read_large ((void*)s, 0, 48)
+ == 0xba9876543210LL);
+ test_fail_unless (bitstream_direct_read_large ((void*)s, 48, 24)
+ == 0x78fedcLL);
+ test_fail_unless (bitstream_direct_read_large ((void*)s, 72, 24)
+ == 0x123456LL);
+ } test_end;
+ /* Write tests */
+ test_begin (t, "write")
+ {
+ bitstream_t bsw;
+ u8 bit8; u16 bit16; u32 bit32;
+ u32 s[4] = { [3] = 0xabba5555 };
+ bitstream_init (&bsw, (void*)s, sizeof(s) - 4, BITSTREAM_WRITE);
+ bit8 = 0x10;
+ bitstream_access (&bsw, &bit8, 8);
+ test_fail_unless (bitstream_available_bits (&bsw) == 88);
+ bit16 = 0x5432;
+ bitstream_access (&bsw, &bit16, 16);
+ test_fail_unless (bitstream_available_bits (&bsw) == 72);
+ bit8 = 0x6;
+ bitstream_access (&bsw, &bit8, 4);
+ test_fail_unless (bitstream_available_bits (&bsw) == 68);
+ bit16 = 0x987;
+ bitstream_access (&bsw, &bit16, 12);
+ test_fail_unless (bitstream_available_bits (&bsw) == 56);
+ bit32 = 0x78fedcba;
+ bitstream_access (&bsw, &bit32, 32);
+ test_fail_unless (bitstream_available_bits (&bsw) == 24);
+ bit32 = 0x123456;
+ bitstream_access (&bsw, &bit32, 24);
+ test_fail_unless (bitstream_available_bits (&bsw) == 0);
+ test_fail_unless (bitstream_finalise (&bsw) == 32);
+ test_fail_unless (s[0] == 0x76543210
+ && s[1] == 0xfedcba98
+ && s[2] == 0x12345678
+ && s[3] == 0xabba5555);
+ } test_end;
+ test_begin (t, "write_large")
+ {
+ u64 bit64;
+ bitstream_t bsw;
+ u32 s[4] = { [3] = 0xabba5555 };
+ bitstream_init (&bsw, (void*)s, sizeof(s) - 4, BITSTREAM_WRITE);
+ bit64 = 0xba9876543210LL;
+ bitstream_access (&bsw, &bit64, 48);
+ test_fail_unless (bitstream_available_bits (&bsw) == 48);
+ bit64 = 0x78fedcLL;
+ bitstream_access (&bsw, &bit64, 24);
+ test_fail_unless (bitstream_available_bits (&bsw) == 24);
+ bit64 = 0x123456LL;
+ bitstream_access (&bsw, &bit64, 24);
+ test_fail_unless (bitstream_available_bits (&bsw) == 0);
+ test_fail_unless (bitstream_finalise (&bsw) == 32);
+ test_fail_unless (s[0] == 0x76543210
+ && s[1] == 0xfedcba98
+ && s[2] == 0x12345678
+ && s[3] == 0xabba5555);
+ } test_end;
+ test_begin (t, "direct_write")
+ {
+ u32 s[4] = { [3] = 0xabba5555 };
+ bitstream_direct_write ((void*)s, 0, 0x10, 8);
+ bitstream_direct_write ((void*)s, 8, 0x5432, 16);
+ bitstream_direct_write ((void*)s, 24, 0x6, 4);
+ bitstream_direct_write ((void*)s, 28, 0x987, 12);
+ bitstream_direct_write ((void*)s, 40, 0x78fedcba, 32);
+ bitstream_direct_write ((void*)s, 72, 0x123456, 24);
+ test_fail_unless (s[0] == 0x76543210
+ && s[1] == 0xfedcba98
+ && s[2] == 0x12345678
+ && s[3] == 0xabba5555);
+ } test_end;
+ test_begin (t, "direct_write_large")
+ {
+ u32 s[4] = { [3] = 0xabba5555 };
+ bitstream_direct_write_large ((void*)s, 0, 0xba9876543210LL, 48);
+ bitstream_direct_write_large ((void*)s, 48, 0x78fedcLL, 24);
+ bitstream_direct_write_large ((void*)s, 72, 0x123456LL, 24);
+ test_fail_unless (s[0] == 0x76543210
+ && s[1] == 0xfedcba98
+ && s[2] == 0x12345678
+ && s[3] == 0xabba5555);
+ } test_end;
+
+ test_begin (t, "read_unaligned")
+ {
+ u32 bit32 = 0;
+ bitstream_t bsr;
+ static const u32 s[] = { 0x76543210, 0xfedcba98, 0x12345678 };
+
+ bitstream_init (&bsr, (void*)((u8*)s+1), sizeof (s), BITSTREAM_READ);
+ test_fail_unless (bitstream_access (&bsr, &bit32, 24)
+ && bit32 == 0x765432);
+
+ bitstream_finalise (&bsr);
+ } test_end;
+ test_begin (t, "write_unaligned")
+ {
+ u16 bit16;
+ bitstream_t bsw;
+ u32 s[4] = { [0] = 0x55000088, [1] = 0xabba5555 };
+ bitstream_init (&bsw, (void*)((u8*)s+1),
+ sizeof(s) - 4, BITSTREAM_WRITE);
+
+ bit16 = 0x6677;
+ bitstream_access (&bsw, &bit16, 16);
+
+ bit16 = 0x6655;
+ bitstream_access (&bsw, &bit16, 16);
+
+ test_fail_unless (bitstream_finalise (&bsw) == 8);
+ test_fail_unless (s[0] == 0x55667788
+ && s[1] == 0xabba5566);
+ } test_end;
+ test_begin (t, "memcpy")
+ {
+ u8 data[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00 };
+ u8 copy[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff };
+ bitstream_memcpy (copy, data, sizeof(data) - 1);
+ test_fail_unless (data[6] == copy[6] && copy[7] == 0xff);
+ } test_end;
+
+ /* TODO: -- add a random number based test here --. */
+}
+
+void
+bitstream_test_suite (test_t t)
+{
+ test_suite_begin (t, "bitstream");
+ bitstream_basic_test_case (t);
+}
+
+int
+main (int argc, char **argv)
+{
+ test_t t;
+ test_init (t, argc, argv);
+ bitstream_test_suite (t);
+ test_result (t);
+ return test_nb_failed (t) == 0 ? 0 : 1;
+}
diff --git a/cesar/lib/test/blk/Makefile b/cesar/lib/test/blk/Makefile
new file mode 100644
index 0000000000..02d11eeaca
--- /dev/null
+++ b/cesar/lib/test/blk/Makefile
@@ -0,0 +1,7 @@
+BASE = ../../..
+
+HOST_PROGRAMS = test_blk
+test_blk_SOURCES = test_blk.c
+test_blk_MODULES = lib
+
+include $(BASE)/common/make/top.mk
diff --git a/cesar/lib/test/blk/src/test_blk.c b/cesar/lib/test/blk/src/test_blk.c
new file mode 100644
index 0000000000..64e94d7840
--- /dev/null
+++ b/cesar/lib/test/blk/src/test_blk.c
@@ -0,0 +1,125 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/test_blk.c
+ * \brief Test BLK.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "lib/blk.h"
+#include "lib/test.h"
+
+#include <string.h>
+
+struct test_obj_t
+{
+ void *a;
+ void *b;
+};
+typedef struct test_obj_t test_obj_t;
+
+void
+test_obj_init (test_obj_t *ctx, void *a, void *b)
+{
+ ctx->a = a;
+ blk_addref (a);
+ ctx->b = b;
+ blk_addref (b);
+}
+
+void
+test_obj_uninit (void *data)
+{
+ test_obj_t *ctx = data;
+ blk_release (ctx->a);
+ blk_release (ctx->b);
+}
+
+void
+blk_basic_test_case (test_t t)
+{
+ test_case_begin (t, "basic");
+ test_begin (t, "desc")
+ {
+ blk_t *a, *f, *l, *p;
+ /* Allocate. */
+ a = blk_alloc_desc ();
+ f = blk_alloc_desc_range (42, &l);
+ /* Write. */
+ memset ((u8 *) a + sizeof (blk_t), 42,
+ BLK_DESC_SIZE - sizeof (blk_t));
+ memset (a->data, 42, BLK_SIZE);
+ for (p = f; p != l; p = p->next)
+ {
+ memset ((u8 *) p + sizeof (blk_t), 42,
+ BLK_DESC_SIZE - sizeof (blk_t));
+ memset (p->data, 42, BLK_SIZE);
+ }
+ memset ((u8 *) p + sizeof (blk_t), 42,
+ BLK_DESC_SIZE - sizeof (blk_t));
+ memset (p->data, 42, BLK_SIZE);
+ /* Add/release refs. */
+ blk_addref_desc_range (f, l);
+ blk_addref_desc (a);
+ blk_addref_desc (f);
+ blk_addref_desc (f->next);
+ blk_addref_desc (f->next->next);
+ blk_addref_desc_range_nb (f->next->next->next, 4);
+ blk_release_desc_range (f, l);
+ blk_release_desc (a);
+ blk_release_desc (a);
+ blk_release_desc_range_nb (f->next, 6);
+ blk_release_desc_range (f, l);
+ blk_release_desc (f);
+ /* Check. */
+ test_fail_unless (blk_check_memory ());
+ } test_end;
+ test_begin (t, "obj")
+ {
+ void *a, *b, *c, *d;
+ /* Allocate. */
+ a = blk_alloc ();
+ b = blk_alloc ();
+ c = blk_alloc_zero ();
+ test_fail_unless (((u8 *)c)[42] == 0);
+ d = blk_new (test_obj_uninit);
+ test_obj_init (d, a, b);
+ /* Add/release refs. */
+ blk_release (a);
+ blk_release (b);
+ blk_addref (d);
+ blk_addref (b);
+ blk_addref (c);
+ blk_release (d);
+ blk_release (c);
+ blk_release (b);
+ blk_release (d);
+ blk_release (c);
+ /* Check. */
+ test_fail_unless (blk_check_memory ());
+ } test_end;
+ blk_print_memory ();
+}
+
+void
+blk_test_suite (test_t t)
+{
+ test_suite_begin (t, "blk");
+ blk_basic_test_case (t);
+}
+
+int
+main (int argc, char **argv)
+{
+ test_t t;
+ test_init (t, argc, argv);
+ blk_test_suite (t);
+ test_result (t);
+ return test_nb_failed (t) == 0 ? 0 : 1;
+}
diff --git a/cesar/lib/test/circular_buffer/Makefile b/cesar/lib/test/circular_buffer/Makefile
new file mode 100644
index 0000000000..68b0f7c144
--- /dev/null
+++ b/cesar/lib/test/circular_buffer/Makefile
@@ -0,0 +1,7 @@
+BASE = ../../..
+
+HOST_PROGRAMS = test_circular_list
+test_circular_list_SOURCES = test_circular.c
+test_circular_list_MODULES = lib
+
+include $(BASE)/common/make/top.mk
diff --git a/cesar/lib/test/circular_buffer/src/test_circular.c b/cesar/lib/test/circular_buffer/src/test_circular.c
new file mode 100644
index 0000000000..d7ce76e02d
--- /dev/null
+++ b/cesar/lib/test/circular_buffer/src/test_circular.c
@@ -0,0 +1,94 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/test/circular_list/src/test_circular.c
+ * \brief « brief description »
+ * \ingroup « module »
+ *
+ * « long description »
+ */
+#include "common/std.h"
+
+#include "lib/circular_buffer.h"
+#include "lib/test.h"
+
+int
+main (void)
+{
+ test_t test;
+ circular_buffer_t list;
+ u8 *my_list[4];
+ bool added;
+ u8* buffer;
+ uint i;
+
+ test_init (test, 0, NULL);
+
+ circular_buffer_init (&list, my_list, 4);
+
+ test_case_begin (test, "Add and get a buffer");
+ test_begin (test, "Add and get a buffer")
+ {
+ added = circular_buffer_add (&list, &i);
+ buffer = circular_buffer_get (&list);
+ test_fail_if (buffer != (u8 *) &i, "Wrong address");
+ }
+ test_end;
+
+ test_case_begin (test, "adding address to the buffer");
+
+ test_begin (test, "Address Add")
+ {
+ for (i = 0; i < 5; i++)
+ {
+ added = circular_buffer_add (&list, buffer);
+
+ if (i < 4)
+ {
+ test_fail_if (added != true, "Address shall be added");
+ test_fail_if (my_list[i] != list.buffer[i], "Wrong address");
+ }
+ else
+ {
+ test_fail_if (added != false, "Address shall not be added");
+ }
+ }
+ }
+ test_end;
+
+
+ buffer = circular_buffer_peek (&list);
+ test_begin (test, "Add and get a buffer")
+ {
+ buffer = circular_buffer_peek (&list);
+ test_fail_if (buffer != (u8*) &i, "Wrong address");
+ }
+ test_end;
+
+
+ test_case_begin (test, "Getting address from the buffer");
+
+ test_begin (test, "Address get")
+ {
+ for (i = 0; i < 5; i++)
+ {
+ buffer = circular_buffer_get (&list);
+
+ if (i < 4)
+ test_fail_if (buffer != (u8*) &i, "Wrong address");
+ else
+ test_fail_if (buffer != NULL, "Wrong address");
+ }
+
+ }
+ test_end;
+
+
+ test_result (test);
+ return test_nb_failed (test) == 0 ? 0 : 1;
+}
diff --git a/cesar/lib/test/crc/Makefile b/cesar/lib/test/crc/Makefile
new file mode 100644
index 0000000000..2a3ca4fd09
--- /dev/null
+++ b/cesar/lib/test/crc/Makefile
@@ -0,0 +1,7 @@
+BASE = ../../..
+
+HOST_PROGRAMS = test_crc
+test_crc_SOURCES = test_crc.c crcmodel.c
+test_crc_MODULES = lib
+
+include $(BASE)/common/make/top.mk
diff --git a/cesar/lib/test/crc/inc/crcmodel.h b/cesar/lib/test/crc/inc/crcmodel.h
new file mode 100644
index 0000000000..c06312e84f
--- /dev/null
+++ b/cesar/lib/test/crc/inc/crcmodel.h
@@ -0,0 +1,160 @@
+/******************************************************************************/
+/* Start of crcmodel.h */
+/******************************************************************************/
+/* */
+/* Author : Ross Williams (ross@guest.adelaide.edu.au.). */
+/* Date : 3 June 1993. */
+/* Status : Public domain. */
+/* */
+/* Description : This is the header (.h) file for the reference */
+/* implementation of the Rocksoft^tm Model CRC Algorithm. For more */
+/* information on the Rocksoft^tm Model CRC Algorithm, see the document */
+/* titled "A Painless Guide to CRC Error Detection Algorithms" by Ross */
+/* Williams (ross@guest.adelaide.edu.au.). This document is likely to be in */
+/* "ftp.adelaide.edu.au/pub/rocksoft". */
+/* */
+/* Note: Rocksoft is a trademark of Rocksoft Pty Ltd, Adelaide, Australia. */
+/* */
+/******************************************************************************/
+/* */
+/* How to Use This Package */
+/* ----------------------- */
+/* Step 1: Declare a variable of type cm_t. Declare another variable */
+/* (p_cm say) of type p_cm_t and initialize it to point to the first */
+/* variable (e.g. p_cm_t p_cm = &cm_t). */
+/* */
+/* Step 2: Assign values to the parameter fields of the structure. */
+/* If you don't know what to assign, see the document cited earlier. */
+/* For example: */
+/* p_cm->cm_width = 16; */
+/* p_cm->cm_poly = 0x8005L; */
+/* p_cm->cm_init = 0L; */
+/* p_cm->cm_refin = TRUE; */
+/* p_cm->cm_refot = TRUE; */
+/* p_cm->cm_xorot = 0L; */
+/* Note: Poly is specified without its top bit (18005 becomes 8005). */
+/* Note: Width is one bit less than the raw poly width. */
+/* */
+/* Step 3: Initialize the instance with a call cm_ini(p_cm); */
+/* */
+/* Step 4: Process zero or more message bytes by placing zero or more */
+/* successive calls to cm_nxt. Example: cm_nxt(p_cm,ch); */
+/* */
+/* Step 5: Extract the CRC value at any time by calling crc = cm_crc(p_cm); */
+/* If the CRC is a 16-bit value, it will be in the bottom 16 bits. */
+/* */
+/******************************************************************************/
+/* */
+/* Design Notes */
+/* ------------ */
+/* PORTABILITY: This package has been coded very conservatively so that */
+/* it will run on as many machines as possible. For example, all external */
+/* identifiers have been restricted to 6 characters and all internal ones to */
+/* 8 characters. The prefix cm (for Crc Model) is used as an attempt to avoid */
+/* namespace collisions. This package is endian independent. */
+/* */
+/* EFFICIENCY: This package (and its interface) is not designed for */
+/* speed. The purpose of this package is to act as a well-defined reference */
+/* model for the specification of CRC algorithms. If you want speed, cook up */
+/* a specific table-driven implementation as described in the document cited */
+/* above. This package is designed for validation only; if you have found or */
+/* implemented a CRC algorithm and wish to describe it as a set of parameters */
+/* to the Rocksoft^tm Model CRC Algorithm, your CRC algorithm implementation */
+/* should behave identically to this package under those parameters. */
+/* */
+/******************************************************************************/
+
+/* The following #ifndef encloses this entire */
+/* header file, rendering it indempotent. */
+#ifndef CM_DONE
+#define CM_DONE
+
+/******************************************************************************/
+
+/* The following definitions are extracted from my style header file which */
+/* would be cumbersome to distribute with this package. The DONE_STYLE is the */
+/* idempotence symbol used in my style header file. */
+
+#ifndef DONE_STYLE
+
+//#ifndef __USE_MISC
+typedef unsigned long ulong;
+//#endif
+//typedef unsigned bool;
+typedef unsigned char * p_ubyte_;
+typedef const unsigned char * cp_ubyte_;
+
+#ifndef TRUE
+#define FALSE 0
+#define TRUE 1
+#endif
+
+/* Change to the second definition if you don't have prototypes. */
+#define P_(A) A
+/* #define P_(A) () */
+
+/* Uncomment this definition if you don't have void. */
+/* typedef int void; */
+
+#endif
+
+/******************************************************************************/
+
+/* CRC Model Abstract Type */
+/* ----------------------- */
+/* The following type stores the context of an executing instance of the */
+/* model algorithm. Most of the fields are model parameters which must be */
+/* set before the first initializing call to cm_ini. */
+typedef struct
+ {
+ int cm_width; /* Parameter: Width in bits [8,32]. */
+ ulong cm_poly; /* Parameter: The algorithm's polynomial. */
+ ulong cm_init; /* Parameter: Initial register value. */
+ bool cm_refin; /* Parameter: Reflect input bytes? */
+ bool cm_refot; /* Parameter: Reflect output CRC? */
+ ulong cm_xorot; /* Parameter: XOR this to output CRC. */
+
+ ulong cm_reg; /* Context: Context during execution. */
+ } cm_t;
+typedef cm_t *p_cm_t;
+
+/******************************************************************************/
+
+/* Functions That Implement The Model */
+/* ---------------------------------- */
+/* The following functions animate the cm_t abstraction. */
+
+void cm_ini P_((p_cm_t p_cm));
+/* Initializes the argument CRC model instance. */
+/* All parameter fields must be set before calling this. */
+
+void cm_nxt P_((p_cm_t p_cm,int ch));
+/* Processes a single message byte [0,255]. */
+
+void cm_blk P_((p_cm_t p_cm,cp_ubyte_ blk_adr,ulong blk_len));
+/* Processes a block of message bytes. */
+
+ulong cm_crc P_((p_cm_t p_cm));
+/* Returns the CRC value for the message bytes processed so far. */
+
+/******************************************************************************/
+
+/* Functions For Table Calculation */
+/* ------------------------------- */
+/* The following function can be used to calculate a CRC lookup table. */
+/* It can also be used at run-time to create or check static tables. */
+
+ulong cm_tab P_((p_cm_t p_cm,int index));
+/* Returns the i'th entry for the lookup table for the specified algorithm. */
+/* The function examines the fields cm_width, cm_poly, cm_refin, and the */
+/* argument table index in the range [0,255] and returns the table entry in */
+/* the bottom cm_width bytes of the return value. */
+
+/******************************************************************************/
+
+/* End of the header file idempotence #ifndef */
+#endif
+
+/******************************************************************************/
+/* End of crcmodel.h */
+/******************************************************************************/
diff --git a/cesar/lib/test/crc/src/crcmodel.c b/cesar/lib/test/crc/src/crcmodel.c
new file mode 100644
index 0000000000..f93342a1cc
--- /dev/null
+++ b/cesar/lib/test/crc/src/crcmodel.c
@@ -0,0 +1,148 @@
+/******************************************************************************/
+/* Start of crcmodel.c */
+/******************************************************************************/
+/* */
+/* Author : Ross Williams (ross@guest.adelaide.edu.au.). */
+/* Date : 3 June 1993. */
+/* Status : Public domain. */
+/* */
+/* Description : This is the implementation (.c) file for the reference */
+/* implementation of the Rocksoft^tm Model CRC Algorithm. For more */
+/* information on the Rocksoft^tm Model CRC Algorithm, see the document */
+/* titled "A Painless Guide to CRC Error Detection Algorithms" by Ross */
+/* Williams (ross@guest.adelaide.edu.au.). This document is likely to be in */
+/* "ftp.adelaide.edu.au/pub/rocksoft". */
+/* */
+/* Note: Rocksoft is a trademark of Rocksoft Pty Ltd, Adelaide, Australia. */
+/* */
+/******************************************************************************/
+/* */
+/* Implementation Notes */
+/* -------------------- */
+/* To avoid inconsistencies, the specification of each function is not echoed */
+/* here. See the header file for a description of these functions. */
+/* This package is light on checking because I want to keep it short and */
+/* simple and portable (i.e. it would be too messy to distribute my entire */
+/* C culture (e.g. assertions package) with this package. */
+/* */
+/******************************************************************************/
+#include "common/std.h"
+#include "inc/crcmodel.h"
+
+/******************************************************************************/
+
+/* The following definitions make the code more readable. */
+
+#define BITMASK(X) (1L << (X))
+#define MASK32 0xFFFFFFFFL
+#define LOCAL static
+
+/******************************************************************************/
+
+LOCAL ulong reflect P_((ulong v,int b));
+LOCAL ulong reflect (v,b)
+/* Returns the value v with the bottom b [0,32] bits reflected. */
+/* Example: reflect(0x3e23L,3) == 0x3e26 */
+ulong v;
+int b;
+{
+ int i;
+ ulong t = v;
+ for (i=0; i<b; i++)
+ {
+ if (t & 1L)
+ v|= BITMASK((b-1)-i);
+ else
+ v&= ~BITMASK((b-1)-i);
+ t>>=1;
+ }
+ return v;
+}
+
+/******************************************************************************/
+
+LOCAL ulong widmask P_((p_cm_t));
+LOCAL ulong widmask (p_cm)
+/* Returns a longword whose value is (2^p_cm->cm_width)-1. */
+/* The trick is to do this portably (e.g. without doing <<32). */
+p_cm_t p_cm;
+{
+ return (((1L<<(p_cm->cm_width-1))-1L)<<1)|1L;
+}
+
+/******************************************************************************/
+
+void cm_ini (p_cm)
+p_cm_t p_cm;
+{
+ p_cm->cm_reg = p_cm->cm_init;
+}
+
+/******************************************************************************/
+
+void cm_nxt (p_cm,ch)
+p_cm_t p_cm;
+int ch;
+{
+ int i;
+ ulong uch = (ulong) ch;
+ ulong topbit = BITMASK(p_cm->cm_width-1);
+
+ if (p_cm->cm_refin) uch = reflect(uch,8);
+ p_cm->cm_reg ^= (uch << (p_cm->cm_width-8));
+ for (i=0; i<8; i++)
+ {
+ if (p_cm->cm_reg & topbit)
+ p_cm->cm_reg = (p_cm->cm_reg << 1) ^ p_cm->cm_poly;
+ else
+ p_cm->cm_reg <<= 1;
+ p_cm->cm_reg &= widmask(p_cm);
+ }
+}
+
+/******************************************************************************/
+
+void cm_blk (p_cm,blk_adr,blk_len)
+p_cm_t p_cm;
+cp_ubyte_ blk_adr;
+ulong blk_len;
+{
+ while (blk_len--) cm_nxt(p_cm,*blk_adr++);
+}
+
+/******************************************************************************/
+
+ulong cm_crc (p_cm)
+p_cm_t p_cm;
+{
+ if (p_cm->cm_refot)
+ return p_cm->cm_xorot ^ reflect(p_cm->cm_reg,p_cm->cm_width);
+ else
+ return p_cm->cm_xorot ^ p_cm->cm_reg;
+}
+
+/******************************************************************************/
+
+ulong cm_tab (p_cm,index)
+p_cm_t p_cm;
+int index;
+{
+ int i;
+ ulong r;
+ ulong topbit = BITMASK(p_cm->cm_width-1);
+ ulong inbyte = (ulong) index;
+
+ if (p_cm->cm_refin) inbyte = reflect(inbyte,8);
+ r = inbyte << (p_cm->cm_width-8);
+ for (i=0; i<8; i++)
+ if (r & topbit)
+ r = (r << 1) ^ p_cm->cm_poly;
+ else
+ r<<=1;
+ if (p_cm->cm_refin) r = reflect(r,p_cm->cm_width);
+ return r & widmask(p_cm);
+}
+
+/******************************************************************************/
+/* End of crcmodel.c */
+/******************************************************************************/
diff --git a/cesar/lib/test/crc/src/test_crc.c b/cesar/lib/test/crc/src/test_crc.c
new file mode 100644
index 0000000000..2e5e9aea35
--- /dev/null
+++ b/cesar/lib/test/crc/src/test_crc.c
@@ -0,0 +1,294 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/test_crc.c
+ * \brief CRC test.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "lib/rnd.h"
+#include "lib/test.h"
+
+#include "lib/crc.h"
+
+#include "inc/crcmodel.h"
+
+#include <stdio.h>
+
+void
+crc_rocksoft_model_test_case (test_t t)
+{
+ lib_rnd_t rnd[1];
+ /* Algorithms ending with ref or pat are non standard refelected or
+ * assymetric pattern algorithms in order to have a reflected CRC for each
+ * size and to test for init and xorout pattern reflections. */
+ static u32 crc32_tab[256];
+ static crc_t crc32 = { 32, 0x04c11db7, 0xffffffff, true, true, 0xffffffff,
+ 0, { .t32 = crc32_tab } };
+ static u32 crc32ref_tab[256];
+ static crc_t crc32ref = { 32, 0x04c11db7, 0xffffffff, false, false, 0xffffffff,
+ 0, { .t32 = crc32ref_tab } };
+ static u32 hpavfc_tab[256];
+ static crc_t hpavfc = { 24, 0x800063, 0xffffff, true, true, 0xffffff,
+ 0, { .t32 = hpavfc_tab } };
+ static u32 hpavfcref_tab[256];
+ static crc_t hpavfcref = { 24, 0x800063, 0xffffff, false, false, 0xffffff,
+ 0, { .t32 = hpavfcref_tab } };
+ static u16 citt_tab[256];
+ static crc_t citt = { 16, 0x1021, 0xffff, false, false, 0x0000,
+ 0, { .t16 = citt_tab } };
+ static u16 xmodem_tab[256];
+ static crc_t xmodem = { 16, 0x8408, 0x0000, true, true, 0x0000,
+ 0, { .t16 = xmodem_tab } };
+ /* This one is not that useful because HP 1.0 FC does not contain a
+ * integral number of byte. */
+ static u8 hpfc10_tab[256];
+ static crc_t hpfc10 = { 8, 0x03, 0xff, true, true, 0xff,
+ 0, { .t8 = hpfc10_tab } };
+ static u8 hpfc10ref_tab[256];
+ static crc_t hpfc10ref = { 8, 0x03, 0xff, false, false, 0xff,
+ 0, { .t8 = hpfc10ref_tab } };
+ static u32 crc32pat_tab[256];
+ static crc_t crc32pat = { 32, 0x04c11db7, 0x01234567, true, true, 0xabcdef01,
+ 0, { .t32 = crc32pat_tab } };
+ static u32 crc32patref_tab[256];
+ static crc_t crc32patref = { 32, 0x04c11db7, 0x01234567, false, false, 0xabcdef01,
+ 0, { .t32 = crc32patref_tab } };
+ static u32 crc32patbiref_tab[256];
+ static crc_t crc32patbiref = { 32, 0x04c11db7, 0x01234567, true, false, 0xabcdef01,
+ 0, { .t32 = crc32patbiref_tab } };
+ uint crc_i;
+ crc_t *crc;
+ static const struct
+ {
+ const char *name;
+ crc_t *crc;
+ } crcs[] =
+ {
+ { "crc32", &crc32 },
+ { "crc32ref", &crc32ref },
+ { "hpavfc", &hpavfc },
+ { "hpavfcref", &hpavfcref },
+ { "citt", &citt },
+ { "xmodem", &xmodem },
+ { "hpfc10", &hpfc10 },
+ { "hpfc10ref", &hpfc10ref },
+ { "crc32pat", &crc32pat },
+ { "crc32patref", &crc32patref },
+ { "crc32patbiref", &crc32patbiref },
+ };
+ lib_rnd_init (rnd, 1234);
+ test_case_begin (t, "rocksoft model");
+ for (crc_i = 0; crc_i < COUNT (crcs); crc_i++)
+ {
+ char name[32];
+ crc = crcs[crc_i].crc;
+ /* Build the corresponding Rocksoft^tm model. */
+ cm_t cm;
+ cm.cm_width = crc->width;
+ cm.cm_poly = crc->generator;
+ cm.cm_init = crc->init;
+ cm.cm_refin = crc->refin;
+ cm.cm_refot = crc->refout;
+ cm.cm_xorot = crc->xorout;
+ /* Init. */
+ snprintf (name, COUNT (name), "%s init", crcs[crc_i].name);
+ test_begin (t, name)
+ {
+ crc_init (crc);
+ } test_end;
+ /* Tables. */
+ snprintf (name, COUNT (name), "%s table", crcs[crc_i].name);
+ test_begin (t, name)
+ {
+ uint i;
+ /* Compare tables. */
+ switch (crc->width)
+ {
+ case 32:
+ case 24:
+ for (i = 0; i < 256; i++)
+ {
+ u32 ref = cm_tab (&cm, i);
+ test_fail_unless (crc->table.t32[i] == ref,
+ "table[%d] mismatch: 0x%08x != 0x%08x",
+ i, crc->table.t32[i], ref);
+ }
+ break;
+ case 16:
+ for (i = 0; i < 256; i++)
+ {
+ u16 ref = cm_tab (&cm, i);
+ test_fail_unless (crc->table.t16[i] == ref,
+ "table[%d] mismatch: 0x%04x != 0x%04x",
+ i, crc->table.t16[i], ref);
+ }
+ break;
+ case 8:
+ for (i = 0; i < 256; i++)
+ {
+ u8 ref = cm_tab (&cm, i);
+ test_fail_unless (crc->table.t8[i] == ref,
+ "table[%d] mismatch: 0x%02x != 0x%02x",
+ i, crc->table.t8[i], ref);
+ }
+ break;
+ }
+ } test_end;
+ /* Check string. */
+ snprintf (name, COUNT (name), "%s check string", crcs[crc_i].name);
+ const char *check_str = "123456789";
+ const uint check_str_len = 9;
+ test_begin (t, name)
+ {
+ u32 my1, my2, ref;
+ my1 = crc_compute_block (crc, (u8 *) check_str, check_str_len);
+ my2 = crc_compute_begin (crc);
+ my2 = crc_compute_continue_block (crc, my2, (u8 *) check_str,
+ check_str_len);
+ my2 = crc_compute_end (crc, my2);
+ test_fail_unless (my1 == my2);
+ cm_ini (&cm);
+ cm_blk (&cm, (u8 *) check_str, check_str_len);
+ ref = cm_crc (&cm);
+ test_fail_unless (my1 == ref);
+ test_verbose_print ("%s check: 0x%0*x", crcs[crc_i].name,
+ crc->width / 4, my1);
+ } test_end;
+ /* Check buffer. */
+ snprintf (name, COUNT (name), "%s check buffer", crcs[crc_i].name);
+ u8 check_buf[2048];
+ test_begin (t, name)
+ {
+ uint i;
+ for (i = 0; i < 256; i++)
+ check_buf[i] = i;
+ for (i = 256 / 4; i < COUNT (check_buf) / 4; i++)
+ *((u32 *) check_buf + i) = lib_rnd32 (rnd);
+ u32 my, ref;
+ my = crc_compute_begin (crc);
+ my = crc_compute_continue_block (crc, my, check_buf,
+ COUNT (check_buf) / 3);
+ my = crc_compute_continue_block (crc, my, check_buf
+ + COUNT (check_buf) / 3,
+ COUNT (check_buf)
+ - COUNT (check_buf) / 3);
+ my = crc_compute_end (crc, my);
+ cm_ini (&cm);
+ cm_blk (&cm, check_buf, COUNT (check_buf));
+ ref = cm_crc (&cm);
+ test_fail_unless (my == ref);
+ } test_end;
+ }
+}
+
+void
+crc_hpav_vectors_test_case (test_t t)
+{
+ test_case_begin (t, "hpav vectors");
+ /* HPAV FC */
+ static u32 hpavfc_tab[256];
+ static crc_t hpavfc = { 24, 0x800063, 0xffffff, true, true, 0xffffff,
+ 0, { .t32 = hpavfc_tab } };
+ static const u8 fcav_vector[16] =
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
+ 0x0c, 0x71, 0x74, 0x69 };
+ /* The CRC is computed considering that the LSB of the first byte is the
+ * highest order bit (x^127). CRC is stored with is highest order bit
+ * first which correspond to the LSB of the CRC register. This explain
+ * that: */
+ const u32 fcav_crc = 0x697471;
+ /* This constant is defined in the Homeplug specification: */
+ const u32 fcav_rx_good = 0x380ffe;
+ test_begin (t, "fcav begin")
+ {
+ crc_init (&hpavfc);
+ } test_end;
+ test_begin (t, "fcav tx")
+ {
+ u32 crc;
+ crc = crc_compute_begin (&hpavfc);
+ crc = crc_compute_continue_block (&hpavfc, crc, fcav_vector,
+ COUNT (fcav_vector) - 3);
+ crc = crc_compute_end (&hpavfc, crc);
+ test_fail_unless (crc == fcav_crc, "CRC mismatch 0x%06x != 0x%06x",
+ crc, fcav_crc);
+ } test_end;
+ test_begin (t, "fcav rx")
+ {
+ u32 crc;
+ crc = crc_compute_block (&hpavfc, fcav_vector, COUNT (fcav_vector));
+ test_fail_unless (crc == fcav_rx_good,
+ "received CRC not good: 0x%06x != 0x%06x", crc,
+ fcav_rx_good);
+ } test_end;
+ /* PB CRC. */
+ static u32 pbenc_tab[256];
+ static crc_t pbenc = { 32, 0x04c11db7, 0xffffffff, true, true, 0xffffffff,
+ 0, { .t32 = pbenc_tab } };
+ static const u8 pbenc_vector[136] =
+ {
+ 0x00, 0x00, 0x00, 0x1e, 0x21, 0x69, 0x71, 0x5a, 0xfc, 0x31, 0x20,
+ 0x13, 0xec, 0x61, 0xb6, 0x08, 0xcf, 0xcc, 0x6a, 0x65, 0xfa, 0x9d,
+ 0x0a, 0x04, 0x4e, 0xf7, 0x50, 0x78, 0x66, 0x8a, 0x65, 0x0e, 0x2b,
+ 0x7d, 0xa6, 0x8c, 0x27, 0x7c, 0x93, 0x92, 0x5a, 0x2f, 0x67, 0x40,
+ 0xd1, 0xb4, 0x10, 0xbf, 0xe3, 0x0a, 0x43, 0xf5, 0x43, 0x08, 0xc2,
+ 0x1f, 0x5c, 0xdc, 0xf7, 0x8c, 0xe8, 0xa4, 0x48, 0x65, 0xec, 0x00,
+ 0x57, 0x87, 0x88, 0x39, 0xda, 0x85, 0x2b, 0x93, 0xa6, 0x2b, 0xa6,
+ 0x40, 0x78, 0xe9, 0x44, 0x72, 0xb2, 0x11, 0xb8, 0x18, 0xe9, 0x01,
+ 0x2c, 0x36, 0x75, 0xcf, 0xe4, 0x4d, 0x60, 0x57, 0x89, 0xa2, 0x95,
+ 0x31, 0xff, 0x5d, 0x29, 0xa1, 0xff, 0xf2, 0x5b, 0xe7, 0x67, 0xad,
+ 0xc6, 0xff, 0x61, 0xc6, 0x52, 0x81, 0xdc, 0xf9, 0xe7, 0x19, 0x33,
+ 0x0f, 0x89, 0x46, 0x29, 0xa9, 0x04, 0xcd, 0x85, 0x96, 0xe5, 0xbf,
+ 0xdb, 0xe6, 0x90, 0x95
+ };
+ const u32 pbenc_crc = 0x9590e6db;
+ /* This constant is defined in the Homeplug specification: */
+ const u32 pbenc_rx_good = 0x2144df1c;
+ test_begin (t, "pbenc begin")
+ {
+ crc_init (&pbenc);
+ } test_end;
+ test_begin (t, "pbenc tx")
+ {
+ u32 crc;
+ crc = crc_compute_begin (&pbenc);
+ crc = crc_compute_continue_block (&pbenc, crc, pbenc_vector,
+ COUNT (pbenc_vector) - 4);
+ crc = crc_compute_end (&pbenc, crc);
+ test_fail_unless (crc == pbenc_crc, "CRC mismatch 0x%08x != 0x%08x",
+ crc, pbenc_crc);
+ } test_end;
+ test_begin (t, "pbenc rx")
+ {
+ u32 crc;
+ crc = crc_compute_block (&pbenc, pbenc_vector, COUNT (pbenc_vector));
+ test_fail_unless (crc == pbenc_rx_good,
+ "received CRC not good: 0x%08x != 0x%08x", crc,
+ pbenc_rx_good);
+ } test_end;
+}
+
+void
+crc_test_suite (test_t t)
+{
+ test_suite_begin (t, "crc");
+ crc_rocksoft_model_test_case (t);
+ crc_hpav_vectors_test_case (t);
+}
+
+int
+main (int argc, char **argv)
+{
+ test_t t;
+ test_init (t, argc, argv);
+ crc_test_suite (t);
+ test_result (t);
+ return test_nb_failed (t) == 0 ? 0 : 1;
+}
diff --git a/cesar/lib/test/heap/Makefile b/cesar/lib/test/heap/Makefile
new file mode 100644
index 0000000000..112cf7a42d
--- /dev/null
+++ b/cesar/lib/test/heap/Makefile
@@ -0,0 +1,7 @@
+BASE = ../../..
+
+HOST_PROGRAMS = test_heap
+test_heap_SOURCES = test_heap.c
+test_heap_MODULES = lib
+
+include $(BASE)/common/make/top.mk
diff --git a/cesar/lib/test/heap/src/test_heap.c b/cesar/lib/test/heap/src/test_heap.c
new file mode 100644
index 0000000000..20e0d9ac14
--- /dev/null
+++ b/cesar/lib/test/heap/src/test_heap.c
@@ -0,0 +1,272 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file test_heap.c
+ * \brief Test heap.
+ * \ingroup lib_test
+ */
+#include "common/std.h"
+#include "lib/rnd.h"
+#include "lib/heap.h"
+#include "lib/test.h"
+
+#if DEBUG
+# define NB_NODES 10000
+# define NB_ITER 10000
+#else
+# define NB_NODES 100000
+# define NB_ITER 100000000
+#endif
+
+/**
+ * Check heap structure.
+ * \param t test context
+ * \param heap the heap to check
+ * \return the number of elements
+ */
+static uint
+heap_check (test_t t, heap_t *heap)
+{
+ test_within (t);
+ uint n, depth, maxdepth;
+ heap_node_t *h;
+ h = heap_get_root (heap);
+ n = depth = maxdepth = 0;
+ while (h)
+ {
+ test_fail_unless (h != h->left && h != h->right);
+ test_fail_unless (!h->left || h->left->father == h);
+ test_fail_unless (!h->right || h->right->father == h);
+ if (h->left)
+ {
+ h = h->left;
+ depth++;
+ }
+ else if (h->right)
+ {
+ h = h->right;
+ depth++;
+ }
+ else
+ {
+ /* Go up... */
+ while (h)
+ {
+ test_fail_unless
+ (!h->father ||
+ !less_mod2p32 (PARENT_OF (heap_node_u32_t, node, h)->key,
+ PARENT_OF (heap_node_u32_t, node,
+ h->father)->key)
+ );
+ n++;
+ if (h->father && h->father->left == h && h->father->right)
+ {
+ /* ...and right if coming from left. */
+ h = h->father->right;
+ break;
+ }
+ else
+ {
+ h = h->father;
+ if (depth + 1 > maxdepth)
+ maxdepth = depth + 1;
+ depth--;
+ }
+ }
+ }
+ }
+ return n;
+}
+
+/**
+ * Maintain stats about right path length.
+ * \param heap the heap
+ * \param t test context
+ * \param min minimum path length
+ * \param max maximum path length
+ * \param sum sum of path length (to compute average)
+ */
+static void
+heap_stats (test_t t, heap_t *heap, uint *min, uint *max, unsigned long long *sum)
+{
+ test_within (t);
+ heap_node_t *n;
+ uint path_length;
+#if CONFIG_HEAP_LEFTIST
+ uint null_path_length = heap_get_root (heap)->null_path_length + 1;
+#endif
+ for (n = heap_get_root (heap), path_length = 0;
+ n;
+ n = n->right)
+ {
+#if CONFIG_HEAP_LEFTIST
+ test_fail_unless (null_path_length = n->null_path_length + 1);
+ null_path_length = n->null_path_length;
+#endif
+ path_length++;
+ }
+#if CONFIG_HEAP_LEFTIST
+ test_fail_unless (null_path_length == 1);
+#endif
+ *min = MIN (*min, path_length);
+ *max = MAX (*max, path_length);
+ *sum += path_length;
+}
+
+/**
+ * Return a limited random number.
+ * \param rnd rnd context.
+ * \return the random number.
+ *
+ * As we use a mod2p32 logic, all values should be distant no more than 2^31.
+ */
+static inline u32
+limited_rnd (lib_rnd_t *rnd)
+{
+ return 0xc0000000 + (lib_rnd32 (rnd) & 0x7fffffff);
+}
+
+void
+heap_basic_test_case (test_t t)
+{
+ uint i;
+ uint min = 0, max = 0;
+ unsigned long long sum = 0;
+ lib_rnd_t rnd;
+ heap_t heap, heap2;
+ heap_node_u32_t nodes[NB_NODES];
+ test_case_begin (t, "basic");
+ lib_rnd_init (&rnd, 1234);
+ /* Initialise heap & nodes. */
+ heap_init (&heap, &heap_node_u32_less_mod2p32);
+ heap_init (&heap2, &heap_node_u32_less_mod2p32);
+ for (i = 0; i < COUNT (nodes); i++)
+ heap_node_init (&nodes[i].node);
+ /* Insert them with random key. */
+ test_begin (t, "insert")
+ {
+ for (i = 0; i < COUNT (nodes) / 2; i++)
+ {
+ nodes[i].key = limited_rnd (&rnd);
+ heap_insert (&heap, &nodes[i].node);
+ test_fail_unless (DEBUG && i + 1 == heap_check (t, &heap));
+ }
+ for (i = 0; i < COUNT (nodes) / 2; i++)
+ {
+ uint j = i + COUNT (nodes) / 2;
+ nodes[j].key = limited_rnd (&rnd);
+ heap_insert (&heap2, &nodes[j].node);
+ test_fail_unless (DEBUG && i + 1 == heap_check (t, &heap2));
+ }
+ } test_end;
+ /* Merge. */
+ test_begin (t, "merge")
+ {
+ heap_merge (&heap, &heap2);
+ test_fail_unless (DEBUG && COUNT (nodes) == heap_check (t, &heap));
+ test_fail_unless (DEBUG && heap_empty (&heap2));
+ } test_end;
+ /* Remove a node and insert it back. */
+ test_begin (t, "remove and insert")
+ {
+ for (i = 0; i < NB_ITER; i++)
+ {
+ heap_node_u32_t *r;
+ if (lib_rnd_flip_coin (&rnd, LIB_RND_RATIO (0.8)))
+ {
+ if (lib_rnd_flip_coin (&rnd, LIB_RND_RATIO (0.5)))
+ {
+ r = PARENT_OF (heap_node_u32_t, node,
+ heap_get_root (&heap));
+ heap_remove_root (&heap);
+ }
+ else
+ {
+ r = &nodes[lib_rnd_uniform (&rnd, COUNT (nodes))];
+ heap_remove (&heap, &r->node);
+ }
+ test_fail_unless
+ (DEBUG && COUNT (nodes) - 1 == heap_check (t, &heap));
+ r->key = limited_rnd (&rnd);
+ heap_insert (&heap, &r->node);
+ }
+ else
+ {
+ if (lib_rnd_flip_coin (&rnd, LIB_RND_RATIO (0.5)))
+ {
+ r = PARENT_OF (heap_node_u32_t, node,
+ heap_get_root (&heap));
+ }
+ else
+ {
+ r = &nodes[lib_rnd_uniform (&rnd, COUNT (nodes))];
+ }
+ if (lib_rnd_flip_coin (&rnd, LIB_RND_RATIO (0.5)))
+ {
+ r->key = limited_rnd (&rnd);
+ }
+ else
+ {
+ r->key += (lib_rnd32 (&rnd) & 0xff) - 0x80;
+ if (r->key < 0xc0000000 && r->key >= 0x80000000)
+ r->key = 0xc0000000;
+ else if (r->key > 0x3fffffff && r->key < 0x80000000)
+ r->key = 0x3fffffff;
+ }
+ heap_adjust (&heap, &r->node);
+ }
+ test_fail_unless
+ (DEBUG && COUNT (nodes) == heap_check (t, &heap));
+ if (DEBUG)
+ heap_stats (t, &heap, &min, &max, &sum);
+ }
+ } test_end;
+ /* Remove all nodes and check order. */
+ test_begin (t, "check order")
+ {
+ i = COUNT (nodes);
+ u32 last = PARENT_OF (heap_node_u32_t, node,
+ heap_get_root (&heap))->key;
+ while (!heap_empty (&heap))
+ {
+ heap_node_u32_t *r = PARENT_OF (heap_node_u32_t, node,
+ heap_get_root (&heap));
+ test_fail_unless (!less_mod2p32 (r->key, last));
+ last = r->key;
+ heap_remove_root (&heap);
+ i--;
+ test_fail_unless (DEBUG && i == heap_check (t, &heap));
+ }
+ } test_end;
+ /* Print stats about right path length. */
+ if (DEBUG)
+ {
+ test_begin (t, "check depth")
+ {
+ test_verbose_print ("min=%d, max=%d, avg=%d", min, max,
+ (uint) (sum / NB_ITER));
+ } test_end;
+ }
+}
+
+void
+heap_test_suite (test_t t)
+{
+ test_suite_begin (t, "heap");
+ heap_basic_test_case (t);
+}
+
+int
+main (int argc, char **argv)
+{
+ test_t t;
+ test_init (t, argc, argv);
+ heap_test_suite (t);
+ test_result (t);
+ return test_nb_failed (t) == 0 ? 0 : 1;
+}
diff --git a/cesar/lib/test/list/Makefile b/cesar/lib/test/list/Makefile
new file mode 100644
index 0000000000..819511bbd7
--- /dev/null
+++ b/cesar/lib/test/list/Makefile
@@ -0,0 +1,7 @@
+BASE = ../../..
+
+HOST_PROGRAMS = test_list
+test_list_SOURCES = test_list.c
+test_list_MODULES = lib
+
+include $(BASE)/common/make/top.mk
diff --git a/cesar/lib/test/list/src/test_list.c b/cesar/lib/test/list/src/test_list.c
new file mode 100644
index 0000000000..af02728069
--- /dev/null
+++ b/cesar/lib/test/list/src/test_list.c
@@ -0,0 +1,267 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/test_list.c
+ * \brief Test lists.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "lib/rnd.h"
+#include "lib/list.h"
+#include "lib/test.h"
+
+#define NB_ITEMS 1000
+#define NB_ITER 100000
+#define NB_LISTS 5
+
+struct test_list_t
+{
+ list_node_t node;
+ int list;
+ int pos;
+};
+typedef struct test_list_t test_list_t;
+
+void
+list_basic_test_case (test_t t)
+{
+ uint i, j;
+ list_t lists[NB_LISTS];
+ uint lists_item_nb[NB_LISTS];
+ lib_rnd_t rnd[1];
+ test_list_t items[NB_ITEMS];
+ test_case_begin (t, "basic");
+ /* Init. */
+ lib_rnd_init (rnd, 1234);
+ for (i = 0; i < COUNT (lists); i++)
+ {
+ list_init (&lists[i]);
+ lists_item_nb[i] = 0;
+ }
+ for (i = 0; i < COUNT (items); i++)
+ {
+ list_init_node (&items[i].node);
+ j = lib_rnd_uniform (rnd, NB_LISTS);
+ items[i].list = j;
+ items[i].pos = lists_item_nb[j]++;
+ list_push (&lists[j], &items[i].node);
+ }
+ /* Test loop. */
+ test_begin (t, "remove and insert")
+ {
+ for (i = 0; i < NB_ITER; i++)
+ {
+ int pos, nb;
+ list_node_t *first, *last, *n;
+ int src_list_i, src_pos;
+ int dst_list_i, dst_pos;
+ list_t *src_list, *dst_list;
+ list_node_t *src_after, *dst_after;
+ bool src_center, src_begin, range;
+ bool dst_center, dst_begin;
+ /* Choose source. */
+ src_center = lib_rnd_flip_coin (rnd, LIB_RND_RATIO (0.3));
+ range = lib_rnd_flip_coin (rnd, LIB_RND_RATIO (0.3));
+ if (src_center)
+ {
+ /* Arbitrary node. */
+ first = &items[lib_rnd_uniform (rnd, NB_ITEMS)].node;
+ test_list_t *tn = PARENT_OF (test_list_t, node, first);
+ src_list_i = tn->list;
+ nb = range ? lib_rnd_uniform (rnd, lists_item_nb[src_list_i] -
+ tn->pos) + 1 : 1;
+ last = first;
+ for (j = 0; j < (uint) nb - 1; j++)
+ last = list_next (last);
+ src_after = list_next (last);
+ src_pos = tn->pos + nb;
+ }
+ else
+ {
+ /* Node at one end. */
+ src_begin = lib_rnd_flip_coin (rnd, LIB_RND_RATIO (0.5));
+ do {
+ src_list_i = lib_rnd_uniform (rnd, NB_LISTS);
+ } while (lists_item_nb[src_list_i] == 0);
+ nb = range ? lib_rnd_uniform (rnd, lists_item_nb[src_list_i]) + 1
+ : 1;
+ if (src_begin)
+ {
+ first = list_begin (&lists[src_list_i]);
+ last = first;
+ for (j = 0; j < (uint) nb - 1; j++)
+ last = list_next (last);
+ src_after = list_next (last);
+ src_pos = nb;
+ }
+ else
+ {
+ last = list_rbegin (&lists[src_list_i]);
+ first = last;
+ for (j = 0; j < (uint) nb - 1; j++)
+ first = list_prev (first);
+ src_after = list_next (last);
+ src_pos = -1;
+ }
+ }
+ /* Choose destination. */
+ dst_center = lib_rnd_flip_coin (rnd, LIB_RND_RATIO (0.3));
+ if (dst_center)
+ {
+ /* Arbitrary node. */
+ test_list_t *tn;
+ do {
+ tn = &items[lib_rnd_uniform (rnd, NB_ITEMS)];
+ } while (tn->list == src_list_i);
+ dst_list_i = tn->list;
+ dst_after = &tn->node;
+ dst_pos = tn->pos;
+ }
+ else
+ {
+ /* Node at one end. */
+ dst_begin = lib_rnd_flip_coin (rnd, LIB_RND_RATIO (0.5));
+ do {
+ dst_list_i = lib_rnd_uniform (rnd, NB_LISTS);
+ } while (src_list_i == dst_list_i);
+ if (dst_begin)
+ {
+ dst_after = list_begin (&lists[dst_list_i]);
+ dst_pos = 0;
+ }
+ else
+ {
+ dst_after = list_end (&lists[dst_list_i]);
+ dst_pos = lists_item_nb[dst_list_i];
+ }
+ }
+ /* Apply the operation. */
+ src_list = &lists[src_list_i];
+ dst_list = &lists[dst_list_i];
+ if (range)
+ {
+ /* Range operations. */
+ if (dst_center)
+ list_insert_range (dst_list, src_list, dst_after, first,
+ list_next (last));
+ else if (dst_begin)
+ list_unshift_range (dst_list, src_list, first, list_next
+ (last));
+ else
+ list_push_range (dst_list, src_list, first, list_next (last));
+ }
+ else
+ {
+ /* Single operations, remove... */
+ if (src_center)
+ list_remove (src_list, first);
+ else
+ {
+ if (src_begin)
+ n = list_shift (src_list);
+ else
+ n = list_pop (src_list);
+ dbg_assert (n == first);
+ }
+ /* ...and insert. */
+ if (dst_center)
+ list_insert (dst_list, dst_after, first);
+ else if (dst_begin)
+ list_unshift (dst_list, first);
+ else
+ list_push (dst_list, first);
+ }
+ /* Update pos fields of moved nodes. */
+ for (n = first, pos = dst_pos; n != list_next (last);
+ n = list_next (n), pos++)
+ {
+ test_list_t *tn = PARENT_OF (test_list_t, node, n);
+ test_fail_unless (tn->list == src_list_i);
+ tn->list = dst_list_i;
+ tn->pos = pos;
+ }
+ /* Update pos fields in source list. */
+ for (n = src_after, pos = src_pos;
+ n != list_end (src_list);
+ n = list_next (n), pos++)
+ {
+ test_list_t *tn = PARENT_OF (test_list_t, node, n);
+ test_fail_unless (tn->list == src_list_i);
+ test_fail_unless (tn->pos == pos);
+ tn->pos = pos - nb;
+ }
+ lists_item_nb[src_list_i] -= nb;
+ /* Update pos fields in destination list. */
+ for (n = dst_after, pos = dst_pos;
+ n != list_end (dst_list);
+ n = list_next (n), pos++)
+ {
+ test_list_t *tn = PARENT_OF (test_list_t, node, n);
+ test_fail_unless (tn->list == dst_list_i);
+ test_fail_unless (tn->pos == pos);
+ tn->pos = pos + nb;
+ }
+ lists_item_nb[dst_list_i] += nb;
+ /* Check lists. */
+ uint check_items = 0;
+ for (j = 0; j < COUNT (lists); j++)
+ {
+ test_fail_unless
+ ((lists_item_nb[j] == 0 && list_empty (&lists[j])) ||
+ (lists_item_nb[j] != 0 && !list_empty (&lists[j])));
+ if (lib_rnd_flip_coin (rnd, LIB_RND_RATIO (0.5)))
+ {
+ /* Check forward. */
+ pos = 0;
+ for (n = list_begin (&lists[j]); n != list_end (&lists[j]);
+ n = list_next (n), pos++)
+ {
+ test_list_t *tn = PARENT_OF (test_list_t, node, n);
+ test_fail_unless (tn->list == (int) j);
+ test_fail_unless (tn->pos == pos);
+ check_items++;
+ }
+ test_fail_unless (pos == (int) lists_item_nb[j]);
+ }
+ else
+ {
+ /* Check backward. */
+ pos = lists_item_nb[j] - 1;
+ for (n = list_rbegin (&lists[j]); n != list_rend (&lists[j]);
+ n = list_prev (n), pos--)
+ {
+ test_list_t *tn = PARENT_OF (test_list_t, node, n);
+ test_fail_unless (tn->list == (int) j);
+ test_fail_unless (tn->pos == pos);
+ check_items++;
+ }
+ test_fail_unless (pos == -1);
+ }
+ }
+ test_fail_unless (check_items == NB_ITEMS);
+ }
+ } test_end;
+}
+
+void
+list_test_suite (test_t t)
+{
+ test_suite_begin (t, "list");
+ list_basic_test_case (t);
+}
+
+int
+main (int argc, char **argv)
+{
+ test_t t;
+ test_init (t, argc, argv);
+ list_test_suite (t);
+ test_result (t);
+ return test_nb_failed (t) == 0 ? 0 : 1;
+}
diff --git a/cesar/lib/test/read_word/Makefile b/cesar/lib/test/read_word/Makefile
new file mode 100644
index 0000000000..0cf7c380b6
--- /dev/null
+++ b/cesar/lib/test/read_word/Makefile
@@ -0,0 +1,7 @@
+BASE = ../../..
+
+HOST_PROGRAMS = test_read_word
+test_read_word_SOURCES = read_word.c
+test_read_word_MODULES = lib
+
+include $(BASE)/common/make/top.mk \ No newline at end of file
diff --git a/cesar/lib/test/read_word/src/read_word.c b/cesar/lib/test/read_word/src/read_word.c
new file mode 100644
index 0000000000..9d4b55254c
--- /dev/null
+++ b/cesar/lib/test/read_word/src/read_word.c
@@ -0,0 +1,151 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file test_sparc_inte.c
+ * \brief test the whole sar_mf.c source
+ * \ingroup mac/sar/test/unit_test/lib_sar_test
+ *
+ */
+
+#include "common/std.h"
+#include "lib/test.h"
+#include "lib/read_word.h"
+#include <stdio.h>
+#include <string.h>
+
+int main (void)
+{
+ test_t test;
+ u8 buffer[1000];
+ uint length;
+ mac_t mac;
+
+ test_init (test, 0, NULL);
+
+ *(uint *) (buffer + 504) = 0x567801BA;
+ *(uint *) (buffer + 508) = 0x1234;
+
+ length = read_bytes_from_word (buffer + 504, 2) >> 2;
+
+ length = length & 0xFFFF;
+ test_begin(test, "test1")
+ {
+ test_fail_if (length != 110, "function does not work");
+ }
+ test_end;
+
+ *(uint *) (buffer + 504) = 0x01BAFFFF;
+ *(uint *) (buffer + 508) = 0x12345678;
+
+ length = read_bytes_from_word (buffer + 506, 2) >> 2;
+
+ length = length & 0xFFFF;
+ test_begin(test, "test2")
+ {
+ test_fail_if (length != 110, "function does not work");
+ }
+ test_end;
+
+ *(uint *) (buffer + 504) = 0x01BAFFFF;
+ *(uint *) (buffer + 508) = 0x12345678;
+
+ length = read_u24_from_word (buffer + 507);
+
+ test_begin(test, "test3")
+ {
+ test_fail_if (length != 0x567801, "function does not work");
+ }
+ test_end;
+
+ length = read_u24_from_word (buffer + 504);
+
+ test_begin(test, "test4")
+ {
+ test_fail_if (length != 0xBAFFFF, "function does not work");
+ }
+ test_end;
+
+ length = read_u16_from_word (buffer + 507);
+
+ test_begin(test, "test5")
+ {
+ test_fail_if (length != 0x7801, "function does not work");
+ }
+ test_end;
+
+ length = read_u16_from_word (buffer + 504);
+
+ test_begin(test, "test6")
+ {
+ test_fail_if (length != 0xFFFF, "function does not work");
+ }
+ test_end;
+
+ length = read_u8_from_word (buffer + 507);
+
+ test_begin(test, "test7")
+ {
+ test_fail_if (length != 0x01, "function does not work");
+ }
+ test_end;
+
+ length = read_u8_from_word (buffer + 504);
+
+ test_begin(test, "test8")
+ {
+ test_fail_if (length != 0xFF, "function does not work");
+ }
+ test_end;
+
+ *(uint *) (buffer + 508) = 0x12345678;
+ length = read_u32_from_word (buffer + 508);
+ test_begin(test, "test9")
+ {
+ test_fail_if (length != 0x12345678, "function does not work");
+ }
+ test_end;
+
+ *(uint *) (buffer + 508) = 0x56780000;
+ *(uint *) (buffer + 512) = 0x00001234;
+ length = read_u32_from_word (buffer + 510);
+ test_begin(test, "test10")
+ {
+ test_fail_if (length != 0x12345678, "function does not work");
+ }
+ test_end;
+
+ *(uint *) buffer = 0xDB1F0F00;
+ *(uint *) (buffer + 4)= 0x12347F6A;
+
+ mac = read_u48_from_word (buffer);
+
+ test_begin(test, "read_mac_address")
+ {
+ test_fail_if (mac != 0x7F6ADB1F0F00ull, "Wrong mac address");
+ }
+ test_end;
+
+ mac = read_u56_from_word (buffer);
+
+ test_begin(test, "read_mac_address with one more byte.")
+ {
+ test_fail_if (mac != 0x347F6ADB1F0F00ull, "Wrong mac address");
+ }
+ test_end;
+
+ mac = read_u64_from_word (buffer);
+
+ test_begin(test, "read_mac_address with two more byte.")
+ {
+ test_fail_if (mac != 0x12347F6ADB1F0F00ull, "Wrong mac address");
+ }
+ test_end;
+
+ test_result (test);
+ return test_nb_failed (test) == 0 ? 0 : 1;
+}
diff --git a/cesar/lib/test/restrack/Config b/cesar/lib/test/restrack/Config
new file mode 100644
index 0000000000..e2899974cd
--- /dev/null
+++ b/cesar/lib/test/restrack/Config
@@ -0,0 +1,2 @@
+CONFIG_RESTRACK=y
+CONFIG_RESTRACK_KEEP=y
diff --git a/cesar/lib/test/restrack/Makefile b/cesar/lib/test/restrack/Makefile
new file mode 100644
index 0000000000..29a0d9c417
--- /dev/null
+++ b/cesar/lib/test/restrack/Makefile
@@ -0,0 +1,7 @@
+BASE = ../../..
+
+HOST_PROGRAMS = test_restrack
+test_restrack_SOURCES = test_restrack.c
+test_restrack_MODULES = lib
+
+include $(BASE)/common/make/top.mk
diff --git a/cesar/lib/test/restrack/src/test_restrack.c b/cesar/lib/test/restrack/src/test_restrack.c
new file mode 100644
index 0000000000..e2ce11bb4d
--- /dev/null
+++ b/cesar/lib/test/restrack/src/test_restrack.c
@@ -0,0 +1,104 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/test_restrack.c
+ * \brief Test resources tracker.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "lib/restrack.h"
+#include "lib/blk.h"
+#include "lib/test.h"
+
+void
+restrack_alone_test_case (test_t t)
+{
+ test_case_begin (t, "alone");
+ test_begin (t, "basic")
+ {
+ int a, b, c, i;
+ restrack_create (NULL, &a, __func__, __LINE__, 1);
+ restrack_create (NULL, &b, __func__, __LINE__, 1);
+ restrack_create (NULL, &c, __func__, __LINE__, 1);
+ for (i = 0; i < 5; i++)
+ {
+ restrack_update (NULL, &a, __func__, __LINE__, 1);
+ restrack_update (NULL, &b, __func__, __LINE__, 1);
+ restrack_update (NULL, &b, __func__, __LINE__, 2);
+ restrack_update (NULL, &b, __func__, __LINE__, -1);
+ }
+ test_fail_unless (!restrack_check ());
+ for (i = 0; i < 5; i++)
+ {
+ restrack_update (NULL, &a, __func__, __LINE__, -1);
+ restrack_update (NULL, &b, __func__, __LINE__, -2);
+ }
+ restrack_destroy (NULL, &a, __func__, __LINE__, -1);
+ restrack_destroy (NULL, &b, __func__, __LINE__, -1);
+ restrack_destroy (NULL, &c, __func__, __LINE__, -1);
+ test_fail_unless (restrack_check ());
+ } test_end;
+}
+
+void
+restrack_blk_test_case (test_t t)
+{
+ test_case_begin (t, "blk");
+ test_begin (t, "basic")
+ {
+ void *a, *b;
+ blk_t *f, *l;
+ int i;
+ a = blk_alloc ();
+ b = blk_alloc ();
+ f = blk_alloc_desc_range (5, &l);
+ for (i = 0; i < 5; i++)
+ {
+ blk_addref (a);
+ blk_addref (b);
+ blk_addref (b);
+ blk_release (b);
+ blk_addref_desc_range (f, l);
+ blk_addref_desc (f);
+ blk_addref_desc (l);
+ blk_release_desc_range (f, l);
+ }
+ test_fail_unless (!restrack_check ());
+ blk_release_desc_range (f, l);
+ test_fail_unless (!restrack_check ());
+ for (i = 0; i < 5; i++)
+ {
+ blk_release (b);
+ blk_release (a);
+ blk_release_desc (f);
+ blk_release_desc (l);
+ }
+ blk_release (b);
+ blk_release (a);
+ test_fail_unless (restrack_check ());
+ } test_end;
+}
+
+void
+restrack_test_suite (test_t t)
+{
+ test_suite_begin (t, "restrack");
+ restrack_alone_test_case (t);
+ restrack_blk_test_case (t);
+}
+
+int
+main (int argc, char **argv)
+{
+ test_t t;
+ test_init (t, argc, argv);
+ restrack_test_suite (t);
+ test_result (t);
+ return test_nb_failed (t) == 0 ? 0 : 1;
+}
diff --git a/cesar/lib/test/rnd/Makefile b/cesar/lib/test/rnd/Makefile
new file mode 100644
index 0000000000..988cae2faa
--- /dev/null
+++ b/cesar/lib/test/rnd/Makefile
@@ -0,0 +1,19 @@
+BASE = ../../..
+
+# TODO, only host for the moment.
+ECOS = y
+TARGET = sparc
+
+HOST_PROGRAMS = test_rnd
+test_rnd_SOURCES = test_rnd.c
+test_rnd_MODULES = lib
+
+test_data_header = obj/inc/mt19937ar.out.h
+CLEAN_FILES = $(test_data_header)
+
+include $(BASE)/common/make/top.mk
+
+$(call src2obj,src/test_rnd.c,host): $(test_data_header)
+$(call src2obj,src/test_rnd.c,target): $(test_data_header)
+$(test_data_header): mt19937ar.out
+ perl $< > $@
diff --git a/cesar/lib/test/rnd/mt19937ar.out b/cesar/lib/test/rnd/mt19937ar.out
new file mode 100644
index 0000000000..c29480ed32
--- /dev/null
+++ b/cesar/lib/test/rnd/mt19937ar.out
@@ -0,0 +1,213 @@
+#!/usr/bin/perl
+print <<EOF;
+/* Autogenerated file, do not edit. */
+static const u32 data[] = {
+EOF
+while (<DATA>)
+{
+ die unless /^(\s*\d+)(\s*\d+)(\s*\d+)(\s*\d+)(\s*\d+)\s$/;
+ print " $1u,$2u,$3u,$4u,$5u,\n";
+ die unless $1 && $2 && $3 && $4 && $5;
+}
+print "};\n";
+__DATA__
+1067595299 955945823 477289528 4107218783 4228976476
+3344332714 3355579695 227628506 810200273 2591290167
+2560260675 3242736208 646746669 1479517882 4245472273
+1143372638 3863670494 3221021970 1773610557 1138697238
+1421897700 1269916527 2859934041 1764463362 3874892047
+3965319921 72549643 2383988930 2600218693 3237492380
+2792901476 725331109 605841842 271258942 715137098
+3297999536 1322965544 4229579109 1395091102 3735697720
+2101727825 3730287744 2950434330 1661921839 2895579582
+2370511479 1004092106 2247096681 2111242379 3237345263
+4082424759 219785033 2454039889 3709582971 835606218
+2411949883 2735205030 756421180 2175209704 1873865952
+2762534237 4161807854 3351099340 181129879 3269891896
+ 776029799 2218161979 3001745796 1866825872 2133627728
+ 34862734 1191934573 3102311354 2916517763 1012402762
+2184831317 4257399449 2899497138 3818095062 3030756734
+1282161629 420003642 2326421477 2741455717 1278020671
+3744179621 271777016 2626330018 2560563991 3055977700
+4233527566 1228397661 3595579322 1077915006 2395931898
+1851927286 3013683506 1999971931 3006888962 1049781534
+1488758959 3491776230 104418065 2448267297 3075614115
+3872332600 891912190 3936547759 2269180963 2633455084
+1047636807 2604612377 2709305729 1952216715 207593580
+2849898034 670771757 2210471108 467711165 263046873
+3569667915 1042291111 3863517079 1464270005 2758321352
+3790799816 2301278724 3106281430 7974801 2792461636
+ 555991332 621766759 1322453093 853629228 686962251
+1455120532 957753161 1802033300 1021534190 3486047311
+1902128914 3701138056 4176424663 1795608698 560858864
+3737752754 3141170998 1553553385 3367807274 711546358
+2475125503 262969859 251416325 2980076994 1806565895
+ 969527843 3529327173 2736343040 2987196734 1649016367
+2206175811 3048174801 3662503553 3138851612 2660143804
+1663017612 1816683231 411916003 3887461314 2347044079
+1015311755 1203592432 2170947766 2569420716 813872093
+1105387678 1431142475 220570551 4243632715 4179591855
+2607469131 3090613241 282341803 1734241730 1391822177
+1001254810 827927915 1886687171 3935097347 2631788714
+3905163266 110554195 2447955646 3717202975 3304793075
+3739614479 3059127468 953919171 2590123714 1132511021
+3795593679 2788030429 982155079 3472349556 859942552
+2681007391 2299624053 647443547 233600422 608168955
+3689327453 1849778220 1608438222 3968158357 2692977776
+2851872572 246750393 3582818628 3329652309 4036366910
+1012970930 950780808 3959768744 2538550045 191422718
+2658142375 3276369011 2927737484 1234200027 1920815603
+3536074689 1535612501 2184142071 3276955054 428488088
+2378411984 4059769550 3913744741 2732139246 64369859
+3755670074 842839565 2819894466 2414718973 1010060670
+1839715346 2410311136 152774329 3485009480 4102101512
+2852724304 879944024 1785007662 2748284463 1354768064
+3267784736 2269127717 3001240761 3179796763 895723219
+ 865924942 4291570937 89355264 1471026971 4114180745
+3201939751 2867476999 2460866060 3603874571 2238880432
+3308416168 2072246611 2755653839 3773737248 1709066580
+4282731467 2746170170 2832568330 433439009 3175778732
+ 26248366 2551382801 183214346 3893339516 1928168445
+1337157619 3429096554 3275170900 1782047316 4264403756
+1876594403 4289659572 3223834894 1728705513 4068244734
+2867840287 1147798696 302879820 1730407747 1923824407
+1180597908 1569786639 198796327 560793173 2107345620
+2705990316 3448772106 3678374155 758635715 884524671
+ 486356516 1774865603 3881226226 2635213607 1181121587
+1508809820 3178988241 1594193633 1235154121 326117244
+2304031425 937054774 2687415945 3192389340 2003740439
+1823766188 2759543402 10067710 1533252662 4132494984
+ 82378136 420615890 3467563163 541562091 3535949864
+2277319197 3330822853 3215654174 4113831979 4204996991
+2162248333 3255093522 2219088909 2978279037 255818579
+2859348628 3097280311 2569721123 1861951120 2907080079
+2719467166 998319094 2521935127 2404125338 259456032
+2086860995 1839848496 1893547357 2527997525 1489393124
+2860855349 76448234 2264934035 744914583 2586791259
+1385380501 66529922 1819103258 1899300332 2098173828
+1793831094 276463159 360132945 4178212058 595015228
+ 177071838 2800080290 1573557746 1548998935 378454223
+1460534296 1116274283 3112385063 3709761796 827999348
+3580042847 1913901014 614021289 4278528023 1905177404
+ 45407939 3298183234 1184848810 3644926330 3923635459
+1627046213 3677876759 969772772 1160524753 1522441192
+ 452369933 1527502551 832490847 1003299676 1071381111
+2891255476 973747308 4086897108 1847554542 3895651598
+2227820339 1621250941 2881344691 3583565821 3510404498
+ 849362119 862871471 797858058 2867774932 2821282612
+3272403146 3997979905 209178708 1805135652 6783381
+2823361423 792580494 4263749770 776439581 3798193823
+2853444094 2729507474 1071873341 1329010206 1289336450
+3327680758 2011491779 80157208 922428856 1158943220
+1667230961 2461022820 2608845159 387516115 3345351910
+1495629111 4098154157 3156649613 3525698599 4134908037
+ 446713264 2137537399 3617403512 813966752 1157943946
+3734692965 1680301658 3180398473 3509854711 2228114612
+1008102291 486805123 863791847 3189125290 1050308116
+3777341526 4291726501 844061465 1347461791 2826481581
+ 745465012 2055805750 4260209475 2386693097 2980646741
+ 447229436 2077782664 1232942813 4023002732 1399011509
+3140569849 2579909222 3794857471 900758066 2887199683
+1720257997 3367494931 2668921229 955539029 3818726432
+1105704962 3889207255 2277369307 2746484505 1761846513
+2413916784 2685127085 4240257943 1166726899 4215215715
+3082092067 3960461946 1663304043 2087473241 4162589986
+2507310778 1579665506 767234210 970676017 492207530
+1441679602 1314785090 3262202570 3417091742 1561989210
+3011406780 1146609202 3262321040 1374872171 1634688712
+1280458888 2230023982 419323804 3262899800 39783310
+1641619040 1700368658 2207946628 2571300939 2424079766
+ 780290914 2715195096 3390957695 163151474 2309534542
+1860018424 555755123 280320104 1604831083 2713022383
+1728987441 3639955502 623065489 3828630947 4275479050
+3516347383 2343951195 2430677756 635534992 3868699749
+ 808442435 3070644069 4282166003 2093181383 2023555632
+1568662086 3422372620 4134522350 3016979543 3259320234
+2888030729 3185253876 4258779643 1267304371 1022517473
+ 815943045 929020012 2995251018 3371283296 3608029049
+2018485115 122123397 2810669150 1411365618 1238391329
+1186786476 3155969091 2242941310 1765554882 279121160
+4279838515 1641578514 3796324015 13351065 103516986
+1609694427 551411743 2493771609 1316337047 3932650856
+4189700203 463397996 2937735066 1855616529 2626847990
+ 55091862 3823351211 753448970 4045045500 1274127772
+1124182256 92039808 2126345552 425973257 386287896
+2589870191 1987762798 4084826973 2172456685 3366583455
+3602966653 2378803535 2901764433 3716929006 3710159000
+2653449155 3469742630 3096444476 3932564653 2595257433
+ 318974657 3146202484 853571438 144400272 3768408841
+ 782634401 2161109003 570039522 1886241521 14249488
+2230804228 1604941699 3928713335 3921942509 2155806892
+ 134366254 430507376 1924011722 276713377 196481886
+3614810992 1610021185 1785757066 851346168 3761148643
+2918835642 3364422385 3012284466 3735958851 2643153892
+3778608231 1164289832 205853021 2876112231 3503398282
+3078397001 3472037921 1748894853 2740861475 316056182
+1660426908 168885906 956005527 3984354789 566521563
+1001109523 1216710575 2952284757 3834433081 3842608301
+2467352408 3974441264 3256601745 1409353924 1329904859
+2307560293 3125217879 3622920184 3832785684 3882365951
+2308537115 2659155028 1450441945 3532257603 3186324194
+1225603425 1124246549 175808705 3009142319 2796710159
+3651990107 160762750 1902254979 1698648476 1134980669
+ 497144426 3302689335 4057485630 3603530763 4087252587
+ 427812652 286876201 823134128 1627554964 3745564327
+2589226092 4202024494 62878473 3275585894 3987124064
+2791777159 1916869511 2585861905 1375038919 1403421920
+ 60249114 3811870450 3021498009 2612993202 528933105
+2757361321 3341402964 2621861700 273128190 4015252178
+3094781002 1621621288 2337611177 1796718448 1258965619
+4241913140 2138560392 3022190223 4174180924 450094611
+3274724580 617150026 2704660665 1469700689 1341616587
+ 356715071 1188789960 2278869135 1766569160 2795896635
+ 57824704 2893496380 1235723989 1630694347 3927960522
+ 428891364 1814070806 2287999787 4125941184 3968103889
+3548724050 1025597707 1404281500 2002212197 92429143
+2313943944 2403086080 3006180634 3561981764 1671860914
+1768520622 1803542985 844848113 3006139921 1410888995
+1157749833 2125704913 1789979528 1799263423 741157179
+2405862309 767040434 2655241390 3663420179 2172009096
+2511931187 1680542666 231857466 1154981000 157168255
+1454112128 3505872099 1929775046 2309422350 2143329496
+2960716902 407610648 2938108129 2581749599 538837155
+2342628867 430543915 740188568 1937713272 3315215132
+2085587024 4030765687 766054429 3517641839 689721775
+1294158986 1753287754 4202601348 1974852792 33459103
+3568087535 3144677435 1686130825 4134943013 3005738435
+3599293386 426570142 754104406 3660892564 1964545167
+ 829466833 821587464 1746693036 1006492428 1595312919
+1256599985 1024482560 1897312280 2902903201 691790057
+1037515867 3176831208 1968401055 2173506824 1089055278
+1748401123 2941380082 968412354 1818753861 2973200866
+3875951774 1119354008 3988604139 1647155589 2232450826
+3486058011 3655784043 3759258462 847163678 1082052057
+ 989516446 2871541755 3196311070 3929963078 658187585
+3664944641 2175149170 2203709147 2756014689 2456473919
+3890267390 1293787864 2830347984 3059280931 4158802520
+1561677400 2586570938 783570352 1355506163 31495586
+3789437343 3340549429 2092501630 896419368 671715824
+3530450081 3603554138 1055991716 3442308219 1499434728
+3130288473 3639507000 17769680 2259741420 487032199
+4227143402 3693771256 1880482820 3924810796 381462353
+4017855991 2452034943 2736680833 2209866385 2128986379
+ 437874044 595759426 641721026 1636065708 3899136933
+ 629879088 3591174506 351984326 2638783544 2348444281
+2341604660 2123933692 143443325 1525942256 364660499
+ 599149312 939093251 1523003209 106601097 376589484
+1346282236 1297387043 764598052 3741218111 933457002
+1886424424 3219631016 525405256 3014235619 323149677
+2038881721 4100129043 2851715101 2984028078 1888574695
+2014194741 3515193880 4180573530 3461824363 2641995497
+3179230245 2902294983 2217320456 4040852155 1784656905
+3311906931 87498458 2752971818 2635474297 2831215366
+3682231106 2920043893 3772929704 2816374944 309949752
+2383758854 154870719 385111597 1191604312 1840700563
+ 872191186 2925548701 1310412747 2102066999 1504727249
+3574298750 1191230036 3330575266 3180292097 3539347721
+ 681369118 3305125752 3648233597 950049240 4173257693
+1760124957 512151405 681175196 580563018 1169662867
+4015033554 2687781101 699691603 2673494188 1137221356
+ 123599888 472658308 1053598179 1012713758 3481064843
+3759461013 3981457956 3830587662 1877191791 3650996736
+ 988064871 3515461600 4089077232 2225147448 1249609188
+2643151863 3896204135 2416995901 1397735321 3460025646
diff --git a/cesar/lib/test/rnd/src/test_rnd.c b/cesar/lib/test/rnd/src/test_rnd.c
new file mode 100644
index 0000000000..ae460d5d97
--- /dev/null
+++ b/cesar/lib/test/rnd/src/test_rnd.c
@@ -0,0 +1,164 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file test_rnd.c
+ * \brief Test the random number generator.
+ * \ingroup lib_test
+ *
+ * \todo Replace all the stdio calls to the future test library calls.
+ */
+#include "common/std.h"
+#include "lib/rnd.h"
+#include "lib/test.h"
+
+#include "mt19937ar.out.h"
+
+#include <string.h>
+
+void
+rnd_basic_test_case (test_t t)
+{
+ uint i;
+ u32 r;
+ lib_rnd_t ctx;
+ static const u32 init[4] = { 0x123, 0x234, 0x345, 0x456 };
+ test_case_begin (t, "basic");
+ /* Initialise. */
+ lib_rnd_init_by_array (&ctx, init, COUNT (init));
+ test_begin (t, "compare")
+ {
+ /* Compare with original Mersenne Twister code. */
+ for (i = 0; i < COUNT (data); i++)
+ {
+ r = lib_rnd32 (&ctx);
+ test_fail_unless (r == data[i], "i=%u, r=%u", i, r);
+ }
+ } test_end;
+ /* Check lib_rnd_uniform bound. */
+ test_begin (t, "bound")
+ {
+ bool ub, ut;
+ ub = ut = false;
+ for (i = 0; i < 100000; i++)
+ {
+ r = lib_rnd_uniform (&ctx, 1000);
+ test_fail_if (r >= 1000, "bound overflow i=%u", i);
+ if (r == 0) ub = true;
+ if (r == 999) ut = true;
+ }
+ test_fail_if (!ub || !ut, "bound not hit");
+ } test_end;
+ /* Check lib_rnd_uniform uniformity. */
+ test_begin (t, "uniformity")
+ {
+ int less, more;
+ less = more = 0;
+ for (i = 0; i < 100000; i++)
+ {
+ r = lib_rnd_uniform (&ctx, 0xc0000000);
+ if (r > 0xc0000000 / 2)
+ more++;
+ else
+ less++;
+ }
+ test_fail_if (ABS (more - less) > 1000,
+ "not uniform more=%d, less=%d", more, less);
+ } test_end;
+}
+
+void
+rnd_buf_run (test_t t, lib_rnd_t *rnd, u8 *buf1, u8 *buf2, uint pos,
+ uint size)
+{
+ test_within (t);
+ uint i;
+ dbg_assert_ptr (buf1);
+ dbg_assert_ptr (buf2);
+ /* Generate two buffers. */
+ lib_rnd_buffer (rnd, buf1 + pos, size);
+ lib_rnd_buffer (rnd, buf2 + pos, size);
+ /* Consider that the two buffers should have different content (or tweak
+ * lib_rnd_init until this is true!). */
+ for (i = pos; i < pos + size; i++)
+ test_fail_if (buf1[i] == buf2[i], "improbable match at %d", i);
+}
+
+void
+rnd_buf_test_case (test_t t)
+{
+ u8 buf[2][256];
+ uint pos, size;
+ lib_rnd_t rnd[1];
+ test_case_begin (t, "buf");
+ /* Initialise. */
+ lib_rnd_init (rnd, 12345);
+ memset (buf, 0x42, sizeof (buf));
+ pos = 0;
+ test_begin (t, "padded buffer")
+ {
+ size = 64;
+ dbg_assert ((pos & 3) == 0 && ((pos + size) & 3) == 0);
+ rnd_buf_run (t, rnd, buf[0], buf[1], pos, size);
+ } test_end;
+ pos += size;
+ test_begin (t, "unpadded end")
+ {
+ size = 63;
+ dbg_assert ((pos & 3) == 0 && ((pos + size) & 3) == 3);
+ rnd_buf_run (t, rnd, buf[0], buf[1], pos, size);
+ } test_end;
+ pos += size;
+ test_begin (t, "unpadded both")
+ {
+ size = 63;
+ dbg_assert ((pos & 3) == 3 && ((pos + size) & 3) == 2);
+ rnd_buf_run (t, rnd, buf[0], buf[1], pos, size);
+ } test_end;
+ pos += size;
+ test_begin (t, "small")
+ {
+ size = 3;
+ dbg_assert ((pos & 3) == 2 && ((pos + size) & 3) == 1
+ && pos / 4 + 1 == (pos + size) / 4);
+ rnd_buf_run (t, rnd, buf[0], buf[1], pos, size);
+ } test_end;
+ pos += size;
+ test_begin (t, "tiny")
+ {
+ size = 2;
+ dbg_assert ((pos & 3) == 1 && ((pos + size) & 3) == 3
+ && pos / 4 == (pos + size) / 4);
+ rnd_buf_run (t, rnd, buf[0], buf[1], pos, size);
+ } test_end;
+ pos += size;
+ test_begin (t, "unpadded begin")
+ {
+ size = COUNT (buf[0]) - pos;
+ dbg_assert ((pos & 3) == 3 && ((pos + size) & 3) == 0);
+ rnd_buf_run (t, rnd, buf[0], buf[1], pos, size);
+ } test_end;
+ pos += size;
+}
+
+void
+rnd_test_suite (test_t t)
+{
+ test_suite_begin (t, "rnd");
+ rnd_basic_test_case (t);
+ rnd_buf_test_case (t);
+}
+
+int
+main (int argc, char **argv)
+{
+ test_t t;
+ test_init (t, argc, argv);
+ rnd_test_suite (t);
+ test_result (t);
+ return test_nb_failed (t) == 0 ? 0 : 1;
+}
diff --git a/cesar/lib/test/set/Makefile b/cesar/lib/test/set/Makefile
new file mode 100644
index 0000000000..7d601a0a1d
--- /dev/null
+++ b/cesar/lib/test/set/Makefile
@@ -0,0 +1,8 @@
+BASE = ../../..
+
+
+HOST_PROGRAMS = test_set
+test_set_SOURCES = test_set.c
+test_set_MODULES = lib
+
+include $(BASE)/common/make/top.mk
diff --git a/cesar/lib/test/set/src/test_set.c b/cesar/lib/test/set/src/test_set.c
new file mode 100644
index 0000000000..971c699cec
--- /dev/null
+++ b/cesar/lib/test/set/src/test_set.c
@@ -0,0 +1,362 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/test_set.c
+ * \brief Set test.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "lib/test.h"
+#include "lib/rnd.h"
+#include "lib/set.h"
+
+#define DEBUG_PRINT 0
+
+#if DEBUG_PRINT
+# include <stdio.h>
+# define NB_NODES 8
+# define NB_ITER 100
+# define NOT_TOO_BIG(x) ((x) & (NB_NODES * 2 - 1))
+#elif DEBUG
+# define NB_NODES 16384
+# define NB_ITER 10000
+# define NOT_TOO_BIG(x) (x)
+#else
+# define NB_NODES 131072
+# define NB_ITER 1000000
+# define NOT_TOO_BIG(x) (x)
+#endif
+
+/** Set node with an u32 data. */
+struct set_node_u32_t
+{
+ set_node_t node;
+ u32 data;
+};
+typedef struct set_node_u32_t set_node_u32_t;
+
+/**
+ * Comparison function for an u32 node.
+ * \param l left hand node
+ * \param r right hand node
+ * \return true iff left is lesser than right
+ */
+static bool
+set_u32_less (set_node_t *l, set_node_t *r)
+{
+ u32 ld, rd;
+ dbg_assert (l);
+ dbg_assert (r);
+ ld = PARENT_OF (set_node_u32_t, node, l)->data;
+ rd = PARENT_OF (set_node_u32_t, node, r)->data;
+ return ld < rd;
+}
+
+/**
+ * Check a node and recurse.
+ * \param t test context
+ * \param node node to check
+ * \param depth tree depth
+ * \param less comparison function
+ * \return tree size
+ */
+static uint
+set_check_node (test_t t, set_node_t *node, uint *depth, set_node_less_t less)
+{
+ test_within (t);
+ uint size, ldepth, rdepth;
+ dbg_assert (node && node != node->left);
+ dbg_assert (depth);
+ /* AA-tree structure checks. */
+ test_fail_unless (node->level > node->right->right->level);
+ test_fail_unless (node->level == node->left->level + 1);
+ test_fail_unless (node->level == node->right->level
+ || node->level == node->right->level + 1);
+ test_fail_unless (node->left == node->left->left
+ || node->left->father == node);
+ test_fail_unless (node->right == node->right->left
+ || node->right->father == node);
+ /* Binary search tree checks & stats. */
+ dbg_assert (node->left);
+ dbg_assert (node->right);
+ size = 1;
+ ldepth = rdepth = 0;
+ if (node->left != node->left->left)
+ {
+ test_fail_unless (less (node->left, node));
+ size += set_check_node (t, node->left, &ldepth, less);
+ }
+ if (node->right != node->right->left)
+ {
+ test_fail_unless (less (node, node->right));
+ size += set_check_node (t, node->right, &rdepth, less);
+ }
+ *depth = MAX (ldepth, rdepth) + 1;
+ return size;
+}
+
+/**
+ * Recursively check a tree.
+ * \param t test context
+ * \param set the tree to check
+ * \param depth tree depth
+ * \return tree size
+ */
+uint
+set_check (test_t t, set_t *set, uint *depth)
+{
+ test_within (t);
+ dbg_assert (set);
+ dbg_assert (depth);
+ if (set->root == set->root->left)
+ {
+ *depth = 0;
+ test_fail_unless (set_empty (set));
+ return 0;
+ }
+ else
+ {
+ test_fail_unless (!set_empty (set));
+ return set_check_node (t, set->root, depth, set->less);
+ }
+}
+
+#if DEBUG_PRINT
+
+/**
+ * Travel the tree at the \a p depth and print.
+ * \param node current node
+ * \param size number of characters available
+ * \param p depth to print
+ * \param c current recursion depth
+ */
+static void
+set_print_nodes (set_node_t *node, uint size, uint p, uint c)
+{
+ dbg_assert (node);
+ dbg_assert (p >= c);
+ if (p == c)
+ {
+ if (node->left == node)
+ {
+ printf ("%*s", size, " ");
+ }
+ else
+ {
+ uint before = (size + 1) / 2;
+ uint after = size - before;
+ uint data = PARENT_OF (set_node_u32_t, node, node)->data;
+ uint level = node->level;
+ /* ASCII codes... */
+#define GREY "\e[30;1m"
+#define BLACK "\e[0m"
+ printf ("%*u" GREY "%-*u" BLACK, before, data, after, level);
+ }
+ }
+ else
+ {
+ set_print_nodes (node->left, size, p, c + 1);
+ set_print_nodes (node->right, size, p, c + 1);
+ }
+}
+
+/**
+ * Print a tree.
+ * \param set tree to print
+ * \param depth tree depth
+ */
+static void
+set_print (set_t *set, uint depth)
+{
+ uint i, size;
+ dbg_assert (set);
+ printf ("depth: %d\n", depth);
+ /* Screen size is limited... */
+ size = 4 << (MIN (depth, 5u) - 1);
+ for (i = 0; i < MIN (depth, 6u); i++)
+ {
+ set_print_nodes (set->root, size / (1 << i), i, 0);
+ printf ("\n");
+ }
+ if (depth > 6u)
+ printf ("...\n");
+}
+
+#else /* !DEBUG_PRINT */
+# define set_print(set, depth)
+#endif /* !DEBUG_PRINT */
+
+void
+set_basic_test_case (test_t t)
+{
+ uint i, maxdepth, depth;
+ u64 sumdepth;
+ lib_rnd_t rnd[1];
+ set_t set;
+ set_node_u32_t nodes[NB_NODES];
+ test_case_begin (t, "basic");
+ lib_rnd_init (rnd, 1234);
+ /* Initialise. */
+ set_init (&set, set_u32_less);
+ for (i = 0; i < COUNT (nodes) / 2; i++)
+ {
+ set_node_init (&nodes[i].node);
+ nodes[i].data = i;
+ }
+ for (; i < COUNT (nodes); i++)
+ {
+ set_node_init (&nodes[i].node);
+ /* Ensure there is no duplicates. */
+ nodes[i].data = NOT_TOO_BIG ((lib_rnd32 (rnd) & ~(NB_NODES - 1)) | i);
+ }
+ /* Empty set tests. */
+ test_begin (t, "empty")
+ {
+ test_fail_unless (set_empty (&set));
+ test_fail_unless (set_begin (&set) == set_end (&set));
+ } test_end;
+ /* Insert. */
+ test_begin (t, "insert")
+ {
+ maxdepth = 0;
+ test_fail_unless (0 == set_check (t, &set, &depth));
+ for (i = 0; i < COUNT (nodes); i++)
+ {
+ test_fail_unless (set_insert (&set, &nodes[i].node));
+ if (DEBUG)
+ {
+ test_fail_unless (i + 1 == set_check (t, &set, &depth));
+ if (maxdepth < depth)
+ maxdepth = depth;
+ }
+ set_print (&set, depth);
+ }
+ if (DEBUG)
+ test_verbose_print ("count = %d, max depth = %d", COUNT (nodes),
+ maxdepth);
+ } test_end;
+ /* Insert duplicates, should be denied. */
+ test_begin (t, "insert dup")
+ {
+ set_node_u32_t dup;
+ set_node_init (&dup.node);
+ for (i = 0; i < COUNT (nodes); i++)
+ {
+ dup.data = nodes[i].data;
+ test_fail_if (set_insert (&set, &dup.node), "dup accepted");
+ }
+ } test_end;
+ /* Find nodes. */
+ test_begin (t, "find nodes")
+ {
+ for (i = 0; i < NB_ITER; i++)
+ {
+ set_node_u32_t k;
+ set_node_init (&k.node);
+ if (lib_rnd_flip_coin (rnd, LIB_RND_RATIO (0.5)))
+ {
+ /* Node in the set. */
+ set_node_u32_t *n;
+ n = &nodes[lib_rnd_uniform (rnd, NB_NODES)];
+ k.data = n->data;
+ test_fail_unless (set_find (&set, &k.node) == &n->node);
+ }
+ else
+ {
+ /* Node not in the set. */
+ u32 r;
+ do {
+ r = lib_rnd32 (rnd);
+ } while (nodes[r & (NB_NODES - 1)].data == r);
+ k.data = r;
+ test_fail_unless (set_find (&set, &k.node) == NULL);
+ }
+ }
+ } test_end;
+ /* Now, remove a node and insert it back. */
+ test_begin (t, "remove and insert")
+ {
+ sumdepth = 0;
+ maxdepth = 0;
+ for (i = 0; i < NB_ITER; i++)
+ {
+ set_node_u32_t *n, k;
+ u32 r;
+ set_node_init (&k.node);
+ n = &nodes[lib_rnd_uniform (rnd, NB_NODES)];
+ do {
+ r = NOT_TOO_BIG (lib_rnd32 (rnd));
+ k.data = r;
+ } while (set_find (&set, &k.node));
+ /* Remove. */
+ set_remove (&set, &n->node);
+ if (DEBUG)
+ {
+ test_fail_unless (COUNT (nodes) - 1
+ == set_check (t, &set, &depth));
+ if (maxdepth < depth)
+ maxdepth = depth;
+ }
+ set_print (&set, depth);
+ /* Insert. */
+ n->data = r;
+ test_fail_unless (set_insert (&set, &n->node));
+ if (DEBUG)
+ {
+ test_fail_unless (COUNT (nodes)
+ == set_check (t, &set, &depth));
+ if (maxdepth < depth)
+ maxdepth = depth;
+ sumdepth += depth;
+ }
+ set_print (&set, depth);
+ }
+ if (DEBUG)
+ test_verbose_print ("count = %d, avg depth = %d, max depth = %d",
+ COUNT (nodes), (uint) (sumdepth / NB_ITER),
+ maxdepth);
+ } test_end;
+ /* Check order. */
+ test_begin (t, "order")
+ {
+ uint size, last, data;
+ set_node_t *n;
+ n = set_begin (&set);
+ test_fail_if (!n || n == set_end (&set));
+ last = PARENT_OF (set_node_u32_t, node, n)->data;
+ size = 1;
+ for (n = set_next (&set, n); n != set_end (&set);
+ n = set_next (&set, n))
+ {
+ test_fail_unless (n);
+ data = PARENT_OF (set_node_u32_t, node, n)->data;
+ test_fail_unless (last < data, "broken order");
+ last = data;
+ size++;
+ }
+ test_fail_unless (size == COUNT (nodes));
+ } test_end;
+}
+
+void
+set_test_suite (test_t t)
+{
+ test_suite_begin (t, "set");
+ set_basic_test_case (t);
+}
+
+int
+main (int argc, char **argv)
+{
+ test_t t;
+ test_init (t, argc, argv);
+ set_test_suite (t);
+ test_result (t);
+ return test_nb_failed (t) == 0 ? 0 : 1;
+}
diff --git a/cesar/lib/test/test/Config b/cesar/lib/test/test/Config
new file mode 100644
index 0000000000..1221024089
--- /dev/null
+++ b/cesar/lib/test/test/Config
@@ -0,0 +1 @@
+CONFIG_DEBUG_FATAL_CATCH = y
diff --git a/cesar/lib/test/test/Makefile b/cesar/lib/test/test/Makefile
new file mode 100644
index 0000000000..9d10954870
--- /dev/null
+++ b/cesar/lib/test/test/Makefile
@@ -0,0 +1,8 @@
+BASE = ../../..
+
+
+HOST_PROGRAMS = test_test
+test_test_SOURCES = test_test.c
+test_test_MODULES = lib
+
+include $(BASE)/common/make/top.mk
diff --git a/cesar/lib/test/test/src/test_test.c b/cesar/lib/test/test/src/test_test.c
new file mode 100644
index 0000000000..78409f8f5d
--- /dev/null
+++ b/cesar/lib/test/test/src/test_test.c
@@ -0,0 +1,90 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/test_test.c
+ * \brief Test the test infrastructure.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "lib/test.h"
+
+void
+mytest_basic_test_case (test_t t)
+{
+ uint i;
+ test_case_begin (t, "basic");
+ test_begin (t, "test no fail")
+ {
+ } test_end;
+ test_begin (t, "test_fail_unless ok")
+ {
+ test_fail_unless (1 == 1);
+ } test_end;
+ test_begin (t, "test_fail_unless nok")
+ {
+ test_fail_unless (1 == 2);
+ } test_end;
+ test_begin (t, "test_fail_if print nok")
+ {
+ test_fail_if (1 != 2, "%d is not %d", 1, 2);
+ } test_end;
+ test_begin (t, "test_fail_if loop nok after 5")
+ {
+ for (i = 0; i < 10; i++)
+ {
+ test_verbose_print ("i = %d", i);
+ if (i > 5)
+ test_fail ("fail at i = %d", i);
+ }
+ } test_end;
+ test_begin (t, "catch assert")
+ {
+ dbg_fatal_try_begin
+ {
+ dbg_assert (1 == 2);
+ }
+ dbg_fatal_try_catch (const char *the_error)
+ {
+ test_verbose_print ("catched: %s", the_error);
+ }
+ dbg_fatal_try_end;
+ } test_end;
+ test_begin (t, "no catch assert")
+ {
+ dbg_assert (1 == 2);
+ } test_end;
+ test_begin (t, "division by zero")
+ {
+ uint a = 1;
+ uint b = 0;
+ uint c = a / b;
+ test_verbose_print ("can you compute this: %d", c);
+ } test_end;
+ test_begin (t, "segmentation fault")
+ {
+ *(u32 *) NULL = 0;
+ } test_end;
+}
+
+void
+mytest_test_suite (test_t t)
+{
+ test_suite_begin (t, "mytest");
+ mytest_basic_test_case (t);
+}
+
+int
+main (int argc, char **argv)
+{
+ test_t t;
+ test_init (t, argc, argv);
+ mytest_test_suite (t);
+ test_result (t);
+ return test_nb_failed (t) == 0 ? 0 : 1;
+}
diff --git a/cesar/lib/test/trace/Config b/cesar/lib/test/trace/Config
new file mode 100644
index 0000000000..79839151a9
--- /dev/null
+++ b/cesar/lib/test/trace/Config
@@ -0,0 +1,2 @@
+CONFIG_DEBUG_MORE = y
+CONFIG_TRACE = y
diff --git a/cesar/lib/test/trace/Makefile b/cesar/lib/test/trace/Makefile
new file mode 100644
index 0000000000..475dfc75b9
--- /dev/null
+++ b/cesar/lib/test/trace/Makefile
@@ -0,0 +1,7 @@
+BASE = ../../..
+
+HOST_PROGRAMS = test_trace
+test_trace_SOURCES = test_trace.c
+test_trace_MODULES = lib
+
+include $(BASE)/common/make/top.mk
diff --git a/cesar/lib/test/trace/src/test_trace.c b/cesar/lib/test/trace/src/test_trace.c
new file mode 100644
index 0000000000..c2d1f0e8ff
--- /dev/null
+++ b/cesar/lib/test/trace/src/test_trace.c
@@ -0,0 +1,302 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/test_trace.c
+ * \brief Trace test.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "lib/rnd.h"
+#include "lib/trace.h"
+#include "lib/test.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#define NB_ITER 100000
+#define MAX_ARGS 8
+
+#define NB_PRINT 1000
+
+struct growing_buffer_t
+{
+ char *buf;
+ uint buf_pos;
+ uint buf_size;
+};
+typedef struct growing_buffer_t growing_buffer_t;
+
+int
+dump_callback (void *user, char *text, uint text_size)
+{
+ dbg_assert (user);
+ dbg_assert (text && text_size != 0);
+ growing_buffer_t *g = user;
+ /* Grow buffer if necessary. */
+ if (g->buf_pos + text_size >= g->buf_size)
+ {
+ g->buf_size = (g->buf_size + text_size) * 2;
+ g->buf = realloc (g->buf, g->buf_size);
+ dbg_assert (g->buf);
+ }
+ /* Copy data. */
+ memcpy (g->buf + g->buf_pos, text, text_size);
+ g->buf_pos += text_size;
+ return text_size;
+}
+
+void
+growing_sprintf (growing_buffer_t *g, const char *fmt, ...)
+{
+ dbg_assert (g);
+ dbg_assert (fmt);
+ va_list ap;
+ va_start (ap, fmt);
+ do
+ {
+ int ret = vsnprintf (g->buf + g->buf_pos, g->buf_size - g->buf_pos,
+ fmt, ap);
+ // Hum, ecos does not use the same meaning for the return value.
+ if (ret != -1 && ret < (int) (g->buf_size - g->buf_pos - 1))
+ {
+ g->buf_pos += ret;
+ break;
+ }
+ else
+ {
+ g->buf_size *= 2;
+ g->buf = realloc (g->buf, g->buf_size);
+ dbg_assert (g->buf);
+ }
+ } while (1);
+}
+
+void
+trace_basic_test_case (test_t t)
+{
+ uint i, j;
+ lib_rnd_t rnd[1];
+ trace_buffer_t trace_buf[3];
+ uint sum[COUNT (trace_buf)] = { };
+ /* Initialise. */
+ test_case_begin (t, "basic");
+ lib_rnd_init (rnd, 1234);
+ trace_init ();
+ /* Test. */
+ test_begin (t, "massive print and drop")
+ {
+ trace_buffer_add (&trace_buf[0], "one", 2, 4, true, NULL);
+ trace_buffer_add (&trace_buf[1], "two", 2, 1, false, NULL);
+ trace_buffer_add (&trace_buf[2], "three", 0, 1, false, NULL);
+ for (i = 0; i < NB_ITER; i++)
+ {
+ if (lib_rnd_flip_coin (rnd, LIB_RND_RATIO (0.995)))
+ {
+ /* Trace. */
+ uint buf_i = lib_rnd_uniform (rnd, COUNT (trace_buf));
+ uint arg_nb = lib_rnd_uniform (rnd, MAX_ARGS + 1);
+ uint args[MAX_ARGS];
+ for (j = 0; j < arg_nb; j++)
+ args[j] = lib_rnd32 (rnd);
+ /* trace_(fast_)?print\d (...) {{{ */
+ if (trace_buf[buf_i].locked)
+ {
+ switch (arg_nb)
+ {
+ case 8:
+ trace_fast_print8 (&trace_buf[buf_i], i, args[0],
+ args[1], args[2], args[3], args[4],
+ args[5], args[6], args[7]);
+ break;
+ case 7:
+ trace_fast_print7 (&trace_buf[buf_i], i, args[0],
+ args[1], args[2], args[3], args[4],
+ args[5], args[6]);
+ break;
+ case 6:
+ trace_fast_print6 (&trace_buf[buf_i], i, args[0],
+ args[1], args[2], args[3], args[4],
+ args[5]);
+ break;
+ case 5:
+ trace_fast_print5 (&trace_buf[buf_i], i, args[0],
+ args[1], args[2], args[3],
+ args[4]);
+ break;
+ case 4:
+ trace_fast_print4 (&trace_buf[buf_i], i, args[0],
+ args[1], args[2], args[3]);
+ break;
+ case 3:
+ trace_fast_print3 (&trace_buf[buf_i], i, args[0],
+ args[1], args[2]);
+ break;
+ case 2:
+ trace_fast_print2 (&trace_buf[buf_i], i, args[0],
+ args[1]);
+ break;
+ case 1:
+ trace_fast_print1 (&trace_buf[buf_i], i, args[0]);
+ break;
+ case 0:
+ trace_fast_print0 (&trace_buf[buf_i], i);
+ break;
+ }
+ }
+ else
+ {
+ switch (arg_nb)
+ {
+ case 8:
+ trace_print8 (&trace_buf[buf_i], i, args[0], args[1],
+ args[2], args[3], args[4], args[5],
+ args[6], args[7]);
+ break;
+ case 7:
+ trace_print7 (&trace_buf[buf_i], i, args[0], args[1],
+ args[2], args[3], args[4], args[5],
+ args[6]);
+ break;
+ case 6:
+ trace_print6 (&trace_buf[buf_i], i, args[0], args[1],
+ args[2], args[3], args[4], args[5]);
+ break;
+ case 5:
+ trace_print5 (&trace_buf[buf_i], i, args[0], args[1],
+ args[2], args[3], args[4]);
+ break;
+ case 4:
+ trace_print4 (&trace_buf[buf_i], i, args[0], args[1],
+ args[2], args[3]);
+ break;
+ case 3:
+ trace_print3 (&trace_buf[buf_i], i, args[0], args[1],
+ args[2]);
+ break;
+ case 2:
+ trace_print2 (&trace_buf[buf_i], i, args[0], args[1]);
+ break;
+ case 1:
+ trace_print1 (&trace_buf[buf_i], i, args[0]);
+ break;
+ case 0:
+ trace_print0 (&trace_buf[buf_i], i);
+ break;
+ }
+ }
+ /* }}} */
+ }
+ else
+ {
+ /* Drop chunks. */
+ uint chunks_nb = 0;
+ for (j = 0; j < COUNT (trace_buf); j++)
+ {
+ dbg_assert (trace_buf[j].chunks_nb
+ >= trace_buf[j].preload);
+ chunks_nb += trace_buf[j].chunks_nb
+ - trace_buf[j].preload;
+ }
+ trace_drop_chunks (1 + (chunks_nb > 30
+ ? lib_rnd_uniform (rnd, chunks_nb - 30)
+ : 0));
+ }
+ for (j = 0; j < COUNT (trace_buf); j++)
+ sum[j] += trace_buf[j].chunks_nb;
+ }
+ test_verbose_print ("avg chunks_nb: %d %d %d",
+ sum[0] / NB_ITER,
+ sum[1] / NB_ITER,
+ sum[2] / NB_ITER);
+ trace_buffer_remove (&trace_buf[0]);
+ trace_buffer_remove (&trace_buf[1]);
+ trace_buffer_remove (&trace_buf[2]);
+ } test_end;
+ test_begin (t, "dump")
+ {
+#define TEST_TRACE_TRACE(id, args...) \
+ TRACE_SHORT (TEST_TRACE_TRACE_, &trace_buf[0], id, ## args)
+ enum
+ {
+ TEST_TRACE_TRACE_ONE,
+ TEST_TRACE_TRACE_TWO,
+ TEST_TRACE_TRACE_THREE,
+ TEST_TRACE_TRACE_FOUR,
+ };
+ static const trace_event_id_t ei[] = {
+ TRACE_EVENT (TEST_TRACE_TRACE_ONE, "one"),
+ TRACE_EVENT (TEST_TRACE_TRACE_TWO, "two %d", TIMESTAMP),
+ TRACE_EVENT (TEST_TRACE_TRACE_THREE, "three %u, %x, %d, %b, %b"),
+ TRACE_EVENT (TEST_TRACE_TRACE_FOUR, "four %m, %d"),
+ };
+ trace_namespace_t ns;
+ trace_namespace_init (&ns, ei, COUNT (ei));
+ trace_buffer_add (&trace_buf[0], "trace", 2, 1, false, &ns);
+ /* Trace and record expected trace. */
+ growing_buffer_t expected_dump;
+ expected_dump.buf_pos = 0;
+ expected_dump.buf_size = 100;
+ expected_dump.buf = malloc (expected_dump.buf_size);
+ dbg_assert (expected_dump.buf);
+ for (i = 0; i < NB_PRINT; i++)
+ {
+ trace_print0 (&trace_buf[0], TEST_TRACE_TRACE_ONE);
+ growing_sprintf (&expected_dump, "[.] one\n");
+ TEST_TRACE_TRACE (TWO, 0x123abc ^ i, -123456789 + i);
+ growing_sprintf (&expected_dump, "[0x%08x] two %d\n",
+ 0x123abc ^ i, -123456789 + i);
+ TEST_TRACE_TRACE (THREE, 123456789 - i, 0xabcdef ^ i, 1, true,
+ false);
+ growing_sprintf (&expected_dump,
+ "[.] three %u, 0x%08x, %d, %s, %s\n",
+ 123456789 - i, 0xabcdef ^ i, 1, "true", "false");
+ TEST_TRACE_TRACE (FOUR, TRACE_U64 (0xbc9a78563412LL), i);
+ growing_sprintf (&expected_dump,
+ "[.] four 12:34:56:78:9a:bc, %d\n", i);
+ }
+ test_verbose_print ("%s", expected_dump.buf);
+ /* Dump to memory. */
+ growing_buffer_t dump;
+ dump.buf_pos = 0;
+ dump.buf_size = 100;
+ dump.buf = malloc (dump.buf_size);
+ dbg_assert (dump.buf);
+ int ret = trace_buffer_dump (&trace_buf[0], dump_callback, &dump);
+ /* Check dump. */
+ test_fail_unless (expected_dump.buf_pos == dump.buf_pos);
+ test_fail_unless ((int) dump.buf_pos == ret);
+ test_fail_unless (memcmp (expected_dump.buf, dump.buf, dump.buf_pos)
+ == 0);
+ /* Cleanup. */
+ free (expected_dump.buf);
+ free (dump.buf);
+ trace_buffer_remove (&trace_buf[0]);
+ } test_end;
+ /* Uninit. */
+ trace_uninit ();
+}
+
+void
+trace_test_suite (test_t t)
+{
+ test_suite_begin (t, "trace");
+ trace_basic_test_case (t);
+}
+
+int
+main (int argc, char **argv)
+{
+ test_t t;
+ test_init (t, argc, argv);
+ trace_test_suite (t);
+ test_result (t);
+ return test_nb_failed (t) == 0 ? 0 : 1;
+}
diff --git a/cesar/lib/test/try/Makefile b/cesar/lib/test/try/Makefile
new file mode 100644
index 0000000000..dd7f7b4771
--- /dev/null
+++ b/cesar/lib/test/try/Makefile
@@ -0,0 +1,8 @@
+BASE = ../../..
+
+
+HOST_PROGRAMS = test_try
+test_try_SOURCES = test_try.c
+test_try_MODULES = lib
+
+include $(BASE)/common/make/top.mk
diff --git a/cesar/lib/test/try/src/test_try.c b/cesar/lib/test/try/src/test_try.c
new file mode 100644
index 0000000000..86a843da5b
--- /dev/null
+++ b/cesar/lib/test/try/src/test_try.c
@@ -0,0 +1,125 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/test_try.c
+ * \brief Test light exception support.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "lib/try.h"
+#include "lib/test.h"
+
+void
+try_basic_test_case (test_t t)
+{
+ test_case_begin (t, "basic");
+ test_begin (t, "no throw")
+ {
+ bool always = false;
+ try_begin
+ {
+ }
+ try_catch (100)
+ {
+ test_fail ("threw");
+ }
+ try_end;
+ try_begin
+ {
+ }
+ try_catch (100)
+ {
+ test_fail ("threw");
+ }
+ try_always
+ {
+ always = true;
+ }
+ try_end;
+ test_fail_unless (always, "did not execute the always block");
+ } test_end;
+ test_begin (t, "throw catch")
+ {
+ bool caught = false;
+ bool always = false;
+ try_begin
+ {
+ try_throw (100);
+ }
+ try_catch (100)
+ {
+ caught = true;
+ }
+ try_end;
+ test_fail_unless (caught, "did not execute the catch block");
+ caught = false;
+ try_begin
+ {
+ try_throw (100);
+ }
+ try_catch (100)
+ {
+ caught = true;
+ }
+ try_always
+ {
+ always = true;
+ }
+ try_end;
+ test_fail_unless (caught, "did not execute the catch block");
+ test_fail_unless (always, "did not execute the always block");
+ } test_end;
+ test_begin (t, "throw again")
+ {
+ int pass = 3;
+ try_begin
+ {
+ try_begin
+ {
+ try_throw (100);
+ }
+ try_catch (101)
+ {
+ test_fail ("threw 101");
+ }
+ try_always
+ {
+ pass--;
+ }
+ try_end;
+ }
+ try_catch (100)
+ {
+ pass--;
+ }
+ try_always
+ {
+ pass--;
+ }
+ try_end;
+ test_fail_unless (pass == 0, "did not execute some block");
+ } test_end;
+}
+
+void
+try_test_suite (test_t t)
+{
+ test_suite_begin (t, "try");
+ try_basic_test_case (t);
+}
+
+int
+main (int argc, char **argv)
+{
+ test_t t;
+ test_init (t, argc, argv);
+ try_test_suite (t);
+ test_result (t);
+ return test_nb_failed (t) == 0 ? 0 : 1;
+}
diff --git a/cesar/lib/test/utils/Makefile b/cesar/lib/test/utils/Makefile
new file mode 100644
index 0000000000..5d78d56e6b
--- /dev/null
+++ b/cesar/lib/test/utils/Makefile
@@ -0,0 +1,7 @@
+BASE = ../../..
+
+HOST_PROGRAMS = test_utils
+test_utils_SOURCES = test_utils.c
+test_utils_MODULES = lib
+
+include $(BASE)/common/make/top.mk
diff --git a/cesar/lib/test/utils/src/test_utils.c b/cesar/lib/test/utils/src/test_utils.c
new file mode 100644
index 0000000000..23ef0307cf
--- /dev/null
+++ b/cesar/lib/test/utils/src/test_utils.c
@@ -0,0 +1,65 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/test_utils.c
+ * \brief Utilities tests.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "lib/test.h"
+
+void
+bits_test_case (test_t t)
+{
+ test_case_begin (t, "bits");
+ test_begin (t, "ones")
+ {
+ test_fail_unless (BITS_ONES_COUNT ((u8) 0x00) == 0);
+ test_fail_unless (BITS_ONES_COUNT ((u8) 0x0f) == 4);
+ test_fail_unless (BITS_ONES_COUNT ((u8) 0xf0) == 4);
+ test_fail_unless (BITS_ONES_COUNT ((u8) 0xa5) == 4);
+ test_fail_unless (BITS_ONES_COUNT ((u8) 0xff) == 8);
+ test_fail_unless (BITS_ONES_COUNT ((u16) 0x0000) == 0);
+ test_fail_unless (BITS_ONES_COUNT ((u16) 0x0f0f) == 8);
+ test_fail_unless (BITS_ONES_COUNT ((u16) 0xf0f0) == 8);
+ test_fail_unless (BITS_ONES_COUNT ((u16) 0xa5a5) == 8);
+ test_fail_unless (BITS_ONES_COUNT ((u16) 0xffff) == 16);
+ test_fail_unless (BITS_ONES_COUNT ((u32) 0x00000000) == 0);
+ test_fail_unless (BITS_ONES_COUNT ((u32) 0x0f0f0f0f) == 16);
+ test_fail_unless (BITS_ONES_COUNT ((u32) 0xf0f0f0f0) == 16);
+ test_fail_unless (BITS_ONES_COUNT ((u32) 0xa5a5a5a5) == 16);
+ test_fail_unless (BITS_ONES_COUNT ((u32) 0xffffffff) == 32);
+ test_fail_unless (BITS_ONES_COUNT ((u64) 0x0000000000000000ull) == 0);
+ test_fail_unless (BITS_ONES_COUNT ((u64) 0x0f0f0f0f0f0f0f0full)
+ == 32);
+ test_fail_unless (BITS_ONES_COUNT ((u64) 0xf0f0f0f0f0f0f0f0ull)
+ == 32);
+ test_fail_unless (BITS_ONES_COUNT ((u64) 0xa5a5a5a5a5a5a5a5ull)
+ == 32);
+ test_fail_unless (BITS_ONES_COUNT ((u64) 0xffffffffffffffffull)
+ == 64);
+ } test_end;
+}
+
+void
+utils_test_suite (test_t t)
+{
+ test_suite_begin (t, "utils");
+ bits_test_case (t);
+}
+
+int
+main (int argc, char **argv)
+{
+ test_t t;
+ test_init (t, argc, argv);
+ utils_test_suite (t);
+ test_result (t);
+ return test_nb_failed (t) == 0 ? 0 : 1;
+}
diff --git a/cesar/lib/trace.h b/cesar/lib/trace.h
new file mode 100644
index 0000000000..10da874ddf
--- /dev/null
+++ b/cesar/lib/trace.h
@@ -0,0 +1,403 @@
+#ifndef lib_trace_h
+#define lib_trace_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/trace.h
+ * \brief Trace system.
+ * \ingroup lib
+ *
+ * The trace system provides an events recording system. It is coupled with
+ * the dynamic allocation system in order to use all the available memory for
+ * trace buffers.
+ */
+#include "config/trace.h"
+
+#if CONFIG_TRACE
+
+#include "lib/blk.h"
+#include "lib/list.h"
+
+/** Useful to initialise a trace_event_id_t. */
+#define TRACE_EVENT(id, format_string_, options...) \
+[(id)] = { .format_string = (format_string_) \
+ PREPROC_FOR_EACH (TRACE_EVENT_OPTIONS_, options) }
+#define TRACE_EVENT_OPTIONS_(option) , PASTE (TRACE_EVENT_OPTIONS_, option)
+#define TRACE_EVENT_OPTIONS_TIMESTAMP .timestamp = true
+
+/** Could be used to define tracing shortcut.
+ * \param prefix text to prepend to id symbol
+ * \param buffer trace buffer
+ * \param id event id postfix part
+ * \param args optional arguments
+ *
+ * This macro will count its arguments, call the right trace function and cast
+ * each arguments to an integer.
+ */
+#define TRACE_SHORT(prefix, buffer, id, args...) \
+ PASTE_EXPAND (trace_print, PREPROC_NARG (args)) \
+((buffer), PREPROC_FOR_EACH_COMMA (TRACE_SHORT_CAST, \
+ PASTE (prefix, id), ## args))
+#define TRACE_SHORT_CAST(x) ((int) (x))
+
+/** Could be used to define tracing shortcut for fast traces.
+ * See TRACE_SHORT.
+ */
+#define TRACE_FAST_SHORT(prefix, buffer, id, args...) \
+ PASTE_EXPAND (trace_fast_print, PREPROC_NARG (args)) \
+((buffer), PREPROC_FOR_EACH_COMMA (TRACE_SHORT_CAST, \
+ PASTE (prefix, id), ## args))
+
+/** Split a 64 bit parameter in two parameters, lsb first. Will evaluate the
+ * argument two times. */
+#define TRACE_U64(dw) \
+ ((u32) ((dw) & 0xffffffff)), ((u32) ((dw) >> 32))
+
+/* Forward declarations. */
+typedef struct trace_t trace_t;
+typedef struct trace_buffer_t trace_buffer_t;
+typedef struct trace_chunk_t trace_chunk_t;
+typedef struct trace_namespace_t trace_namespace_t;
+
+/** Trace buffer context. */
+struct trace_buffer_t
+{
+ /** List node in trace context. */
+ list_node_t node;
+ /** Number of chunks. */
+ uint chunks_nb;
+ /** Drop policy level, 0-31. See trace_drop_chunks(). */
+ uint drop_level;
+ /** Reserved chunks, there will be always at least that much chunks in
+ * this buffer. Theses extra buffers can be used to write events without
+ * allocating new chunks. */
+ uint preload;
+ /** Is this buffer locked? Locked buffers can not lose chunks. */
+ bool locked;
+ /** Pointer to head (older) chunk descriptor in this buffer. */
+ trace_chunk_t *head;
+ /** Pointer to tail (newer, current) chunk descriptor in this buffer. */
+ trace_chunk_t *tail;
+ /** Trace buffer name. */
+ const char *name;
+ /** Name space used for text dump. */
+ trace_namespace_t *namespace;
+};
+
+/** Trace buffer chunk descriptor. */
+struct trace_chunk_t
+{
+ /** Next (newer) chunk in this trace buffer. */
+ trace_chunk_t *next;
+ /** Data in this chunk. */
+ u32 *data;
+ /** Number of data words in this chunk. */
+ u32 *data_end;
+ /** Maximum usable data words. */
+ u32 *chunk_end;
+};
+
+/**
+ * Callback for trace formating.
+ * \param text text buffer to write to
+ * \param text_size text buffer size
+ * \param data data to format
+ * \return number of characters written, or -1 for error
+ *
+ * This callback is not supposed to append any trailing new line or null
+ * character.
+ *
+ * Note that the return value can not be used to know how many characters
+ * would have been necessary.
+ */
+typedef int (*trace_format_u32_t) (char *text, uint text_size, int data);
+
+/**
+ * Callback for trace formating, 64 bit version.
+ * \param text text buffer to write to
+ * \param text_size text buffer size
+ * \param data data to format
+ * \return number of characters written, or -1 for error
+ *
+ * This callback is not supposed to append any trailing new line or null
+ * character.
+ *
+ * Note that the return value can not be used to know how many characters
+ * would have been necessary.
+ */
+typedef int (*trace_format_u64_t) (char *text, uint text_size, u64 data);
+
+/** Trace event id. */
+struct trace_event_id_t
+{
+ /** Associated format string. */
+ const char *format_string;
+ /** Is the first parameter a timestamp? */
+ bool timestamp;
+};
+typedef struct trace_event_id_t trace_event_id_t;
+
+/** Trace arguments formatting. */
+struct trace_format_t
+{
+ /** Number of used parameters. */
+ uint size;
+ /** Formatting callback. */
+ union {
+ /** 32 bit version. */
+ trace_format_u32_t format_u32;
+ /** 64 bit version. */
+ trace_format_u64_t format_u64;
+ } callback;
+};
+typedef struct trace_format_t trace_format_t;
+
+/** Trace name space. Provides information to dump a trace buffer as text. */
+struct trace_namespace_t
+{
+ /** Map an event identifier to its format string. */
+ const trace_event_id_t *event_ids;
+ /** Number of registered events. */
+ uint event_ids_nb;
+ /** Map a format letter to its formatting callback. */
+ trace_format_t formats['z' - 'A' + 1];
+};
+
+/**
+ * Callback for text dump.
+ * \param user user parameter
+ * \param text text buffer with text to write
+ * \param text_size size of text to write, i.e. number of characters
+ * \return should return size, any other value will stop dump
+ */
+typedef int (*trace_dump_callback_t) (void *user, char *text, uint text_size);
+
+BEGIN_DECLS
+
+/**
+ * Initialise the trace system.
+ */
+void
+trace_init (void);
+
+/**
+ * Uninitialise the trace system.
+ */
+void
+trace_uninit (void);
+
+/**
+ * Try to drop chunks in order to release memory.
+ * \param n number of chunk to release
+ * \return false if no more memory can be released
+ *
+ * The trace system is supposed to use all the remaining memory of the system.
+ * However, its priority is of course lesser than other modules. When there
+ * is a memory starvation, the allocator call this method to ask the trace
+ * module to release memory.
+ *
+ * As there is several different trace buffers, the question is now to decide
+ * which trace buffer should drop data. All trace buffers share the remaining
+ * memory, but some buffers can use more memory than others. This is
+ * represented by the drop_level parameter. Each trace buffer will have its
+ * memory part divided by 2^drop_level. This means that a trace buffer with
+ * drop_level = 0 will use twice as much memory than a trace buffer with
+ * drop_level = 1, and so on...
+ *
+ * The preload parameter defines a number of reserved trace chunks which do
+ * not count towards this sharing system.
+ *
+ * Note that the blocks are released, not freed. This means that if some
+ * chunks are referenced by another component, this function can free less
+ * memory than expected.
+ */
+bool
+trace_drop_chunks (uint n);
+
+/**
+ * Initialise a name space and fill default formats.
+ * \param ns name space to initialise
+ * \param event_ids table of event id
+ * \param event_ids_nb number of event id in the table
+ */
+void
+trace_namespace_init (trace_namespace_t *ns,
+ const trace_event_id_t *event_ids, uint event_ids_nb);
+
+/**
+ * Register a format code.
+ * \param ns the name space
+ * \param code the assigned code
+ * \param format the formating callback
+ */
+void
+trace_namespace_register_format (trace_namespace_t *ns, char code,
+ trace_format_u32_t format);
+
+/**
+ * Register a format code for u64 parameters.
+ * \param ns the name space
+ * \param code the assigned code
+ * \param format the formating callback
+ */
+void
+trace_namespace_register_format_u64 (trace_namespace_t *ns, char code,
+ trace_format_u64_t format);
+
+/**
+ * Add a new trace buffer.
+ * \param buf the uninitialised buffer structure to add
+ * \param name buffer name
+ * \param drop_level the buffer drop_level (see trace_drop_chunks())
+ * \param preload the buffer preload, this many chunks are allocated
+ * immediately (minimum 1)
+ * \param locked the buffer will not participate in the remaining memory
+ * sharing, use for real time trace buffers
+ * \param namespace name space for trace text dump
+ */
+void
+trace_buffer_add (trace_buffer_t *buf, const char *name, uint drop_level,
+ uint preload, bool locked, trace_namespace_t *namespace);
+
+/**
+ * Remove a trace buffer and release used memory.
+ * \param buf the buffer to remove
+ */
+void
+trace_buffer_remove (trace_buffer_t *buf);
+
+/**
+ * Dump a full trace buffer as text.
+ * \param buf trace buffer
+ * \param cb callback called several times with text data
+ * \param user user data passed to the callback
+ * \return number of character written or -1 on any error (if one callback
+ * did not return its size parameter)
+ */
+int
+trace_buffer_dump (trace_buffer_t *buf, trace_dump_callback_t cb, void *user);
+
+/**
+ * Dump a full trace buffer as text during debug.
+ * \param buf trace buffer
+ *
+ * This can be useful to dump a trace buffer from a debugger.
+ */
+void
+trace_buffer_dbg_dump (trace_buffer_t *buf);
+
+/**
+ * Write event to trace buffer.
+ * \param buf the trace buffer to write to
+ * \param id event identifier
+ *
+ * If no room left, a new chunk is allocated.
+ */
+void
+trace_print0 (trace_buffer_t *buf, uint id);
+
+/** See trace_print0(). */
+void
+trace_print1 (trace_buffer_t *buf, uint id, int arg0);
+
+/** See trace_print0(). */
+void
+trace_print2 (trace_buffer_t *buf, uint id, int arg0, int arg1);
+
+/** See trace_print0(). */
+void
+trace_print3 (trace_buffer_t *buf, uint id, int arg0, int arg1, int arg2);
+
+/** See trace_print0(). */
+void
+trace_print4 (trace_buffer_t *buf, uint id, int arg0, int arg1, int arg2,
+ int arg3);
+
+/** See trace_print0(). */
+void
+trace_print5 (trace_buffer_t *buf, uint id, int arg0, int arg1, int arg2,
+ int arg3, int arg4);
+
+/** See trace_print0(). */
+void
+trace_print6 (trace_buffer_t *buf, uint id, int arg0, int arg1, int arg2,
+ int arg3, int arg4, int arg5);
+
+/** See trace_print0(). */
+void
+trace_print7 (trace_buffer_t *buf, uint id, int arg0, int arg1, int arg2,
+ int arg3, int arg4, int arg5, int arg6);
+
+/** See trace_print0(). */
+void
+trace_print8 (trace_buffer_t *buf, uint id, int arg0, int arg1, int arg2,
+ int arg3, int arg4, int arg5, int arg6, int arg7);
+
+/**
+ * Write event to trace buffer, fast version.
+ * \param buf the trace buffer to write to
+ * \param id event identifier
+ *
+ * The fast version will never allocate new memory to record the provided
+ * event. This is useful when real time constrains forbid any undefined
+ * complexity algorithms.
+ */
+void
+trace_fast_print0 (trace_buffer_t *buf, uint id);
+
+/** See trace_fast_print0(). */
+void
+trace_fast_print1 (trace_buffer_t *buf, uint id, int arg1);
+
+/** See trace_fast_print0(). */
+void
+trace_fast_print2 (trace_buffer_t *buf, uint id, int arg1, int arg2);
+
+/** See trace_fast_print0(). */
+void
+trace_fast_print3 (trace_buffer_t *buf, uint id, int arg1, int arg2,
+ int arg3);
+
+/** See trace_fast_print0(). */
+void
+trace_fast_print4 (trace_buffer_t *buf, uint id, int arg1, int arg2, int arg3,
+ int arg4);
+
+/** See trace_fast_print0(). */
+void
+trace_fast_print5 (trace_buffer_t *buf, uint id, int arg1, int arg2, int arg3,
+ int arg4, int arg5);
+
+/** See trace_fast_print0(). */
+void
+trace_fast_print6 (trace_buffer_t *buf, uint id, int arg1, int arg2, int arg3,
+ int arg4, int arg5, int arg6);
+
+/** See trace_fast_print0(). */
+void
+trace_fast_print7 (trace_buffer_t *buf, uint id, int arg1, int arg2, int arg3,
+ int arg4, int arg5, int arg6, int arg7);
+
+/** See trace_fast_print0(). */
+void
+trace_fast_print8 (trace_buffer_t *buf, uint id, int arg1, int arg2, int arg3,
+ int arg4, int arg5, int arg6, int arg7, int arg8);
+
+END_DECLS
+
+#else /* !CONFIG_TRACE */
+
+# define trace_init() ((void) 0)
+# define trace_uninit() ((void) 0)
+# define trace_drop_chunks(n) ((void) ((n), 0))
+# define TRACE_SHORT(prefix, buffer, id, args...) ((void) 0)
+# define TRACE_FAST_SHORT(prefix, buffer, id, args...) ((void) 0)
+
+#endif /* !CONFIG_TRACE */
+
+#endif /* lib_trace_h */
diff --git a/cesar/lib/try.h b/cesar/lib/try.h
new file mode 100644
index 0000000000..563ad7c4dd
--- /dev/null
+++ b/cesar/lib/try.h
@@ -0,0 +1,120 @@
+#ifndef lib_try_h
+#define lib_try_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/try.h
+ * \brief Light exception system.
+ * \ingroup lib
+ *
+ * This system mimics C++ exception handling using C setjmp/longjmp. Hey, but
+ * this is not as safe as C++ exceptions!
+ *
+ * Here is an example use:
+ *
+ * \code
+ * try_begin
+ * {
+ * ...some code...
+ * try_throw (code thrown);
+ * ...some code...
+ * }
+ * try_catch (code to catch)
+ * {
+ * ...handle exception...
+ * }
+ * try_always
+ * {
+ * ...optional code always executed when leaving this block scope...
+ * }
+ * try_end;
+ * \endcode
+ *
+ * Main usage should be test code and fatal error trapping. This is not safe
+ * and fast enough to be used for production code.
+ *
+ * When an exception is thrown, it is caught by each try block in order to
+ * clean up after itself.
+ */
+
+#include <setjmp.h>
+
+/** Pointer to the most recently set setjmp context. */
+extern jmp_buf *try_state_;
+
+/** Reserved catch codes. */
+enum try_code_t
+{
+ /** This is reserved. */
+ TRY_CODE_NONE,
+ /** Thrown for fatal error. */
+ TRY_CODE_FATAL,
+ /** Thrown for test failure. */
+ TRY_CODE_TEST_FAILURE,
+};
+
+/** Begin a try block. */
+#define try_begin try_begin_
+
+/** Define the catch block inside a try block. */
+#define try_catch(code) try_catch_(code)
+
+/** Define the always block inside a try block. */
+#define try_always try_always_
+
+/** End a try block. */
+#define try_end try_end_
+
+#define try_begin_ \
+{ \
+ int thrown_; \
+ bool caught_ = false; \
+ jmp_buf *old_try_state_ = try_state_; \
+ jmp_buf this_try_state_; \
+ try_state_ = &this_try_state_; \
+ /* ANSI says assigning setjmp return value is forbidden*/ \
+ /* this code is not portable... */ \
+ thrown_ = setjmp (*try_state_); \
+ if (thrown_ == 0) \
+ {
+
+#define try_catch_(code) \
+ } \
+ else \
+ { \
+ caught_ = thrown_ == (code); \
+ if (caught_) \
+ {
+
+#define try_always_ \
+ } \
+ } \
+ { \
+ {
+
+#define try_end_ \
+ } \
+ } \
+ try_state_ = old_try_state_; \
+ if (thrown_ != 0 && !caught_) \
+ { \
+ /* Jump again. */ \
+ dbg_assert_print (try_state_, "uncaught exception"); \
+ longjmp (*try_state_, thrown_); \
+ } \
+}
+
+/** Throw an exception code. */
+#define try_throw(code) try_throw_(code)
+
+#define try_throw_(code) \
+ do { \
+ longjmp (*try_state_, (code)); \
+ } while (0)
+
+#endif /* lib_try_h */
diff --git a/cesar/lib/types.h b/cesar/lib/types.h
new file mode 100644
index 0000000000..37eb80f5d8
--- /dev/null
+++ b/cesar/lib/types.h
@@ -0,0 +1,59 @@
+#ifndef lib_types_h
+#define lib_types_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/types.h
+ * \brief Common types header.
+ * \ingroup lib
+ *
+ * Define common types used almost everywhere.
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+
+#ifdef DOXYGEN_ONLY
+/** Boolean value. This C99 type comes from lib/stdbool.h. It can store true or
+ * false values. */
+typedef _Bool bool;
+#endif
+
+/** Pointer value to use when debuging where a pointer is known to be
+ * invalid. */
+#define INVALID_PTR ((void *) 0xDEADDEAD)
+
+/** Convenient shortcut for unsigned int. */
+typedef unsigned int uint;
+
+/**
+ * \name Fixed size types
+ * Theses types should only be used when a specific size is required, not as
+ * general purpose types. If the size does not matter, use an int or uint.
+ */
+/*@{*/
+typedef unsigned long long u64;
+typedef signed long long s64;
+typedef unsigned int u32;
+typedef signed int s32;
+typedef unsigned short u16;
+typedef signed short s16;
+typedef unsigned char u8;
+typedef signed char s8;
+/*@}*/
+
+/**
+ * MAC Address.
+ * Stored as little endian, i.e. the first MAC address byte is in the least
+ * significant bits.
+ *
+ * Ex: 11:22:33:44:55:66 => 0x0000665544332211ull
+ */
+typedef u64 mac_t;
+
+#endif /* lib_types_h */
diff --git a/cesar/lib/utils.h b/cesar/lib/utils.h
new file mode 100644
index 0000000000..cfee107585
--- /dev/null
+++ b/cesar/lib/utils.h
@@ -0,0 +1,258 @@
+#ifndef lib_utils_h
+#define lib_utils_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/utils.h
+ * \brief Common utilities header.
+ * \ingroup lib
+ *
+ * Define useful utilities used almost everywhere.
+ *
+ * Do not add or modify any macro unless you own the special skills needed to
+ * prevent the creation of a mass destruction weapon from a nice looking
+ * macro.
+ */
+#include "lib/preproc.h"
+
+/** Count the number of element of a table. */
+#define COUNT(table) (sizeof (table) / sizeof ((table)[0]))
+
+/** Count the number of element of a table which is a member of a structure. */
+#define COUNT_MEMBER(parent, table) (COUNT (((parent *) NULL)->table))
+
+/** Return true iff \p a is before \p b modulo 2^32. This is useful to compare two
+ * values of a overflowing counter. This only works iff \p a and \p b are
+ * distant no more than 2^31. */
+extern inline bool
+less_mod2p32 (u32 a, u32 b)
+{
+ return (s32) (a - b) < 0;
+}
+
+/** Return true iff \p a is before or equal to \p b modulo 2^32. This is
+ * useful to compare two values of a overflowing counter. This only works iff
+ * \p a and \p b are distant no more than 2^31. */
+extern inline bool
+lesseq_mod2p32 (u32 a, u32 b)
+{
+ return (s32) (a - b) <= 0;
+}
+
+/** Return true iff \p a is before \p b modulo 2^16. This is useful to compare two
+ * values of a overflowing counter. This only works iff \p a and \p b are
+ * distant no more than 2^15. */
+extern inline bool
+less_mod2p16 (u16 a, u16 b)
+{
+ return (s16) (a - b) < 0;
+}
+
+/** Return true iff \p a is before or equal to \p b modulo 2^16. This is
+ * useful to compare two values of a overflowing counter. This only works iff
+ * \p a and \p b are distant no more than 2^15. */
+extern inline bool
+lesseq_mod2p16 (u16 a, u16 b)
+{
+ return (s16) (a - b) <= 0;
+}
+
+/** Return the absolute value. */
+#define ABS(v) ({ typeof (v) _v = (v); _v > 0 ? _v : -_v; })
+
+/** Return the maximum value. */
+#define MAX(a, b) ({ typeof (a) _a = (a); typeof (b) _b = (b); \
+ _a > _b ? _a : _b; })
+
+/** Return the minimum value. */
+#define MIN(a, b) ({ typeof (a) _a = (a); typeof (b) _b = (b); \
+ _a < _b ? _a : _b; })
+
+/** Exchange two value. */
+#define XCH(a, b) do { \
+ typeof (b) _tmp = (a); \
+ (a) = (b); \
+ (b) = _tmp; \
+} while (0)
+
+/** Return a bit mask composed of a number of LSB ones.
+ * \param b number of one bits, 1 to 31
+ *
+ * - BITS_ONES (0) => error
+ * - BITS_ONES (1) => 0x00000001
+ * - BITS_ONES (15) => 0x00007fff
+ * - BITS_ONES (31) => 0xffffffff
+ */
+#define BITS_ONES(b) ((1u << ((b) - 1) << 1) - 1)
+
+/** Return a bit mask composed of a number of LSB ones, corresponding to the
+ * given bit field.
+ * \param f bit field define
+ *
+ * The bit field is a preprocessor symbol composed of MSB and LSB separated by
+ * a comma.
+ */
+#define BF_ONES(f) BF_ONES_ (f)
+#define BF_ONES_(m, l) BITS_ONES ((m) - (l) + 1)
+
+/** Return a bit mask composed of a number of shifted ones.
+ * \param b number of one bits, 1 to 31
+ * \param s shift, 0 to 30
+ *
+ * - BITS_MASK (0, 0) => error
+ * - BITS_MASK (1, 14) => 0x00004000
+ * - BITS_MASK (15, 7) => 0x003fff80
+ * - BITS_MASK (31, 0) => 0xffffffff
+ */
+#define BITS_MASK(b, s) (BITS_ONES (b) << (s))
+
+/** Return a bit mask composed of a number of shifted ones, corresponding to
+ * the given bit field.
+ * \param f bit field define
+ *
+ * \see BF_ONES.
+ */
+#define BF_MASK(f) BF_MASK_ (f)
+#define BF_MASK_(m, l) BITS_MASK ((m) - (l) + 1, (l))
+
+/** Return true if the given value is small enough to fit in the given bit
+ * field.
+ * \param f bit field define
+ * \param v value to check
+ *
+ * \see BF_ONES.
+ */
+#define BF_CHECK(f, v) BF_CHECK_ (f, (v))
+#define BF_CHECK_(m, l, v) !((v) & ~BF_ONES_ ((m), (l)))
+
+/** Shift the given value to OR it at the right position in the given bit
+ * field.
+ * \param f bit field define
+ * \param v value to shift
+ *
+ * The value is not masked, it should be masked or checked before.
+ * \see BF_ONES.
+ */
+#define BF_SHIFT(f, v) BF_SHIFT_ (f, (v))
+#define BF_SHIFT_(m, l, v) ((v) << (l))
+
+/** Extract the given bit field.
+ * \param f bit field define
+ * \param v value to extract from
+ *
+ * \see BF_ONES.
+ */
+#define BF_GET(f, v) BF_GET_ (f, (v))
+#define BF_GET_(m, l, v) ((v) << (31 - (m)) >> (31 - (m) + (l)))
+
+/** Pack different bit fields together.
+ * \param reg register name (prefix)
+ * \param fv pair of (field, value)
+ *
+ * Example:
+ * \code
+ * #define MYREG__A 7, 0
+ * #define MYREG__B 23, 12
+ * BF_FILL (MYREG, (A, 0x42), (B, 0x123)) => 0x00123042
+ * \endcode
+ */
+#define BF_FILL(reg, fv...) \
+ (0 PREPROC_FOR_EACH_PARAM (BF_FILL_FIELD_, reg ## __, fv))
+#define BF_FILL_FIELD_(reg, fv) \
+ BF_FILL_FIELD__ (reg, PREPROC_UNPACK (fv))
+#define BF_FILL_FIELD__(reg, fv) \
+ BF_FILL_FIELD___ (reg, fv)
+#define BF_FILL_FIELD___(reg, f, v) \
+ | BF_SHIFT (reg ## f, v)
+
+/** Return the number of one bits. */
+#define BITS_ONES_COUNT(x) ({ \
+ typeof (x) _x = (x); \
+ uint i, c = 0; \
+ for (i = sizeof (_x) * 8; i; i--) \
+ { \
+ if (_x & 1) \
+ c++; \
+ _x >>= 1; \
+ } \
+ c; \
+})
+
+/** Return the offset of the given \p member in the given \p parent struct. */
+#define OFFSET_OF(parent, member) ((uint) &((parent *) NULL)->member)
+
+/** When \p member is a member of \p parent struct and \p p a pointer to this
+ * member, return a pointer to the containing struct. */
+#define PARENT_OF(parent, member, p) \
+ ((parent *) ((u8 *) (p) - OFFSET_OF (parent, member)))
+
+/** Cast to the corresponding volatile type. */
+#define VOLATILE(v) ((volatile typeof (*(v)) *) (v))
+
+/** Stop the compiler to reorder instructions across this barrier. You may
+ * consider using volatile instead. */
+#define REORDER_BARRIER() __asm__ __volatile__ ("" : : : "memory")
+
+/** Reverse bitfields if needed to have the first field using the least
+ * significant bit. */
+#define BITFIELDS_WORD(args...) BITFIELDS_WORD_ (args)
+
+#define BITFIELDS_WORD_ECHO(x) x
+#if DEFS_REVERSE_BITFIELDS
+# define BITFIELDS_WORD_(args...) \
+ PREPROC_FOR_EACH (BITFIELDS_WORD_ECHO, PREPROC_REVERSE (args))
+#else
+# define BITFIELDS_WORD_(args...) \
+ PREPROC_FOR_EACH (BITFIELDS_WORD_ECHO, args)
+#endif
+
+/** Define a fixed point number from a double, with 32 bits precision. */
+#define CONST_UF32(d) ((u32) ((1ull << 32) * (d) + 0.5))
+
+/**
+ * Generic dichotomy search.
+ * \param min minimum index
+ * \param max maximum index (past the end)
+ * \param index index unsigned integer variable
+ * \param less comparison expression
+ *
+ * This will expand to a code block which make a dichotomy search in any
+ * indexable object.
+ *
+ * In the following example, the variable \c i gets the found index. It may
+ * index a value greater than the looked up value or be equal to max if all
+ * elements are smaller than the looked up element.
+ *
+ * \code
+ * extern int table[256];
+ * uint i;
+ * int looked_up;
+ * DICHOTOMY_SEARCH (0, COUNT (table), i, looked_up < table[i]);
+ * \endcode
+ */
+#define DICHOTOMY_SEARCH(min, max, index, less) \
+ do { \
+ uint a_, b_; \
+ a_ = (min); \
+ b_ = (max); \
+ while (a_ != b_) \
+ { \
+ index = (a_ + b_) / 2; \
+ if (less) \
+ { \
+ b_ = index; \
+ } \
+ else \
+ { \
+ a_ = index + 1; \
+ } \
+ } \
+ index = a_; \
+ } while (0)
+
+#endif /* lib_utils_h */
diff --git a/cesar/lib/visual_state_api/Module b/cesar/lib/visual_state_api/Module
new file mode 100644
index 0000000000..7645df89eb
--- /dev/null
+++ b/cesar/lib/visual_state_api/Module
@@ -0,0 +1,2 @@
+SOURCES := SEMExpl.c SEMExplA.c SEMForce.c SEMInq.c SEMInst.c SEMMach.c SEMMain.c SEMName.c SEMNameA.c SEMStAll.c SEMState.c SMPExpl.c SMPExplA.c SMPForce.c SMPInq.c SMPInst.c SMPMach.c SMPMain.c SMPName.c SMPNameA.c SMPStAll.c SMPState.c
+INCLUDES += lib/visual_state_api/src
diff --git a/cesar/lib/visual_state_api/src/SEMExpl.c b/cesar/lib/visual_state_api/src/SEMExpl.c
new file mode 100644
index 0000000000..054442b215
--- /dev/null
+++ b/cesar/lib/visual_state_api/src/SEMExpl.c
@@ -0,0 +1,27 @@
+/*
+ * Type: Source Code File
+ *
+ * Id: SEMExpl.c
+ *
+ * Function: Contains the SEM_Expl SEM Library Expert version 4 function.
+ *
+ * Portability: ANSI-C Compiler.
+ *
+ * Copyright (c) 1999-2006 IAR Systems. All rights reserved.
+ */
+
+/*
+ * Version ! Date ! Status ! Changes
+ *----------------------------------------------------------------------------
+ * 4.0.0.0 ! 011198 ! Closed ! -
+ * 4.0.4 ! 010799 ! Closed ! Minor update, there might be no changes to this particular file.
+ */
+
+#include "SEMLibE.h"
+
+
+unsigned char VS_CALL_CONV SEM_Expl (unsigned char IdentType,
+ SEM_EXPLANATION_TYPE IdentNo, char *Text, unsigned short MaxSize)
+{
+ return (SMP_Expl (SEMContext, IdentType, IdentNo, Text, MaxSize));
+}
diff --git a/cesar/lib/visual_state_api/src/SEMExplA.c b/cesar/lib/visual_state_api/src/SEMExplA.c
new file mode 100644
index 0000000000..ae7bed445e
--- /dev/null
+++ b/cesar/lib/visual_state_api/src/SEMExplA.c
@@ -0,0 +1,28 @@
+/*
+ * Type: Source Code File
+ *
+ * Id: SEMExplA.c
+ *
+ * Function: Contains the SEM_ExplAbs SEM Library Expert version 4
+ * function.
+ *
+ * Portability: ANSI-C Compiler.
+ *
+ * Copyright (c) 1999-2006 IAR Systems. All rights reserved.
+ */
+
+/*
+ * Version ! Date ! Status ! Changes
+ *----------------------------------------------------------------------------
+ * 4.0.0.0 ! 011198 ! Closed ! -
+ * 4.0.4 ! 010799 ! Closed ! Minor update, there might be no changes to this particular file.
+ */
+
+#include "SEMLibE.h"
+
+
+unsigned char VS_CALL_CONV SEM_ExplAbs (unsigned char IdentType,
+ SEM_EXPLANATION_TYPE IdentNo, char VS_TQ_RULEBASE **Text)
+{
+ return (SMP_ExplAbs (SEMContext, IdentType, IdentNo, Text));
+}
diff --git a/cesar/lib/visual_state_api/src/SEMForce.c b/cesar/lib/visual_state_api/src/SEMForce.c
new file mode 100644
index 0000000000..f3bce1add9
--- /dev/null
+++ b/cesar/lib/visual_state_api/src/SEMForce.c
@@ -0,0 +1,27 @@
+/*
+ * Type: Source Code File
+ *
+ * Id: SEMExpl.c
+ *
+ * Function: Contains the SEM_ForceState SEM Library Expert version 4
+ * function.
+ *
+ * Portability: ANSI-C Compiler.
+ *
+ * Copyright (c) 1999-2006 IAR Systems. All rights reserved.
+ */
+
+/*
+ * Version ! Date ! Status ! Changes
+ *----------------------------------------------------------------------------
+ * 4.0.0.0 ! 011198 ! Closed ! -
+ * 4.0.4 ! 010799 ! Closed ! Minor update, there might be no changes to this particular file.
+ */
+
+#include "SEMLibE.h"
+
+
+unsigned char VS_CALL_CONV SEM_ForceState (SEM_STATE_TYPE StateNo)
+{
+ return (SMP_ForceState (SEMContext, StateNo));
+}
diff --git a/cesar/lib/visual_state_api/src/SEMInq.c b/cesar/lib/visual_state_api/src/SEMInq.c
new file mode 100644
index 0000000000..203c998f80
--- /dev/null
+++ b/cesar/lib/visual_state_api/src/SEMInq.c
@@ -0,0 +1,45 @@
+/*
+ * Type: Source Code File
+ *
+ * Id: SEMInq.c
+ *
+ * Function: Contains the SEM_Inquiry, SEM_GetInput and SEM_GetInputAll
+ * SEM Library Expert version 4 function.
+ *
+ * Portability: ANSI-C Compiler.
+ *
+ * Copyright (c) 1999-2006 IAR Systems. All rights reserved.
+ */
+
+/*
+ * Version ! Date ! Status ! Changes
+ *----------------------------------------------------------------------------
+ * 4.0.0.0 ! 011198 ! Closed ! -
+ * 4.0.4 ! 010799 ! Closed ! Minor update, there might be no changes to this particular file.
+ */
+
+#include "SEMLibE.h"
+
+
+unsigned char VS_CALL_CONV SEM_Inquiry (void)
+{
+ return (SMP_Inquiry (SEMContext));
+}
+
+
+unsigned char VS_CALL_CONV SEM_GetInput (SEM_EVENT_TYPE *EventNo,
+ SEM_EVENT_TYPE *EventList)
+{
+ return (SMP_GetInput (SEMContext, EventNo, EventList));
+}
+
+
+
+#ifdef SEM_GET_INPUT_ALL
+unsigned char VS_CALL_CONV SEM_GetInputAll (SEM_EVENT_TYPE *EventVector,
+ SEM_EVENT_TYPE *EventList, SEM_EVENT_TYPE MaxSize)
+{
+ return (SMP_GetInputAll (SEMContext, EventVector, EventList, MaxSize));
+}
+#endif
+
diff --git a/cesar/lib/visual_state_api/src/SEMInst.c b/cesar/lib/visual_state_api/src/SEMInst.c
new file mode 100644
index 0000000000..ddd32600ba
--- /dev/null
+++ b/cesar/lib/visual_state_api/src/SEMInst.c
@@ -0,0 +1,33 @@
+/*
+ * Type: Source Code File
+ *
+ * Id: SEMInst.c
+ *
+ * Function: Contains the SEM_InitInstances and SEM_SetInstance
+ SEM Library Expert version 4 function.
+ *
+ * Portability: ANSI-C Compiler.
+ *
+ * Copyright (c) 1999-2006 IAR Systems. All rights reserved.
+ */
+
+/*
+ * Version ! Date ! Status ! Changes
+ *----------------------------------------------------------------------------
+ * 4.0.0.1 ! 021298 ! Closed ! -
+ * 4.0.4 ! 010799 ! Closed ! Minor update, there might be no changes to this particular file.
+ */
+
+#include "SEMLibE.h"
+
+
+unsigned char VS_CALL_CONV SEM_InitInstances (void)
+{
+ return (SMP_InitInstances (SEMContext));
+}
+
+
+unsigned char VS_CALL_CONV SEM_SetInstance (SEM_INSTANCE_TYPE Instance)
+{
+ return (SMP_SetInstance (SEMContext, Instance));
+}
diff --git a/cesar/lib/visual_state_api/src/SEMLibE.h b/cesar/lib/visual_state_api/src/SEMLibE.h
new file mode 100644
index 0000000000..6262d60aea
--- /dev/null
+++ b/cesar/lib/visual_state_api/src/SEMLibE.h
@@ -0,0 +1,1882 @@
+/*
+ * Type: Header File
+ *
+ * Id: SEMLibE.h
+ *
+ * Function: Header file for the SEM Library Expert version 4 definitions
+ * and function prototypes.
+ *
+ * Portability: ANSI-C Compiler.
+ *
+ * Copyright (c) 1999-2006 IAR Systems. All rights reserved.
+ */
+
+/*
+ * Version ! Date ! Status ! Changes
+ *----------------------------------------------------------------------------
+ * 4.0.0.9 ! 240299 ! Closed ! -
+ * 4.0.4 ! 010799 ! Closed ! Minor update, there might be no changes to this particular file.
+ */
+
+#ifndef __SEMLIBE_H
+#define __SEMLIBE_H
+
+
+#include <stddef.h>
+#include <stdlib.h>
+
+
+/* Include SEM Library Definition Header File. */
+#include "SEMEDef.h"
+
+
+#ifndef VS_CODER_GUID
+#error The generated files were generated by a visualSTATE Coder, which is not compliant with this version of the visualSTATE Expert API.
+#endif
+
+
+#ifdef VISUALSTATE_EXPERT_DLL
+#include "SEMEdll.h"
+#else
+#define VS_CALL_CONV
+#define VS_CONTEXT_TYPE SEMContext
+#endif
+
+
+#ifndef VS_TRUE
+#define VS_TRUE (1)
+#endif
+
+#ifndef VS_FALSE
+#define VS_FALSE (0)
+#endif
+
+
+#define SEM_VERS_ID 0X050
+
+
+#ifdef VS_RUNTIME_INFO
+typedef struct
+{
+ char pSignatureVersion[VS_SIGNATURE_VERSION_LENGTH];
+ char pSignatureContent[VS_SIGNATURE_CONTENT_LENGTH];
+} VSRunTimeInfo;
+#endif
+
+
+typedef struct
+{
+ unsigned long IdAndEventGroupType;
+ unsigned long nNofEvents;
+ unsigned long nNofSignals;
+ unsigned long nNofStates;
+ unsigned long nNofStateMachines;
+ unsigned long nNofActionFunctions;
+ unsigned long nNofInstances;
+ unsigned long SSize;
+ unsigned long SMIPos;
+ unsigned long EGTPos;
+ unsigned long EGTIPos;
+ unsigned long RDPos;
+ unsigned long RIPos;
+ unsigned long RTIPos;
+ unsigned long TSPos;
+ unsigned long ENIPos;
+ unsigned long SNIPos;
+ unsigned long ANIPos;
+ unsigned long EEIPos;
+ unsigned long SEIPos;
+ unsigned long AEIPos;
+ unsigned long contextPtrOffset;
+} RBH;
+
+
+extern SEM_CONTEXT *SEMContext;
+extern unsigned char SEMInitCC;
+
+
+enum
+{
+ /*
+ * Status code 0: SES_OKAY.
+ *
+ * Explanation: Function performed successfully.
+ *
+ * Solution: None.
+ */
+ SES_OKAY, /* 0 */
+
+
+ /*
+ * Status code: SES_FOUND.
+ *
+ * Explanation: The called function has returned an identifier index
+ * number.
+ *
+ * Solution: Process the returned identifier index number. If the
+ * function SEM_GetInput/SMP_GetInput or SEM_GetOutput/
+ * SMP_GetOutput was called, the function can be called
+ * again to find more events or action expressions.
+ */
+ SES_FOUND, /* 1 */
+
+
+ /*
+ * Status code: SES_ACTIVE.
+ *
+ * Explanation: The completion code has one of the two expositions:
+ * 1) A state/event deduction is started, while an event
+ * inquiry is active. All inquired events have not been
+ * returned by the function SEM_GetInput/SMP_GetInput.
+ * 2) An event inquiry is started, while a state/event
+ * deduction is active. All deduced action expressions
+ * have not been returned by the function SEM_GetOutput/
+ * SMP_GetOutput and the SEM_NextState/SMP_NextState has
+ * not been called to finish the state/event deduction.
+ *
+ * Solution: The completion code is a warning and perhaps the
+ * application program should be rewritten. An event inquiry
+ * and a state/event deduction should not be active at the
+ * same time.
+ */
+ SES_ACTIVE, /* 2 */
+
+
+ /*
+ * Error code: SES_CONTRADICTION.
+ *
+ * Explanation: A contradiction has been detected between two states in a
+ * state machine.
+ *
+ * Solution: Check the VS System.
+ */
+ SES_CONTRADICTION, /* 3 */
+
+
+ /*
+ * Error code: SES_RANGE_ERR.
+ *
+ * Explanation: You are making a reference to an identifier that does not
+ * exist. Note that the first index number is 0. If the rule
+ * base has 4 identifier of the same type and you use a
+ * function with the variable parameter = 4, the function
+ * will return with a SES_RANGE_ERR error. In this case the
+ * highest variable index number is 3.
+ *
+ * Solution: The application program may check the index parameters
+ * with one of the following variables in the SEM_Context
+ * struct:
+ *
+ * nNofEvents
+ * nNofStates
+ * nNofActionFunctions
+ * nNofStateMachines
+ */
+ SES_RANGE_ERR, /* 4 */
+
+
+ /*
+ * Error code: SES_TEXT_TOO_LONG.
+ *
+ * Explanation: The requested text is longer than the specified maximum
+ * length.
+ *
+ * Solution: Increase the maximum length.
+ */
+ SES_TEXT_TOO_LONG, /* 5 */
+
+
+ /*
+ * Error code: SES_TYPE_ERR.
+ *
+ * Explanation: A text function has been called with the wrong identifier
+ * type or the specified text is not included in the VS
+ * System source file.
+ *
+ * Solution: Use the indentifier type symbols (EVENT_TYPE, STATE_TYPE
+ * or ACTION_TYPE) defined in the SEMlibE.h file and remember
+ * to include wanted text in the VS System.
+ */
+ SES_TYPE_ERR, /* 6 */
+
+
+ /*
+ * Error code: SES_EMPTY.
+ *
+ * Explanation: No events has been given to the SEM_Deduct/SMP_Deduct
+ * function before calling this function.
+ *
+ * Solution: Call the SEM_Deduct/SMP_Deduct function with an event
+ * number.
+ */
+ SES_EMPTY, /* 7 */
+
+
+ /*
+ * Error code: SES_BUFFER_OVERFLOW.
+ *
+ * Explanation: A destination buffer cannot hold the number of items
+ * found.
+ *
+ * Solution: Call the function with an extended buffer as destination.
+ */
+ SES_BUFFER_OVERFLOW, /* 8 */
+
+
+ /*
+ * Error code: SES_SIGNAL_QUEUE_FULL.
+ *
+ * Explanation: Signal queue is full.
+ *
+ * Solution: Increase the maximum signal queue size in the VS System or
+ * via the VS Coder signal queue size option.
+ */
+ SES_SIGNAL_QUEUE_FULL, /* 9 */
+
+
+ /*
+ * Status code: SES_VERS_ERR
+ *
+ * Explanation: Incompatible version of VS System attempted loaded.
+ *
+ * Solution: Recompile the VS System.
+ */
+ SES_VERS_ERR = 16, /* 16 */
+
+
+ /*
+ * Status code: SES_FILE_ERR
+ *
+ * Explanation: Error while accessing VS System file.
+ *
+ * Solution: 1) Check file name.
+ * 2) Regenerate VS System.
+ */
+ SES_FILE_ERR, /* 17 */
+
+
+ /*
+ * Status code: SES_MEM_ERR
+ *
+ * Explanation: Error while allocating memory for VS System.
+ *
+ * Solution: 1) Free some memory in your computer.
+ * 2) On PCs, use a large-data memory model.
+ */
+ SES_MEM_ERR, /* 18 */
+
+
+ /*
+ * Status code: SES_NOT_LOADED
+ *
+ * Explanation: No VS System is loaded.
+ *
+ * Solution: Load a VS System before calling the function.
+ */
+ SES_NOT_LOADED, /* 19 */
+
+
+ /*
+ * Status code: SES_NOT_COMPATIBLE
+ *
+ * Explanation: Function is not compatible with current setup.
+ *
+ * Solution: Use an other function.
+ */
+ SES_NOT_COMPATIBLE, /* 20 */
+
+
+ /*
+ * Status code: SES_TYPE_OVERFLOW
+ *
+ * Explanation: The number of instances * state machines exceeds
+ * the range for an unsigned long.
+ *
+ * Solution: Reduce the number of instances or state machines.
+ */
+ SES_TYPE_OVERFLOW /* 21 */
+};
+
+
+/* Identifier types, used when getting texts and explanations. */
+enum {EVENT_TYPE, STATE_TYPE, ACTION_TYPE};
+
+
+/*
+ * Used internal in SMPMain.c
+ */
+#define STATE_SEM_INITIALIZE 0x00
+#define STATE_SEM_SIGNAL 0x01
+#define STATE_SEM_PREPARE 0x02
+#define STATE_SEM_CONSULT 0x03
+#define STATE_SEM_OUTPUT 0x04
+#define STATE_SEM_OKAY 0x05
+
+// added by GL 29/10/2007
+#define SEM_FUNC_OLD_NAMING_STYLE 0
+/*
+ * State/event naming style.
+ */
+#if (SEM_FUNC_OLD_NAMING_STYLE)
+#define SEM_Load sem_load
+#define SEM_Connect sem_connect
+#define SEM_Free sem_free
+#define SEM_Init sem_init
+#define SEM_InitGuardCallBack sem_init_guard_call_back
+#define SEM_InitSignalDBCallBack sem_init_signal_d_b_call_back
+#define SEM_InitSignalQueue sem_init_signal_queue
+#define SEM_InitInstances sem_init_instances
+#define SEM_SetInstance sem_set_instance
+#define SEM_Deduct sem_deduct
+#define SEM_GetOutput sem_get_output
+#define SEM_GetOutputAll sem_get_output_all
+#define SEM_NextState sem_next_state
+#define SEM_NextStateChg sem_next_state_chg
+#define SEM_Inquiry sem_inquiry
+#define SEM_GetInput sem_get_input
+#define SEM_GetInputAll sem_get_input_all
+#define SEM_Name sem_name
+#define SEM_NameAbs sem_name_abs
+#define SEM_Expl sem_expl
+#define SEM_ExplAbs sem_expl_abs
+#define SEM_State sem_state
+#define SEM_StateAll sem_state_all
+#define SEM_Machine sem_machine
+#define SEM_ForceState sem_force_state
+
+#define SMP_Connect smp_connect
+#define SMP_Load smp_load
+#define SMP_Free smp_free
+#define SMP_Init smp_init
+#define SMP_InitGuardCallBack smp_init_guard_call_back
+#define SMP_InitSignalDBCallBack smp_init_signal_d_b_call_back
+#define SMP_InitSignalQueue smp_init_signal_queue
+#define SMP_InitInstances smp_init_instances
+#define SMP_SetInstance smp_set_instance
+#define SMP_Deduct smp_deduct
+#define SMP_GetOutput smp_get_output
+#define SMP_GetOutputAll smp_get_output_all
+#define SMP_NextState smp_next_state
+#define SMP_NextStateChg smp_next_state_chg
+#define SMP_Inquiry smp_inquiry
+#define SMP_GetInput smp_get_input
+#define SMP_GetInputAll smp_get_input_all
+#define SMP_Name smp_name
+#define SMP_NameAbs smp_name_abs
+#define SMP_Expl smp_expl
+#define SMP_ExplAbs smp_expl_abs
+#define SMP_State smp_state
+#define SMP_StateAll smp_state_all
+#define SMP_Machine smp_machine
+#define SMP_ForceState smp_force_state
+#endif
+
+
+/*
+ * Name : SEM_Load
+ *
+ * Description : Calls SMP_Load.
+ *
+ * Argument : See 'argument' section for SMP_Load.
+ *
+ * Return : See 'return' section for SMP_Load.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char VS_CALL_CONV SEM_Load (const char *FileName);
+
+
+/*
+ * Name : SEM_Connect
+ *
+ * Description : Calls SMP_Connect.
+ *
+ * Argument : See 'argument' section for SMP_Connect.
+ *
+ * Return : See 'return' section for SMP_Connect.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char SEM_Connect (void VS_TQ_RULEBASE *VSData);
+
+
+/*
+ * Name : SEM_Free
+ *
+ * Description : Calls SMP_Free.
+ *
+ * Argument : See 'argument' section for SMP_Free.
+ *
+ * Return : See 'return' section for SMP_Free.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern void VS_CALL_CONV SEM_Free (void);
+
+
+/*
+ * Name : SEM_Init
+ *
+ * Description : Calls SMP_Init.
+ *
+ * Argument : See 'argument' section for SMP_Init.
+ *
+ * Return : See 'return' section for SMP_Init.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern void VS_CALL_CONV SEM_Init (void);
+
+
+/*
+ * Name : SEM_InitGuardCallBack
+ *
+ * Description : Calls SEM_InitGuardCallBack.
+ *
+ * Argument : See 'argument' section for SEM_InitGuardCallBack.
+ *
+ * Return : See 'return' section for SEM_InitGuardCallBack.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+#if (SEM_GUARD_EXPRESSION)
+#if (SEM_FUNCEXPHANDLING == 0)
+void SEM_InitGuardCallBack (VS_GUARDEXPR_TYPE VS_TQ_GUARDEXPRCOL * Guard);
+#else
+void SEM_InitGuardCallBack (unsigned char (*Guard)(struct SEM_CONTEXT VS_TQ_CONTEXT *Context, SEM_GUARD_EXPRESSION_TYPE i));
+#endif
+#endif
+
+
+/*
+ * Name : SEM_InitSignalDBCallBack
+ *
+ * Description : Calls SEM_InitSignalDBCallBack.
+ *
+ * Argument : See 'argument' section for SEM_InitSignalDBCallBack.
+ *
+ * Return : See 'return' section for SEM_InitSignalDBCallBack.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+#if (SEM_SIGNAL_DB)
+void SEM_InitSignalDBCallBack (void (*SEM_SignalDB)(SEM_CONTEXT VS_TQ_CONTEXT *Context, SEM_EVENT_TYPE SignalNo));
+#endif
+
+
+/*
+ * Name : SEM_InitSignalQueue
+ *
+ * Description : Calls SMP_InitSignalQueue.
+ *
+ * Argument : See 'argument' section for SMP_InitSignalQueue.
+ *
+ * Return : See 'return' section for SMP_InitSignalQueue.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+#if (SEM_SIGNAL)
+extern void VS_CALL_CONV SEM_InitSignalQueue (void);
+#endif
+
+
+/*
+ * Name : SEM_InitInstances
+ *
+ * Description : Calls SMP_InitInstances.
+ *
+ * Argument : See 'argument' section for SMP_InitInstances.
+ *
+ * Return : See 'return' section for SMP_InitInstances.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char VS_CALL_CONV SEM_InitInstances (void);
+
+
+/*
+ * Name : SEM_SetInstance
+ *
+ * Description : Calls SMP_SetInstance.
+ *
+ * Argument : See 'argument' section for SMP_SetInstance.
+ *
+ * Return : See 'return' section for SMP_SetInstance.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char VS_CALL_CONV SEM_SetInstance (SEM_INSTANCE_TYPE Instance);
+
+
+/*
+ * Name : SEM_Deduct
+ *
+ * Description : Calls SMP_Deduct.
+ *
+ * Argument : See 'argument' section for SMP_Deduct.
+ *
+ * Return : See 'return' section for SMP_Deduct.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char VS_CALL_CONV SEM_Deduct (SEM_EVENT_TYPE EventNo);
+
+
+/*
+ * Name : SEM_GetOutput
+ *
+ * Description : Calls SMP_GetOutput.
+ *
+ * Argument : See 'argument' section for SMP_GetOutput.
+ *
+ * Return : See 'return' section for SMP_GetOutput.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char VS_CALL_CONV SEM_GetOutput (SEM_ACTION_EXPRESSION_TYPE *ActionNo);
+
+
+/*
+ * Name : SEM_GetOutputAll
+ *
+ * Description : Calls SMP_GetOutputAll.
+ *
+ * Argument : See 'argument' section for SMP_GetOutputAll.
+ *
+ * Return : See 'return' section for SMP_GetOutputAll.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char VS_CALL_CONV SEM_GetOutputAll (
+ SEM_ACTION_EXPRESSION_TYPE *ActionExprVector,
+ SEM_ACTION_EXPRESSION_TYPE MaxSize);
+
+
+/*
+ * Name : SEM_NextState
+ *
+ * Description : Calls SMP_NextState.
+ *
+ * Argument : See 'argument' section for SMP_NextState.
+ *
+ * Return : See 'return' section for SMP_NextState.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+#if !defined SEM_NEXT_STATE_CHG || defined VISUALSTATE_EXPERT_DLL
+extern unsigned char VS_CALL_CONV SEM_NextState (void);
+#endif
+
+
+/*
+ * Name : SEM_NextStateChg
+ *
+ * Description : Calls SMP_NextStateChg.
+ *
+ * Argument : See 'argument' section for SMP_NextStateChg.
+ *
+ * Return : See 'return' section for SMP_NextStateChg.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+#if defined SEM_NEXT_STATE_CHG || defined VISUALSTATE_EXPERT_DLL
+extern unsigned char VS_CALL_CONV SEM_NextStateChg (void);
+#endif
+
+
+/*
+ * Name : SEM_Inquiry
+ *
+ * Description : Calls SMP_Inquiry.
+ *
+ * Argument : See 'argument' section for SMP_Inquiry.
+ *
+ * Return : See 'return' section for SMP_Inquiry.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char VS_CALL_CONV SEM_Inquiry (void);
+
+
+/*
+ * Name : SEM_GetInput
+ *
+ * Description : Calls SMP_GetInput.
+ *
+ * Argument : See 'argument' section for SMP_GetInput.
+ *
+ * Return : See 'return' section for SMP_GetInput.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char VS_CALL_CONV SEM_GetInput (SEM_EVENT_TYPE *EventNo,
+ SEM_EVENT_TYPE *EventList);
+
+
+/*
+ * Name : SEM_GetInputAll
+ *
+ * Description : Calls SMP_GetInputAll.
+ *
+ * Argument : See 'argument' section for SMP_GetInputAll.
+ *
+ * Return : See 'return' section for SMP_GetInputAll.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char VS_CALL_CONV SEM_GetInputAll (SEM_EVENT_TYPE *EventVector,
+ SEM_EVENT_TYPE *EventList, SEM_EVENT_TYPE MaxSize);
+
+
+/*
+ * Name : SEM_Name
+ *
+ * Description : Calls SMP_Name.
+ *
+ * Argument : See 'argument' section for SMP_Name.
+ *
+ * Return : See 'return' section for SMP_Name.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char VS_CALL_CONV SEM_Name (unsigned char IdentType,
+ SEM_EXPLANATION_TYPE IdentNo, char *Text, unsigned short MaxSize);
+
+
+/*
+ * Name : SEM_NameAbs
+ *
+ * Description : Calls SMP_NameAbs.
+ *
+ * Argument : See 'argument' section for SMP_NameAbs.
+ *
+ * Return : See 'return' section for SMP_NameAbs.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char VS_CALL_CONV SEM_NameAbs (unsigned char IdentType,
+ SEM_EXPLANATION_TYPE IdentNo, char VS_TQ_RULEBASE **Text);
+
+
+/*
+ * Name : SEM_Expl
+ *
+ * Description : Calls SMP_Expl.
+ *
+ * Argument : See 'argument' section for SMP_Expl.
+ *
+ * Return : See 'return' section for SMP_Expl.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char VS_CALL_CONV SEM_Expl (unsigned char IdentType,
+ SEM_EXPLANATION_TYPE IdentNo, char *Text, unsigned short MaxSize);
+
+
+/*
+ * Name : SEM_ExplAbs
+ *
+ * Description : Calls SMP_ExplAbs.
+ *
+ * Argument : See 'argument' section for SMP_ExplAbs.
+ *
+ * Return : See 'return' section for SMP_ExplAbs
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char VS_CALL_CONV SEM_ExplAbs (unsigned char IdentType,
+ SEM_EXPLANATION_TYPE IdentNo, char VS_TQ_RULEBASE **Text);
+
+
+/*
+ * Name : SEM_State
+ *
+ * Description : Calls SMP_State.
+ *
+ * Argument : See 'argument' section for SMP_State.
+ *
+ * Return : See 'return' section for SMP_State.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char VS_CALL_CONV SEM_State (SEM_STATE_MACHINE_TYPE StateMachineNo,
+ SEM_STATE_TYPE *StateNo);
+
+
+/*
+ * Name : SEM_StateAll
+ *
+ * Description : Calls SMP_StateAll.
+ *
+ * Argument : See 'argument' section for SMP_StateAll.
+ *
+ * Return : See 'return' section for SMP_StateAll.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char VS_CALL_CONV SEM_StateAll (SEM_STATE_TYPE *StateVector,
+ SEM_STATE_MACHINE_TYPE MaxSize);
+
+
+/*
+ * Name : SEM_Machine
+ *
+ * Description : Calls SMP_Machine.
+ *
+ * Argument : See 'argument' section for SMP_Machine.
+ *
+ * Return : See 'return' section for SMP_Machine.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char VS_CALL_CONV SEM_Machine (SEM_STATE_TYPE StateNo,
+ SEM_STATE_MACHINE_TYPE *StateMachineNo);
+
+
+/*
+ * Name : SEM_ForceState
+ *
+ * Description : Calls SMP_ForceState.
+ *
+ * Argument : See 'argument' section for SMP_ForceState.
+ *
+ * Return : See 'return' section for SMP_ForceState.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char VS_CALL_CONV SEM_ForceState (SEM_STATE_TYPE StateNo);
+
+
+/*
+ * Name : SEM_Action
+ *
+ * Description : The macro will call an action function by using the
+ * VSAction function pointer table.
+ *
+ * Argument : ActionNo:
+ * Action index number.
+ *
+ * Return : None.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+#if (SEM_FUNC_OLD_NAMING_STYLE)
+#define sem_action(ActionNo) (*VSAction[ActionNo])(VS_CONTEXT_TYPE)
+#else
+#define SEM_Action(ActionNo) (*VSAction[ActionNo])(VS_CONTEXT_TYPE)
+#endif
+
+
+/*
+ * Name : SEM_TableAction
+ *
+ * Description : The macro will call an action function by using the
+ * specified function pointer table.
+ *
+ * Argument : Table:
+ * Function pointer table.
+ *
+ * ActionNo:
+ * Action index number.
+ *
+ * Context (not in DLL):
+ * A pointer to a VS system context.
+ *
+ * Return : None.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+#if (SEM_FUNC_OLD_NAMING_STYLE)
+#define sem_table_action(Table, ActionNo) (* (Table)[ActionNo])(VS_CONTEXT_TYPE)
+#else
+#define SEM_TableAction(Table, ActionNo) (* (Table)[ActionNo])(VS_CONTEXT_TYPE)
+#endif
+
+
+/*
+ * Name : SMP_Connect
+ *
+ * Description : This function connects to a binary VS System already
+ * residing in memory.
+ *
+ * Argument : Context:
+ * A pointer pointer to a VS System context.
+ *
+ * VSData:
+ * A pointer to the memory area where the VS System
+ * resides.
+ * The VS System area must be an image of the binary
+ * VS System file including texts.
+ *
+ * Return : Completion code:
+ *
+ * SES_FILE_ERR:
+ * VS System file version error.
+ *
+ * SES_MEM_ERR:
+ * There is not enough heap memory.
+ *
+ * SES_NOT_LOADED:
+ * No VS System loaded or connected.
+ *
+ * SES_OKAY:
+ * Success.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char SMP_Connect(SEM_CONTEXT **Context, void VS_TQ_RULEBASE *VSDdata);
+
+
+/*
+ * Name : SMP_Load
+ *
+ * Description : This function loads a binary VS System from a file.
+ * A new context is allocated, the VS System is loaded and
+ * the context is initialized.
+ * Futhermore SMP_Init is called. SMP_InitSignalQueue is also
+ * called if the VS System has signals.
+ * Texts are not loaded into memory.
+ *
+ * Argument : Context:
+ * A pointer pointer to a VS System context.
+ *
+ * FileName:
+ * A pointer to the character string containing the name of
+ * the VS System file to be loaded.
+ *
+ * Return : Completion code:
+ *
+ * SES_FILE_ERR:
+ * VS System file version error.
+ *
+ * SES_MEM_ERR:
+ * There is not enough heap memory.
+ *
+ * SES_OKAY:
+ * Success.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char SMP_Load (SEM_CONTEXT **Context, const char *FileName);
+
+
+/*
+ * Name : SMP_Free
+ *
+ * Description : This function frees the memory allocated by a previous
+ * call to SMP_Load or SMP_Connect. If the VS System was
+ * loaded from disk, the corresponding heap memory is
+ * deallocated.
+ * If context is not equal to NULL, SMP_Free will free the
+ * memory allocated by the VS System and the context.
+ * If the VS System was loaded from disk, the VS System file
+ * is closed.
+ * If context is NULL, nothing is done.
+ *
+ * Argument : Context:
+ * A pointer to a VS System context.
+ *
+ * Return : None.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern void SMP_Free (SEM_CONTEXT VS_TQ_CONTEXT *Context);
+
+
+/*
+ * Name : SMP_Init
+ *
+ * Description : This function (re)initializes the VS System.
+ * Before calling any of the following SEM functions, this
+ * function can be called to initialize the state/event
+ * system.
+ * Both SMP_Load and SMP_Connect implicitly calls SMP_Init
+ * and SMP_InitSignalQueue, thus no call should be
+ * neccessary except if reinitialization is needed.
+ *
+ * Argument : Context:
+ * A pointer to a VS System context.
+ *
+ * Return : Completion code:
+ *
+ * SES_NOT_LOADED:
+ * No VS System loaded or connected.
+ *
+ * SES_OKAY:
+ * Success.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char SMP_Init (SEM_CONTEXT VS_TQ_CONTEXT *Context);
+
+
+/*
+ * Name : SMP_InitGuardCallBack
+ *
+ * Description : This function initializes the guard expression call back
+ * function.
+ * This function should be called after the
+ * SMP_Load/SMP_Connect function if the VS System contains
+ * guard expressions.
+ *
+ * Argument : Context:
+ * A pointer to a VS System context.
+ *
+ * Guard:
+ * If function pointer tables are not used:
+ * A pointer pointer to the VS System guard function
+ * else
+ * A pointer pointer to the VS System guard expression
+ * function pointer table.
+ *
+ * Return : None.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+#if (SEM_GUARD_EXPRESSION)
+#if (SEM_FUNCEXPHANDLING == 0)
+extern void SMP_InitGuardCallBack (SEM_CONTEXT VS_TQ_CONTEXT *Context, VS_GUARDEXPR_TYPE VS_TQ_GUARDEXPRCOL * Guard);
+#else
+extern void SMP_InitGuardCallBack (SEM_CONTEXT VS_TQ_CONTEXT *Context, unsigned char (* Guard)(SEM_CONTEXT VS_TQ_CONTEXT *Context, SEM_GUARD_EXPRESSION_TYPE i));
+#endif
+#endif
+
+
+/*
+ * Name : SMP_InitSignalDBCallBack
+ *
+ * Description : This function initializes the signal double buffer call
+ * back function.
+ * This function should be called after the
+ * SMP_Load/SMP_Connect function if the VS System used
+ * double buffering for any signals.
+ *
+ * Argument : Context:
+ * A pointer to a VS System context.
+ *
+ * SEM_SignalDB:
+ * A pointer to the VS System signal double buffer function
+ * pointer table.
+ *
+ * Return : None.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+#if (SEM_SIGNAL_DB)
+extern void SMP_InitSignalDBCallBack (SEM_CONTEXT VS_TQ_CONTEXT *Context,
+ void (*SEM_SignalDB)(SEM_CONTEXT VS_TQ_CONTEXT *Context, SEM_EVENT_TYPE SignalNo));
+#endif
+
+
+/*
+ * Name : SMP_InitSignalQueue
+ *
+ * Description : This function (re)initialize the signal queue in a
+ * VS System. This function must be called together with
+ * the SMP_Init function.
+ * Both SMP_Load and SMP_Connect implicitly calls SMP_Init
+ * and SMP_InitSignalQueue, thus no call should be
+ * neccessary except if reinitialization is needed.
+ * The function will only be avaliable if the signal queue
+ * is enable.
+ *
+ * Argument : Context:
+ * A pointer to a VS System context.
+ *
+ * Return : None.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+#if (SEM_SIGNAL)
+extern void SMP_InitSignalQueue (SEM_CONTEXT VS_TQ_CONTEXT *Context);
+#endif
+
+
+/*
+ * Name : SMP_InitInstances
+ *
+ * Description : Initialize a set of instances of the VS System.
+ * The function is used for initializing a number of
+ * instances of the VS System.
+ * If the function has already been called, previous
+ * instances are deallocated and a new set is allocated.
+ *
+ * Argument : Context:
+ * A pointer to a VS System context.
+ *
+ * Return : Completion code:
+ *
+ * SES_NOT_LOADED:
+ * No VS System loaded or connected.
+ *
+ * SES_MEM_ERR:
+ * There is not enough heap memory.
+ *
+ * SES_OKAY:
+ * Success.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char SMP_InitInstances (SEM_CONTEXT VS_TQ_CONTEXT *Context);
+
+
+/*
+ * Name : SMP_SetInstance
+ *
+ * Description : The function is used for setting up the instances of
+ * the VS System. The instance will be active until
+ * another call of the function.
+ *
+ * Argument : Context:
+ * A pointer to a VS System context.
+ *
+ * Instances:
+ * The number of VS System instances to be initialized.
+ *
+ * Return : Completion code:
+ *
+ * SES_ACTIVE:
+ * The function was attempted executed while a deduct or
+ * inquiry session was active. The function is not
+ * executed.
+ *
+ * SES_NOT_LOADED:
+ * No VS System loaded or connected.
+ *
+ * SES_RANGE_ERR:
+ * The index number of the VS System instance is
+ * invalid.
+ *
+ * SES_OKAY:
+ * Success.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char SMP_SetInstance (SEM_CONTEXT VS_TQ_CONTEXT *Context,
+ SEM_INSTANCE_TYPE Instance);
+
+
+/*
+ * Name : SMP_Deduct
+ *
+ * Description : The function prepares the reception of action expressions,
+ * that can be deduced on basis of the given event, the
+ * internal current state vector and the rules in the
+ * VS System.
+ * All action expressions are deduced by continously calling
+ * the function SMP_GetOutput or by one call to
+ * SMP_GetOutputAll.
+ * Before calling the SMP_Deduct function again, the
+ * SMP_NextState or SMP_NextStateChg should be called to
+ * enter the new states, if any.
+ *
+ * Argument : Context:
+ * A pointer to a VS System context.
+ *
+ * EventNo:
+ * Event number to be processed.
+ *
+ * Return : Completion code:
+ *
+ * SES_ACTIVE:
+ * The function SMP_Inquiry has been called. All inquired
+ * events have not been returned by the function
+ * SMP_GetInput or SMP_GetInputAll.
+ * The deduction is okay, but the user should not call the
+ * function SMP_GetInput before the functions
+ * SMP_NextState or SMP_NextStateChg and SMP_Inquiry have
+ * been called.
+ *
+ * SES_NOT_LOADED:
+ * No VS System loaded or connected.
+ *
+ * SES_RANGE_ERR:
+ * Event is out of range.
+ *
+ * SES_OKAY:
+ * Success.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char SMP_Deduct (SEM_CONTEXT VS_TQ_CONTEXT *Context,
+ SEM_EVENT_TYPE EventNo);
+
+
+
+/*
+ * Name : SMP_GetOutput
+ *
+ * Description : The function finds an action expressions, if any has been
+ * deduced on basis of the event given to the function
+ * SMP_Deduct, the internal current state vector and the
+ * rules in the VS System.
+ * All action expressions are found by continuous calls to
+ * the SMP_GetOutput function. When the SMP_GetOutput returns
+ * the completion code SES_OKAY all action expressions have
+ * been found.
+ * Use the SMP_Action or SMP_TableAction macros to call the
+ * action expressions.
+ *
+ * Argument : Context:
+ * A pointer to a VS System context.
+ *
+ * ActionNo:
+ * Pointer to store the deduced action expression.
+ *
+ * Return : Completion code:
+ *
+ * SES_CONTRADICTION:
+ * Contradiction detected, the VS System is not consistent.
+ * Check the VS System.
+ *
+ * SES_EMPTY:
+ * No event has been given to the SMP_Deduct function, i.e.
+ * SMP_Deduct has not been called before calling the
+ * SMP_GetOutput function.
+ *
+ * SES_FOUND:
+ * An action expression has been found. The user can
+ * continue to call the SMP_GetOutput, more action
+ * expressions may be found.
+ *
+ * SES_NOT_LOADED:
+ * No VS System loaded or connected.
+ *
+ * SES_OKAY:
+ * All action expressions have been found.
+ * The user can now call the SMP_NextState or
+ * SMP_NextStateChg function to change state.
+ * If SMP_deduct is called with the same event and
+ * SMP_NextState and SMP_NextStateChg is not called, all
+ * action expressions can be found again by calling
+ * SMP_GetOutput.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char SMP_GetOutput (SEM_CONTEXT VS_TQ_CONTEXT *Context,
+ SEM_ACTION_EXPRESSION_TYPE *ActionNo);
+
+
+/*
+ * Name : SMP_GetOutputAll
+ *
+ * Description : The function finds all action expression, if any has been
+ * deduced on basis of the event given to the function
+ * SMP_Deduct, the internal current state vector and the
+ * rules in the VS System.
+ * All action expressions are found by one call to the
+ * SMP_GetOutputAll function.
+ * SMP_GetOutputAll returns the completion code SES_OKAY if
+ * all action expression have succesfully been found.
+ * Defining the symbol SEM_GET_OUTPUT_ALL for your
+ * preprocessor/compiler will enable this function.
+ *
+ * Argument : Context:
+ * A pointer to a VS System context.
+ *
+ * ActionExprVector:
+ * A pointer to array to store the deduced outputs.
+ *
+ * MaxSize:
+ * Specifies the maximum length of the output vector
+ * including the symbol ACTION_EXPRESSION_TERMINATION_ID.
+ *
+ * Return : Completion code:
+ *
+ * SES_BUFFER_OVERFLOW:
+ * The specified MaxSize is too small. The action
+ * expressions vector array is not valid.
+ *
+ * SES_CONTRADICTION:
+ * Contradiction detected, the VS System is not
+ * consistent. Check the VS System.
+ *
+ * SES_EMPTY:
+ * No event has been given to the SMP_Deduct function,
+ * i.e. SMP_Deduct has not been called before calling the
+ * SMP_GetOutputAll function.
+ *
+ * SES_NOT_LOADED:
+ * No VS System loaded or connected.
+ *
+ * SES_OKAY:
+ * All action expressions have been found.
+ * The user can now call the SMP_NextState or
+ * SMP_NextStateChg function to change state.
+ * If SMP_Deduct is called with the same event and
+ * SMP_NextState or SMP_NextStateChg is not called, all
+ * action expressions can be found again by calling
+ * SMP_GetOutpuAll.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char SMP_GetOutputAll (SEM_CONTEXT VS_TQ_CONTEXT *Context,
+ SEM_ACTION_EXPRESSION_TYPE *ActionExprVector,
+ SEM_ACTION_EXPRESSION_TYPE MaxSize);
+
+
+#if defined SEM_NEXT_STATE_CHG || defined VISUALSTATE_EXPERT_DLL
+
+extern unsigned char _SMP_NextStateChg(SEM_CONTEXT VS_TQ_CONTEXT *Context, unsigned char nextStateChg);
+
+#else
+
+extern unsigned char _SMP_NextStateChg(SEM_CONTEXT VS_TQ_CONTEXT *Context);
+
+#endif
+
+
+/*
+ * Name : SMP_NextState
+ *
+ * Description : The function will update the intern current state vector,
+ * if any states can be found on basis of the event given to
+ * the function SMP_Deduct, the internal current state vector
+ * and the rules in the VS System.
+ * The field StateChange in the current SEM_CONTEXT is VS_FALSE
+ * if no state change has occurred, else VS_TRUE.
+ * The state change feature can also be reached by using the
+ * function SMP_NextStateChg. This function is mutually
+ * exclusive with the SMP_NextStateChg function.
+ *
+ * Argument : Context:
+ * A pointer to a VS System context.
+ *
+ * Return : Completion code:
+ *
+ * SES_CONTRADICTION:
+ * Contradiction detected, the VS System is not
+ * consistent. Check the VS System.
+ *
+ * SES_EMPTY:
+ * No event has been given to the SMP_Deduct function,
+ * i.e. SMP_deduct has not been called before calling
+ * the SMP_NextState function.
+ *
+ * SES_NOT_LOADED:
+ * No VS System loaded or connected.
+ *
+ * SES_OKAY:
+ * Success.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+#if defined VISUALSTATE_EXPERT_DLL
+
+#define SMP_NextState(Context) _SMP_NextStateChg(Context, VS_FALSE)
+
+#elif !defined SEM_NEXT_STATE_CHG
+
+/* default for normal users */
+#define SMP_NextState(Context) _SMP_NextStateChg(Context)
+
+#endif
+
+
+/*
+ * Name : SMP_NextStateChg
+ *
+ * Description : The function will update the internal current state
+ * vector, if any states can be found on basis of the event
+ * given to the function SMP_Deduct, the internal current
+ * state vector and the rules in the VS System.
+ * The returned completion code will tell if the internal
+ * state vector was updated with a new value or not, see also
+ * SMP_NextState. This feature could be used to determine if
+ * the SMP_Inquiry function needs to be called.
+ * This function is mutually exclusive with SMP_NextState and
+ * must be enabled by defining the symbol SEM_NEXT_STATE_CHG
+ * for your preprocessor/compiler.
+ *
+ * Argument : Context:
+ * A pointer to a VS System context.
+ *
+ * Return : Completion code:
+ *
+ * SES_CONTRADICTION:
+ * Contradiction detected, the VS System is not
+ * consistent. Check the VS System.
+ *
+ * SES_EMPTY:
+ * No event has been given to the SMP_Deduct function,
+ * i.e. SMP_Deduct has not been called before calling the
+ * SMP_NextStateChg function.
+ *
+ * SES_NOT_LOADED:
+ * No VS System loaded or connected.
+ *
+ * SES_FOUND:
+ * Success. The internal state vector was updated with a
+ * new value.
+ *
+ * SES_OKAY:
+ * Success. The internal state vector did not change
+ * value.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+#if defined SEM_NEXT_STATE_CHG || defined VISUALSTATE_EXPERT_DLL
+
+#define SMP_NextStateChg(Context) _SMP_NextStateChg(Context, VS_TRUE)
+
+#endif
+
+
+/*
+ * Name : SMP_Inquiry
+ *
+ * Description : The function prepares for finding events that can be used
+ * to perform transitions from the current state.
+ * All events are found by continuous calls to the function
+ * SMP_GetInput or one call to SMP_GetInputAll.
+ * As the function will inquire events on the basis of the
+ * internal current state vector, a state transition should
+ * be finished, i.e. the previously called function should
+ * be SMP_Load, SMP_Connect, SMP_Init, SMP_NextState or
+ * SMP_NextStateChg.
+ *
+ * Argument : Context:
+ * A pointer to a VS System context.
+ *
+ * Return : Completion code:
+ *
+ * SES_ACTIVE:
+ * A state transition has not been finished. The user
+ * should not call the function SMP_GetInput, because
+ * wrong events could be inquired, if the function
+ * SMP_NextState is called to finish running transitions.
+ *
+ * SES_NOT_LOADED:
+ * No VS System loaded or connected.
+ *
+ * SES_OKAY:
+ * Success.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char SMP_Inquiry (SEM_CONTEXT VS_TQ_CONTEXT *Context);
+
+
+/*
+ * Name : SMP_GetInput
+ *
+ * Description : The function is used to find events that can be used to
+ * perform state/event transitions and/or to derive action
+ * expressions from the current state. All events are found
+ * by continuous calls to this function.
+ * Because the function will inquire events on the basis of
+ * he internal current state vector, a state/event deduction
+ * should not be inquired.
+ *
+ * Argument : Context:
+ * A pointer to a VS System context.
+ *
+ * EventNo:
+ * A pointer to array to store the inquired event number.
+ *
+ * EventList:
+ * A pointer to an array which holds the event numbers that
+ * can be inquired. The EventList must be terminated with
+ * the symbol EVENT_TERMINATION_ID.
+ * If the pointer is a NULL pointer, then all events can be
+ * inquired.
+ *
+ * Return : Completion code:
+ *
+ * SES_NOT_LOADED:
+ * No VS System loaded or connected.
+ *
+ * SES_RANGE_ERR:
+ * Event number form the EventList is out of range.
+ *
+ * SES_FOUND:
+ * Success. An event has been found. The user should
+ * continue to call the SMP_GetInput, since more events
+ * may be found.
+ *
+ * SES_OKAY:
+ * Success. No more events can be found.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char SMP_GetInput (SEM_CONTEXT VS_TQ_CONTEXT *Context,
+ SEM_EVENT_TYPE *EventNo, SEM_EVENT_TYPE *EventList);
+
+
+/*
+ * Name : SMP_GetInputAll
+ *
+ * Description : The function is used to find all events that can be used
+ * to perform state/event transitions and/or to derive action
+ * expressions from the current state.
+ * All events are found by one call to this function.
+ * Because the function will inquire events on the basis of
+ * the internal current state vector, a state/event deduction
+ * should not be running.
+ * Defining the symbol SEM_GET_INPUT_ALL for your
+ * preprocessor/compiler will enable this function.
+ *
+ * Argument : Context:
+ * A pointer to a VS System context.
+ *
+ * EventVector:
+ * A pointer to array to store the inquired event numbers.
+ *
+ * EventList:
+ * Pointer to an array that holds the event numbers that
+ * can be inquired. The EventList must be terminated with
+ * the symbol EVENT_TERMINATION_ID.
+ * If the pointer is a NULL pointer, then all events can be
+ * inquired.
+ *
+ * MaxSize:
+ * Specifies the maximum length of the event vector
+ * including the symbol EVENT_TERMINATION_ID.
+ *
+ * Return : Completion code:
+ *
+ * SES_BUFFER_OVERFLOW:
+ * Event number from the EventList is out of range.
+ *
+ * SES_NOT_LOADED:
+ * No VS System loaded or connected.
+ *
+ * SES_RANGE_ERR:
+ * Event number from the EventList is out of range.
+ *
+ * SES_OKAY:
+ * Success. All events are found successfully.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char SMP_GetInputAll (SEM_CONTEXT VS_TQ_CONTEXT *Context,
+ SEM_EVENT_TYPE *EventVector, SEM_EVENT_TYPE *EventList,
+ SEM_EVENT_TYPE MaxSize);
+
+
+/*
+ * Name : SMP_Name
+ *
+ * Description : The function get the ASCII name of the specified
+ * identifier.
+ *
+ * Argument : Context:
+ * A pointer to a VS System context.
+ *
+ * IdentType:
+ * Must contain the identifier type of the identifier
+ * number which can be EVENT_TYPE, STATE_TYPE or
+ * ACTION_TYPE.
+ *
+ * IdentNo:
+ * Must contain the index number of an identifier.
+ *
+ * Test:
+ * A pointer to a text string. If the function terminates
+ * successfully, the text string contains the name of the
+ * specified identifier.
+ *
+ * MazSize:
+ * Specifies the maximum length of the text including the
+ * NULL termination character.
+ *
+ * Return : Completion code:
+ *
+ * SES_FILE_ERR:
+ * Unable to read from file.
+ *
+ * SES_NOT_LOADED:
+ * No VS System loaded or connected.
+ *
+ * SES_RANGE_ERR:
+ * Identifier number is out of range.
+ *
+ * SES_TEXT_TOO_LONG:
+ * The text is longer than MazSize.
+ *
+ * SES_TYPE_ERR:
+ * The identifier type is not correct. Remember to
+ * include the desired text in the VS System and specify the
+ * correct identifier type when calling this function.
+ *
+ * SES_OKAY:
+ * Success.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char SMP_Name (SEM_CONTEXT VS_TQ_CONTEXT *Context, unsigned char IdentType,
+ SEM_EXPLANATION_TYPE IdentNo, char *Text, unsigned short MazSize);
+
+
+/*
+ * Name : SMP_NameAbs
+ *
+ * Description : The function gets the pointer to the ASCII name of the
+ * specified identifier.
+ * This function will not work together with the VS Systems
+ * loaded from disk.
+ *
+ * Argument : Context:
+ * A pointer to a VS System context.
+ *
+ * IdentType:
+ * Must contain the identifier type of the identifier
+ * number which can be EVENT_TYPE, STATE_TYPE or
+ * ACTION_TYPE.
+ *
+ * IdentNo:
+ * Must contain the index number of an identifier.
+ *
+ * Text:
+ * Must be a pointer to a char pointer. If the function
+ * terminates successfully, the pointer points to the text
+ * containing the name of the specified identifier.
+ *
+ * Return : Completion code:
+ *
+ * SES_NOT_COMPATIBLE:
+ * The function is not compatible with current setup. The
+ * VS System is probably loaded from disk.
+ * Use the SMP_Name function or compile/link the
+ * VS System into the application.
+ *
+ * SES_NOT_LOADED:
+ * No VS System loaded or connected.
+ *
+ * SES_RANGE_ERR:
+ * Identifier number is out of range.
+ *
+ * SES_TYPE_ERR:
+ * The identifier type is not correct. Remember to
+ * include the desired text in the VS System and specify
+ * the correct identifier type when calling this
+ * function.
+ *
+ * SES_OKAY:
+ * Success.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char SMP_NameAbs (SEM_CONTEXT VS_TQ_CONTEXT *Context,
+ unsigned char IdentType, SEM_EXPLANATION_TYPE IdentNo, char VS_TQ_RULEBASE **Text);
+
+
+/*
+ * Name : SMP_Expl
+ *
+ * Description : The function get the ASCII explanation text of the
+ * specified identifier.
+ *
+ * Argument : Context:
+ * A pointer to a VS System context.
+ *
+ * IdentType:
+ * Must contain the identifier type of the identifier
+ * number which can be EVENT_TYPE, STATE_TYPE or
+ * ACTION_TYPE.
+ *
+ * IdentNo:
+ * Must contain the index number of an identifier.
+ *
+ * Text:
+ * Must be a pointer to a char pointer. If the function
+ * terminates successfully, the pointer points to the text
+ * containing the name of the specified identifier.
+ *
+ * MazSize:
+ * Specifies the maximum length of the Text including the
+ * NULL termination character.
+ *
+ * Return : Completion code:
+ *
+ * SES_FILE_ERR:
+ * Unable to read from file.
+ *
+ * SES_NOT_LOADED:
+ * No VS System loaded or connected.
+ *
+ * SES_RANGE_ERR:
+ * Identifier number is out of range.
+ *
+ * SES_TEXT_TOO_LONG:
+ * The text is longer than MazSize.
+ *
+ * SES_TYPE_ERR:
+ * The identifier type is not correct. Remember to
+ * include the desired text in the VS System and specify the
+ * correct identifier type when calling this function.
+ *
+ * SES_OKAY:
+ * Success.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char SMP_Expl (SEM_CONTEXT VS_TQ_CONTEXT *Context, unsigned char IdentType,
+ SEM_EXPLANATION_TYPE IdentNo, char *Text, unsigned short MaxSize);
+
+
+/*
+ * Name : SMP_ExplAbs
+ *
+ * Description : The function get the pointer to the ASCII explanation text
+ * of the specified identifier.
+ * This function will not work together with VS Systems
+ * loaded from disk.
+ *
+ * Argument : Context:
+ * A pointer to a VS System context.
+ *
+ * IdentType:
+ * Must contain the identifier type of the identifier
+ * number which can be EVENT_TYPE, STATE_TYPE or
+ * ACTION_TYPE.
+ *
+ * IdentNo:
+ * Must contain the index number of an identifier.
+ *
+ * Text:
+ * Must be a pointer to a char pointer. If the function
+ * terminates successfully, the pointer points to the Text
+ * containing the name of the specified identifier.
+ *
+ * Return : Completion code:
+ *
+ * SES_NOT_COMPATIBLE:
+ * The function is not compatible with current setup. The
+ * VS System is probably loaded from disk.
+ * Use the SMP_Expl function or compile/link the
+ * VS System into the application.
+ *
+ * SES_NOT_LOADED:
+ * No VS System loaded or connected.
+ *
+ * SES_RANGE_ERR:
+ * Identifier number is out of range.
+ *
+ * SES_TYPE_ERR:
+ * The identifier type is not correct. Remember to
+ * include the desired text in the VS System and specify
+ * the correct identifier type when calling this
+ * function.
+ *
+ * SES_OKAY:
+ * Success.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char SMP_ExplAbs (SEM_CONTEXT VS_TQ_CONTEXT *Context,
+ unsigned char IdentType, SEM_EXPLANATION_TYPE IdentNo, char VS_TQ_RULEBASE **Text);
+
+
+/*
+ * Name : SMP_State
+ *
+ * Description : The function will return the current state of the
+ * specified state machine.
+ *
+ * Argument : Context:
+ * A pointer to a VS System context.
+ *
+ * StateMachineNo:
+ * State machine number.
+ *
+ * StateNo:
+ * Pointer to store the current state of the specified
+ * state machine.
+ *
+ * Return : Completion code:
+ *
+ * SES_NOT_LOADED:
+ * No VS System loaded or connected.
+ *
+ * SES_RANGE_ERR:
+ * State machine index is out of range.
+ *
+ * SES_FOUND:
+ * Success. State number index found.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char SMP_State (SEM_CONTEXT VS_TQ_CONTEXT *Context,
+ SEM_STATE_MACHINE_TYPE StateMachineNo, SEM_STATE_TYPE *StateNo);
+
+
+/*
+ * Name : SMP_StateAll
+ *
+ * Description : The function will find the current state of all state
+ * machines.
+ *
+ * Argument : Context:
+ * A pointer to a VS System context.
+ *
+ * StateVector:
+ * A pointer to array to store the current state of the
+ * state machines.
+ *
+ * MaxSize:
+ * Specifies the maximum length of the state vector.
+ * Normally the length will be equal to the number of state
+ * machines. The array is not terminated.
+ *
+ * Return : Completion code:
+ *
+ * SES_BUFFER_OVERFLOW:
+ * The specified MaxSize is too small. The state vector
+ * is not valid.
+ *
+ * SES_NOT_LOADED:
+ * No VS System loaded or connected.
+ *
+ * SES_FOUND:
+ * Success. State numbers are found successfully.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char SMP_StateAll (SEM_CONTEXT VS_TQ_CONTEXT *Context,
+ SEM_STATE_TYPE *StateVector, SEM_STATE_MACHINE_TYPE MaxSize);
+
+
+/*
+ * Name : SMP_Machine
+ *
+ * Description : The function will return the state machine index of the
+ * specified state.
+ *
+ * Argument : Context:
+ * A pointer to a VS System context.
+ *
+ * StateNo:
+ * State index number.
+ *
+ * StateMachineNo:
+ * A pointer to store the found state machine index number
+ * of the specified state.
+ *
+ * Return : Completion code:
+ *
+ * SES_NOT_LOADED:
+ * No VS System loaded or connected.
+ *
+ * SES_RANGE_ERR:
+ * State index is out of range.
+ *
+ * SES_FOUND:
+ * Success. State machine index number found.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char SMP_Machine (SEM_CONTEXT VS_TQ_CONTEXT *Context,
+ SEM_STATE_TYPE StateNo, SEM_STATE_MACHINE_TYPE *StateMachineNo);
+
+
+/*
+ * Name : SMP_ForceState
+ *
+ * Description : The function is used for forcing the internal state vector
+ * into the specified state.
+ * The funcition is useful, if the user wants to reestablish
+ * the internal state vector after a power failure of the
+ * target system.
+ * Before calling this function the first time after a power
+ * down, the SMP_Init function should be called to initialize
+ * the VS system.
+ * The state vector established by calls to SMP_ForceState
+ * should be stored in EEPROM before power down.
+ *
+ * Argument : Context:
+ * A pointer to a VS System context.
+ *
+ * StateNo:
+ * State index number.
+ *
+ * Return : Completion code:
+ *
+ * SES_NOT_LOADED:
+ * No VS System loaded or connected.
+ *
+ * SES_RANGE_ERR:
+ * State index is out of range.
+ *
+ * SES_OKAY:
+ * Success.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+extern unsigned char SMP_ForceState (SEM_CONTEXT VS_TQ_CONTEXT *Context,
+ SEM_STATE_TYPE StateNo);
+
+
+/*
+ * Name : SMP_Action
+ *
+ * Description : The macro will call an action function by using the
+ * VSAction function pointer table.
+ *
+ * Argument : Context:
+ * A pointer to a VS System context.
+ *
+ * ActionNo:
+ * Action index number.
+ *
+ * Return : None.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+#if (SEM_FUNC_OLD_NAMING_STYLE)
+
+#if (SEM_FUNCEXPHANDLING == 0)
+#define smp_action(Context, ActionNo) (*VSAction[ActionNo])(Context)
+#else
+#define smp_action(Context, ActionNo) VSAction(Context, ActionNo)
+#endif
+
+#else
+
+#if (SEM_FUNCEXPHANDLING == 0)
+#define SMP_Action(Context, ActionNo) (*VSAction[ActionNo])(Context)
+#else
+#define SMP_Action(Context, ActionNo) VSAction(Context, ActionNo)
+#endif
+
+#endif
+
+
+/*
+ * Name : SMP_TableAction
+ *
+ * Description : The macro will call an action function by using the
+ * specified function pointer table.
+ *
+ * Argument : Context:
+ * A pointer to a VS System context.
+ *
+* Table:
+ * Function pointer table.
+ *
+ * ActionNo:
+ * Action index number.
+ *
+ * Return : None.
+ *
+ * Portability : ANSI-C Compiler.
+ */
+#if (SEM_FUNC_OLD_NAMING_STYLE)
+
+#if (SEM_FUNCEXPHANDLING == 0)
+#define smp_table_action(Context, Table, ActionNo) (* (Table)[ActionNo])(Context)
+#else
+#define smp_table_action(Context, Func, ActionNo) Func(Context, ActionNo)
+#endif
+
+#else
+
+#if (SEM_FUNCEXPHANDLING == 0)
+#define SMP_TableAction(Context, Table, ActionNo) (* (Table)[ActionNo])(Context)
+#else
+#define SMP_TableAction(Context, Func, ActionNo) Func(Context, ActionNo)
+#endif
+
+#endif
+
+#endif
diff --git a/cesar/lib/visual_state_api/src/SEMMach.c b/cesar/lib/visual_state_api/src/SEMMach.c
new file mode 100644
index 0000000000..352a3a756b
--- /dev/null
+++ b/cesar/lib/visual_state_api/src/SEMMach.c
@@ -0,0 +1,27 @@
+/*
+ * Type: Source Code File
+ *
+ * Id: SEMMach.c
+ *
+ * Function: Contains the SEM_Machine SEM Library Expert version 4 function.
+ *
+ * Portability: ANSI-C Compiler.
+ *
+ * Copyright (c) 1999-2006 IAR Systems. All rights reserved.
+ */
+
+/*
+ * Version ! Date ! Status ! Changes
+ *----------------------------------------------------------------------------
+ * 4.0.0.0 ! 011198 ! Closed ! -
+ * 4.0.4 ! 010799 ! Closed ! Minor update, there might be no changes to this particular file.
+ */
+
+#include "SEMLibE.h"
+
+
+unsigned char VS_CALL_CONV SEM_Machine (SEM_STATE_TYPE StateNo,
+ SEM_STATE_MACHINE_TYPE *StateMachineNo)
+{
+ return (SMP_Machine (SEMContext, StateNo, StateMachineNo));
+}
diff --git a/cesar/lib/visual_state_api/src/SEMMain.c b/cesar/lib/visual_state_api/src/SEMMain.c
new file mode 100644
index 0000000000..79eab6180c
--- /dev/null
+++ b/cesar/lib/visual_state_api/src/SEMMain.c
@@ -0,0 +1,154 @@
+/*
+ * Type: Source Code File
+ *
+ * Id: SEMMain.c
+ *
+ * Function: Contains the general SEM Library Expert version 4 functions.
+ *
+ * Portability: ANSI-C Compiler.
+ *
+ * Copyright (c) 1999-2006 IAR Systems. All rights reserved.
+ */
+
+/*
+ * Version ! Date ! Status ! Changes
+ *----------------------------------------------------------------------------
+ * 4.0.0.2 ! 200199 ! Closed ! -
+ * 4.0.4 ! 010799 ! Closed ! Minor update, there might be no changes to this particular file.
+ */
+
+#include "SEMLibE.h"
+
+
+SEM_CONTEXT VS_TQ_CONTEXT *SEMContext = ((SEM_CONTEXT VS_TQ_CONTEXT *) 0);
+unsigned char SEMInitCC = SES_OKAY;
+
+
+#ifdef VISUALSTATE_EXPERT_DLL
+unsigned char DLL_EXPORT SEM_GetInitCC (void)
+{
+ return SEMInitCC;
+}
+#endif
+
+
+unsigned char SEM_Connect (void VS_TQ_RULEBASE *VSData)
+{
+ if (SEMContext)
+ SEM_Free ();
+
+ return (SMP_Connect (&SEMContext, VSData));
+}
+
+
+#ifdef SE_EXPERTDLL
+unsigned char VS_CALL_CONV SEM_Load (const char *FileName)
+{
+ if (SEMContext)
+ SEM_Free ();
+ return (SMP_Load (&SEMContext, FileName));
+}
+#endif
+
+
+void VS_CALL_CONV SEM_Free (void)
+{
+ SMP_Free (SEMContext);
+ SEMContext = NULL;
+}
+
+
+void VS_CALL_CONV SEM_Init (void)
+{
+ SEMInitCC = SMP_Init (SEMContext);
+}
+
+
+#if (SEM_GUARD_EXPRESSION)
+#ifdef VISUALSTATE_EXPERT_DLL
+void SEM_InitGuardCallBack (unsigned char (**Guard)(void))
+#else
+#if (SEM_FUNCEXPHANDLING == 0)
+void SEM_InitGuardCallBack (VS_GUARDEXPR_TYPE VS_TQ_GUARDEXPRCOL * Guard)
+#else
+void SEM_InitGuardCallBack (unsigned char (*Guard)(SEM_CONTEXT VS_TQ_CONTEXT *Context, SEM_GUARD_EXPRESSION_TYPE i))
+#endif
+#endif
+{
+ SMP_InitGuardCallBack (SEMContext, Guard);
+}
+#endif
+
+
+#if (SEM_SIGNAL_DB)
+void SEM_InitSignalDBCallBack (void (*SEM_SignalDB)(SEM_CONTEXT VS_TQ_CONTEXT *Context, SEM_EVENT_TYPE SignalNo))
+{
+ SMP_InitSignalDBCallBack (SEMContext, SEM_SignalDB);
+}
+#endif
+
+
+#if (SEM_SIGNAL)
+void VS_CALL_CONV SEM_InitSignalQueue (void)
+{
+ SMP_InitSignalQueue (SEMContext);
+}
+#endif
+
+
+unsigned char VS_CALL_CONV SEM_Deduct (SEM_EVENT_TYPE EventNo)
+{
+ return (SMP_Deduct (SEMContext, EventNo));
+}
+
+
+unsigned char VS_CALL_CONV SEM_GetOutput (SEM_ACTION_EXPRESSION_TYPE *ActionNo)
+{
+ return (SMP_GetOutput (SEMContext, ActionNo));
+}
+
+
+#if defined SEM_GET_OUTPUT_ALL || defined VISUALSTATE_EXPERT_DLL
+#if (SEM_SIGNAL)
+#ifndef VISUALSTATE_EXPERT_DLL
+#error SEM_GetOutputAll cannot be used when the Project contains signals.
+#endif
+#endif
+unsigned char VS_CALL_CONV SEM_GetOutputAll (SEM_ACTION_EXPRESSION_TYPE *ActionExprVector,
+ SEM_ACTION_EXPRESSION_TYPE MaxSize)
+{
+ return (SMP_GetOutputAll (SEMContext, ActionExprVector, MaxSize));
+}
+#endif
+
+
+#ifdef VISUALSTATE_EXPERT_DLL
+#ifdef SEM_NEXT_STATE_CHG
+#undef SEM_NEXT_STATE_CHG
+#endif
+#endif
+
+#ifndef SEM_NEXT_STATE_CHG
+unsigned char VS_CALL_CONV SEM_NextState (void)
+{
+ return (SMP_NextState (SEMContext));
+}
+#endif
+
+
+#ifdef VISUALSTATE_EXPERT_DLL
+#define SEM_NEXT_STATE_CHG
+#endif
+
+
+#ifdef SEM_NEXT_STATE_CHG
+unsigned char VS_CALL_CONV SEM_NextStateChg (void)
+{
+ return (SMP_NextStateChg (SEMContext));
+}
+#endif
+
+
+#ifdef VISUALSTATE_EXPERT_DLL
+#undef SEM_NEXT_STATE_CHG
+#endif
diff --git a/cesar/lib/visual_state_api/src/SEMName.c b/cesar/lib/visual_state_api/src/SEMName.c
new file mode 100644
index 0000000000..81e5b65c0b
--- /dev/null
+++ b/cesar/lib/visual_state_api/src/SEMName.c
@@ -0,0 +1,27 @@
+/*
+ * Type: Source Code File
+ *
+ * Id: SEMName.c
+ *
+ * Function: Contains the SEM_Name SEM Library Expert version 4 function.
+ *
+ * Portability: ANSI-C Compiler.
+ *
+ * Copyright (c) 1999-2006 IAR Systems. All rights reserved.
+ */
+
+/*
+ * Version ! Date ! Status ! Changes
+ *----------------------------------------------------------------------------
+ * 4.0.0.0 ! 011198 ! Closed ! -
+ * 4.0.4 ! 010799 ! Closed ! Minor update, there might be no changes to this particular file.
+ */
+
+#include "SEMLibE.h"
+
+
+unsigned char VS_CALL_CONV SEM_Name (unsigned char IdentType,
+ SEM_EXPLANATION_TYPE IdentNo, char *Text, unsigned short MaxSize)
+{
+ return (SMP_Name (SEMContext, IdentType, IdentNo, Text, MaxSize));
+}
diff --git a/cesar/lib/visual_state_api/src/SEMNameA.c b/cesar/lib/visual_state_api/src/SEMNameA.c
new file mode 100644
index 0000000000..e813741197
--- /dev/null
+++ b/cesar/lib/visual_state_api/src/SEMNameA.c
@@ -0,0 +1,28 @@
+/*
+ * Type: Source Code File
+ *
+ * Id: SEMNameA.c
+ *
+ * Function: Contains the SEM_NameAbs SEM Library Expert version 4
+ * function.
+ *
+ * Portability: ANSI-C Compiler.
+ *
+ * Copyright (c) 1999-2006 IAR Systems. All rights reserved.
+ */
+
+/*
+ * Version ! Date ! Status ! Changes
+ *----------------------------------------------------------------------------
+ * 4.0.0.0 ! 011198 ! Closed ! -
+ * 4.0.4 ! 010799 ! Closed ! Minor update, there might be no changes to this particular file.
+ */
+
+#include "SEMLibE.h"
+
+
+unsigned char VS_CALL_CONV SEM_NameAbs (unsigned char IdentType,
+ SEM_EXPLANATION_TYPE IdentNo, char VS_TQ_RULEBASE **Text)
+{
+ return (SMP_NameAbs (SEMContext, IdentType, IdentNo, Text));
+}
diff --git a/cesar/lib/visual_state_api/src/SEMStAll.c b/cesar/lib/visual_state_api/src/SEMStAll.c
new file mode 100644
index 0000000000..2ebdaae2f5
--- /dev/null
+++ b/cesar/lib/visual_state_api/src/SEMStAll.c
@@ -0,0 +1,28 @@
+/*
+ * Type: Source Code File
+ *
+ * Id: SEMStAll.c
+ *
+ * Function: Contains the SEM_StateAll SEM Library Expert version 4
+ * function.
+ *
+ * Portability: ANSI-C Compiler.
+ *
+ * Copyright (c) 1999-2006 IAR Systems. All rights reserved.
+ */
+
+/*
+ * Version ! Date ! Status ! Changes
+ *----------------------------------------------------------------------------
+ * 4.0.0.0 ! 011198 ! Closed ! -
+ * 4.0.4 ! 010799 ! Closed ! Minor update, there might be no changes to this particular file.
+ */
+
+#include "SEMLibE.h"
+
+
+unsigned char VS_CALL_CONV SEM_StateAll (SEM_STATE_TYPE *StateVector,
+ SEM_STATE_MACHINE_TYPE MaxSize)
+{
+ return (SMP_StateAll (SEMContext, StateVector, MaxSize));
+}
diff --git a/cesar/lib/visual_state_api/src/SEMState.c b/cesar/lib/visual_state_api/src/SEMState.c
new file mode 100644
index 0000000000..b487762ea6
--- /dev/null
+++ b/cesar/lib/visual_state_api/src/SEMState.c
@@ -0,0 +1,27 @@
+/*
+ * Type: Source Code File
+ *
+ * Id: SEMState.c
+ *
+ * Function: Contains the SEM_State SEM Library Expert version 4 function.
+ *
+ * Portability: ANSI-C Compiler.
+ *
+ * Copyright (c) 1999-2006 IAR Systems. All rights reserved.
+ */
+
+/*
+ * Version ! Date ! Status ! Changes
+ *----------------------------------------------------------------------------
+ * 4.0.0.0 ! 011198 ! Closed ! -
+ * 4.0.4 ! 010799 ! Closed ! Minor update, there might be no changes to this particular file.
+ */
+
+#include "SEMLibE.h"
+
+
+unsigned char VS_CALL_CONV SEM_State (SEM_STATE_MACHINE_TYPE StateMachineNo,
+ SEM_STATE_TYPE *StateNo)
+{
+ return (SMP_State (SEMContext, StateMachineNo, StateNo));
+}
diff --git a/cesar/lib/visual_state_api/src/SMPExpl.c b/cesar/lib/visual_state_api/src/SMPExpl.c
new file mode 100644
index 0000000000..b4b6c15aba
--- /dev/null
+++ b/cesar/lib/visual_state_api/src/SMPExpl.c
@@ -0,0 +1,92 @@
+/*
+ * Type: Source Code File
+ *
+ * Id: SMPExpl.c
+ *
+ * Function: Contains the SMP_Expl SEM Library Expert version 4 function.
+ *
+ * Portability: ANSI-C Compiler.
+ *
+ * Copyright (c) 1999-2006 IAR Systems. All rights reserved.
+ */
+
+/*
+ * Version ! Date ! Status ! Changes
+ *----------------------------------------------------------------------------
+ * 4.0.0.1 ! 101298 ! Closed ! -
+ * 4.0.4 ! 010799 ! Closed ! Minor update, there might be no changes to this particular file.
+ */
+
+#include "SEMLibE.h"
+
+
+unsigned char SMP_Expl (SEM_CONTEXT VS_TQ_CONTEXT *Context, unsigned char IdentType,
+ SEM_EXPLANATION_TYPE IdentNo, char *Text, unsigned short MaxSize)
+{
+ int c;
+ unsigned long Pos;
+ unsigned short i;
+ char VS_TQ_RULEBASE * pT = NULL; /* initialization may be necessary to avoid compiler warnings */
+
+ if (!Context)
+ return (SES_NOT_LOADED);
+ if (!MaxSize)
+ return (SES_TEXT_TOO_LONG);
+ switch (IdentType)
+ {
+ case EVENT_TYPE :
+ if (!Context->pEEIPos)
+ return (SES_TYPE_ERR);
+ if (Context->nNofEvents <= (SEM_EVENT_TYPE)IdentNo)
+ return (SES_RANGE_ERR);
+ Pos = Context->pEEIPos[IdentNo];
+ break;
+ case STATE_TYPE :
+ if (!Context->pSEIPos)
+ return (SES_TYPE_ERR);
+ if (Context->nNofStates <= (SEM_STATE_TYPE)IdentNo)
+ return (SES_RANGE_ERR);
+ Pos = Context->pSEIPos[IdentNo];
+ break;
+ case ACTION_TYPE :
+ if (!Context->pAEIPos)
+ return (SES_TYPE_ERR);
+ if (Context->nNofActionFunctions <= (SEM_ACTION_FUNCTION_TYPE)IdentNo)
+ return (SES_RANGE_ERR);
+ Pos = Context->pAEIPos[IdentNo];
+ break;
+ default :
+ return (SES_TYPE_ERR);
+ }
+ if (Context->pVSFile)
+ {
+#ifndef SE_EXPERTDLL
+ return (SES_NOT_LOADED);
+#else
+ if (fseek (Context->pVSFile, (long)Pos, SEEK_SET))
+ return (SES_FILE_ERR);
+#endif
+ }
+ else
+ pT = (char VS_TQ_RULEBASE *)((char VS_TQ_RULEBASE *)Context->pVSData + Pos);
+
+ for (i = 0; i < MaxSize; i++)
+ {
+#ifdef SE_EXPERTDLL
+ if (Context->pVSFile)
+ {
+ c = fgetc (Context->pVSFile);
+ if (c == EOF)
+ return (SES_FILE_ERR);
+ }
+ else
+#endif
+ c = *pT++;
+ *Text++ = (char)c;
+ if (c == '\0')
+ return (SES_OKAY);
+ }
+ Text--;
+ *Text = '\0';
+ return (SES_TEXT_TOO_LONG);
+}
diff --git a/cesar/lib/visual_state_api/src/SMPExplA.c b/cesar/lib/visual_state_api/src/SMPExplA.c
new file mode 100644
index 0000000000..54e6ad0e6a
--- /dev/null
+++ b/cesar/lib/visual_state_api/src/SMPExplA.c
@@ -0,0 +1,68 @@
+/*
+ * Type: Source Code File
+ *
+ * Id: SMPExplA.c
+ *
+ * Function: Contains the SMP_ExplAbs SEM Library Expert version 4
+ * function.
+ *
+ * Portability: ANSI-C Compiler.
+ *
+ * Copyright (c) 1999-2006 IAR Systems. All rights reserved.
+ */
+
+/*
+ * Version ! Date ! Status ! Changes
+ *----------------------------------------------------------------------------
+ * 4.0.0.1 ! 101298 ! Closed ! -
+ * 4.0.4 ! 010799 ! Closed ! Minor update, there might be no changes to this particular file.
+ */
+
+#include "SEMLibE.h"
+
+
+unsigned char SMP_ExplAbs (SEM_CONTEXT VS_TQ_CONTEXT *Context, unsigned char IdentType,
+ SEM_EXPLANATION_TYPE IdentNo, char VS_TQ_RULEBASE **Text)
+{
+ unsigned long Pos;
+
+ if (!Context)
+ return (SES_NOT_LOADED);
+ switch (IdentType)
+ {
+ case EVENT_TYPE :
+ if (!Context->pEEIPos)
+ return (SES_TYPE_ERR);
+ if (Context->nNofEvents <= (SEM_EVENT_TYPE)IdentNo)
+ return (SES_RANGE_ERR);
+ Pos = Context->pEEIPos[IdentNo];
+ break;
+ case STATE_TYPE :
+ if (!Context->pSEIPos)
+ return (SES_TYPE_ERR);
+ if (Context->nNofStates <= (SEM_STATE_TYPE)IdentNo)
+ return (SES_RANGE_ERR);
+ Pos = Context->pSEIPos[IdentNo];
+ break;
+ case ACTION_TYPE :
+ if (!Context->pAEIPos)
+ return (SES_TYPE_ERR);
+ if (Context->nNofActionFunctions <= (SEM_ACTION_FUNCTION_TYPE)IdentNo)
+ return (SES_RANGE_ERR);
+ Pos = Context->pAEIPos[IdentNo];
+ break;
+ default :
+ return (SES_TYPE_ERR);
+ }
+ if (Context->pVSFile)
+ {
+#ifndef SE_EXPERTDLL
+ return (SES_NOT_LOADED);
+#else
+ return (SES_NOT_COMPATIBLE);
+#endif
+ }
+ else
+ *Text = (char VS_TQ_RULEBASE *)((char VS_TQ_RULEBASE *)Context->pVSData + Pos);
+ return (SES_OKAY);
+}
diff --git a/cesar/lib/visual_state_api/src/SMPForce.c b/cesar/lib/visual_state_api/src/SMPForce.c
new file mode 100644
index 0000000000..955d206ac1
--- /dev/null
+++ b/cesar/lib/visual_state_api/src/SMPForce.c
@@ -0,0 +1,32 @@
+/*
+ * Type: Source Code File
+ *
+ * Id: SMPForce.c
+ *
+ * Function: Contains the SMP_ForceState SEM Library Expert version 4
+ * function.
+ *
+ * Portability: ANSI-C Compiler.
+ *
+ * Copyright (c) 1999-2006 IAR Systems. All rights reserved.
+ */
+
+/*
+ * Version ! Date ! Status ! Changes
+ *----------------------------------------------------------------------------
+ * 4.0.0.0 ! 011198 ! Closed ! -
+ * 4.0.4 ! 010799 ! Closed ! Minor update, there might be no changes to this particular file.
+ */
+
+#include "SEMLibE.h"
+
+
+unsigned char SMP_ForceState (SEM_CONTEXT VS_TQ_CONTEXT *Context, SEM_STATE_TYPE StateNo)
+{
+ if (!Context)
+ return (SES_NOT_LOADED);
+ if (Context->nNofStates <= StateNo)
+ return (SES_RANGE_ERR);
+ Context->pCSV[Context->pSMI[StateNo]] = StateNo;
+ return (SES_OKAY);
+}
diff --git a/cesar/lib/visual_state_api/src/SMPInq.c b/cesar/lib/visual_state_api/src/SMPInq.c
new file mode 100644
index 0000000000..007b374bc9
--- /dev/null
+++ b/cesar/lib/visual_state_api/src/SMPInq.c
@@ -0,0 +1,238 @@
+/*
+ * Type: Source Code File
+ *
+ * Id: SMPInq.c
+ *
+ * Function: Contains the SMP_Inquiry, SMP_GetInput and SMP_GetInputAll
+ * SEM Library Expert version 4 functions.
+ *
+ * Portability: ANSI-C Compiler.
+ *
+ * Copyright (c) 1999-2006 IAR Systems. All rights reserved.
+ */
+
+/*
+ * Version ! Date ! Status ! Changes
+ *----------------------------------------------------------------------------
+ * 4.0.0.5 ! 200199 ! Closed ! -
+ * 4.0.4 ! 010799 ! Closed ! Minor update, there might be no changes to this particular file.
+ * 4.0.4.1 ! 050799 ! Closed ! SMP_GetInput fixed.
+ */
+
+#include "SEMLibE.h"
+
+
+unsigned char SMP_Inquiry (SEM_CONTEXT VS_TQ_CONTEXT *Context)
+{
+ if (!Context)
+ return (SES_NOT_LOADED);
+ Context->InqAct = VS_FALSE;
+ if (Context->State != STATE_SEM_INITIALIZE)
+ return (SES_ACTIVE);
+ else
+ return (SES_OKAY);
+}
+
+
+unsigned char SMP_GetInput (SEM_CONTEXT VS_TQ_CONTEXT *Context,
+ SEM_EVENT_TYPE *EventNo, SEM_EVENT_TYPE *EventList)
+{
+ SEM_RULE_DATA_TYPE rd;
+ SEM_RULE_TABLE_INDEX_TYPE iInqFirstR, iInqLastR;
+ unsigned char i, InqIt, nPos;
+#if (SEM_RMN_NEGATIVE_STATE_SYNCS || defined VISUALSTATE_EXPERT_DLL)
+ SEM_STATE_TYPE s;
+ unsigned char nNeg;
+#endif
+
+ if (!Context)
+ return (SES_NOT_LOADED);
+ if (!Context->InqAct)
+ Context->InqEventNo = 0;
+ for(;;)
+ {
+ Context->InqAct = VS_FALSE;
+ if (Context->InqEventNo >= Context->nNofEvents)
+ break;
+ if (EventList)
+ {
+ Context->InqFoundEventNo = EventList[Context->InqEventNo];
+ if (Context->InqFoundEventNo == EVENT_TERMINATION_ID)
+ break;
+ if (Context->nNofEvents <= Context->InqFoundEventNo)
+ return (SES_RANGE_ERR);
+ }
+ else
+ Context->InqFoundEventNo = Context->InqEventNo;
+ Context->InqEventNo++;
+ Context->InqCurrentEventNo = Context->InqFoundEventNo;
+ for (InqIt = 2; InqIt; InqIt--)
+ {
+#if (SEM_EVENT_GROUP_TABLE_INDEX) || defined VISUALSTATE_EXPERT_DLL
+ if (InqIt == 2)
+ {
+ if (Context->EventGroupType == 2)
+ {
+ Context->iInqFirstEgi = Context->pEGTI[Context->InqCurrentEventNo];
+ Context->iInqLastEgi = Context->pEGTI[Context->InqCurrentEventNo + 1];
+ }
+ }
+#endif
+ if (InqIt == 1)
+ {
+#if (SEM_EVENT_GROUP_INDEX) || defined VISUALSTATE_EXPERT_DLL
+ if (Context->EventGroupType == 1)
+ {
+ Context->InqCurrentEventNo = (SEM_EVENT_TYPE) Context->pEGT[Context->InqCurrentEventNo];
+ if (Context->InqCurrentEventNo == EVENT_UNDEFINED)
+ break;
+ Context->InqCurrentEventNo = (SEM_EVENT_TYPE)(Context->InqCurrentEventNo + Context->nNofEvents);
+ }
+#endif
+#if (SEM_EVENT_GROUP_TABLE_INDEX) || defined VISUALSTATE_EXPERT_DLL
+ if (Context->EventGroupType == 2)
+ {
+ if (Context->iInqFirstEgi == Context->iInqLastEgi)
+ break;
+ Context->InqCurrentEventNo = (SEM_EVENT_TYPE) Context->pEGT[Context->iInqFirstEgi++];
+ Context->InqCurrentEventNo = (SEM_EVENT_TYPE)(Context->InqCurrentEventNo + Context->nNofEvents);
+ InqIt++;
+ }
+#endif
+ }
+ iInqFirstR = Context->pRTI[Context->InqCurrentEventNo];
+ iInqLastR = Context->pRTI[Context->InqCurrentEventNo + 1];
+ while (iInqFirstR < iInqLastR)
+ {
+ Context->iInqRI = Context->pRI[iInqFirstR++];
+#if (SEM_RD_WIDTH_8_BIT && SEM_RDHW_TYPE_1 && SEM_RDHW_WIDTH_16_BIT)
+ Context->iInqRI++;
+ rd = Context->pRD[Context->iInqRI++];
+ nPos = (unsigned char)(rd & 0x0F);
+#if (SEM_RMN_NEGATIVE_STATE_SYNCS || defined VISUALSTATE_EXPERT_DLL)
+ nNeg = (unsigned char)(rd >> 4);
+#endif
+#endif
+#if (SEM_RD_WIDTH_8_BIT && SEM_RDHW_TYPE_2 && SEM_RDHW_WIDTH_24_BIT)
+ rd = Context->pRD[Context->iInqRI];
+ Context->iInqRI += 3;
+ nPos = (unsigned char)(rd & 0x0F);
+#if (SEM_RMN_NEGATIVE_STATE_SYNCS || defined VISUALSTATE_EXPERT_DLL)
+ nNeg = (unsigned char)(rd >> 4);
+#endif
+#endif
+#if (SEM_RD_WIDTH_8_BIT && SEM_RDHW_TYPE_1 && SEM_RDHW_WIDTH_32_BIT)
+ Context->iInqRI += 2;
+#if (SEM_RMN_NEGATIVE_STATE_SYNCS || defined VISUALSTATE_EXPERT_DLL)
+ nNeg = (unsigned char)Context->pRD[Context->iInqRI++];
+#else
+ Context->iInqRI++;
+#endif
+ nPos = (unsigned char)Context->pRD[Context->iInqRI++];
+#endif
+#if (SEM_RD_WIDTH_8_BIT && SEM_RDHW_TYPE_2 && SEM_RDHW_WIDTH_48_BIT)
+#if (SEM_RMN_NEGATIVE_STATE_SYNCS || defined VISUALSTATE_EXPERT_DLL)
+ nNeg = (unsigned char)Context->pRD[Context->iInqRI++];
+#else
+ Context->iInqRI++;
+#endif
+ nPos = (unsigned char)Context->pRD[Context->iInqRI];
+ Context->iInqRI += 5;
+#endif
+#if (SEM_RD_WIDTH_16_BIT && SEM_RDHW_TYPE_1 && SEM_RDHW_WIDTH_16_BIT)
+ rd = Context->pRD[Context->iInqRI++];
+ nPos = (unsigned char)(rd & 0x0F);
+#if (SEM_RMN_NEGATIVE_STATE_SYNCS || defined VISUALSTATE_EXPERT_DLL)
+ nNeg = (unsigned char)((rd >> 4) & 0x0F);
+#endif
+#endif
+#if (SEM_RD_WIDTH_16_BIT && SEM_RDHW_TYPE_3 && SEM_RDHW_WIDTH_32_BIT)
+ rd = Context->pRD[Context->iInqRI++];
+ nPos = (unsigned char)(rd & 0x0F);
+#if (SEM_RMN_NEGATIVE_STATE_SYNCS || defined VISUALSTATE_EXPERT_DLL)
+ nNeg = (unsigned char)((rd >> 4) & 0x0F);
+#endif
+ Context->iInqRI += 1;
+#endif
+#if (SEM_RD_WIDTH_16_BIT && SEM_RDHW_TYPE_1 && SEM_RDHW_WIDTH_32_BIT)
+ Context->iInqRI++;
+ rd = Context->pRD[Context->iInqRI++];
+ nPos = (unsigned char)(rd & 0x0FF);
+#if (SEM_RMN_NEGATIVE_STATE_SYNCS || defined VISUALSTATE_EXPERT_DLL)
+ nNeg = (unsigned char)(rd >> 8);
+#endif
+#endif
+#if (SEM_RD_WIDTH_16_BIT && SEM_RDHW_TYPE_2 && SEM_RDHW_WIDTH_48_BIT)
+ rd = Context->pRD[Context->iInqRI];
+ Context->iInqRI += 3;
+ nPos = (unsigned char)(rd & 0x0FF);
+#if (SEM_RMN_NEGATIVE_STATE_SYNCS || defined VISUALSTATE_EXPERT_DLL)
+ nNeg = (unsigned char)(rd >> 8);
+#endif
+#endif
+#if (SEM_RD_WIDTH_32_BIT && SEM_RDHW_TYPE_1 && SEM_RDHW_WIDTH_32_BIT)
+ rd = Context->pRD[Context->iInqRI++];
+ nPos = (unsigned char)(rd & 0X0FF);
+#if (SEM_RMN_NEGATIVE_STATE_SYNCS || defined VISUALSTATE_EXPERT_DLL)
+ nNeg = (unsigned char)((rd >> 8) & 0X0FF);
+#endif
+#endif
+#if (SEM_RD_WIDTH_32_BIT && SEM_RDHW_TYPE_3 && SEM_RDHW_WIDTH_64_BIT)
+ rd = Context->pRD[Context->iInqRI++];
+ nPos = (unsigned char)(rd & 0x0FF);
+#if (SEM_RMN_NEGATIVE_STATE_SYNCS || defined VISUALSTATE_EXPERT_DLL)
+ nNeg = (unsigned char)((rd >> 8) & 0x0FF);
+#endif
+ Context->iInqRI++;
+#endif
+ for (i = 0; i < nPos; i++)
+ {
+ rd = Context->pRD[Context->iInqRI++];
+ if (rd != Context->pCSV[Context->pSMI[rd]])
+ goto NextRule;
+ }
+#if (SEM_RMN_NEGATIVE_STATE_SYNCS || defined VISUALSTATE_EXPERT_DLL)
+ for (i = 0; i < nNeg; i++)
+ {
+ rd = Context->pRD[Context->iInqRI++];
+ s = Context->pCSV[Context->pSMI[rd]];
+ if ((s == STATE_UNDEFINED) || (s == (SEM_STATE_TYPE) rd))
+ goto NextRule;
+ }
+#endif
+ Context->InqAct = VS_TRUE;
+ *EventNo = Context->InqFoundEventNo;
+ return (SES_FOUND);
+NextRule :
+ ;
+ }
+ }
+ }
+ return (SES_OKAY);
+}
+
+
+#if defined SEM_GET_INPUT_ALL || defined VISUALSTATE_EXPERT_DLL
+unsigned char SMP_GetInputAll (SEM_CONTEXT VS_TQ_CONTEXT *Context,
+ SEM_EVENT_TYPE *EventVector, SEM_EVENT_TYPE *EventList,
+ SEM_EVENT_TYPE MaxSize)
+{
+ SEM_EVENT_TYPE i;
+ unsigned char CC;
+
+ if (!Context)
+ return (SES_NOT_LOADED);
+
+ for (i = 0; ((CC = SMP_GetInput (Context, &EventVector[i], EventList)) == SES_FOUND)
+ && i < MaxSize - 1; i++);
+
+ if (CC == SES_OKAY)
+ {
+ EventVector[i] = EVENT_TERMINATION_ID;
+ return (SES_OKAY);
+ }
+ if (CC == SES_FOUND)
+ return (SES_BUFFER_OVERFLOW);
+ return (CC);
+}
+#endif
diff --git a/cesar/lib/visual_state_api/src/SMPInst.c b/cesar/lib/visual_state_api/src/SMPInst.c
new file mode 100644
index 0000000000..13b094f700
--- /dev/null
+++ b/cesar/lib/visual_state_api/src/SMPInst.c
@@ -0,0 +1,78 @@
+/*
+ * Type: Source Code File
+ *
+ * Id: SMPInst.c
+ *
+ * Function: Contains the SMP_InitInstances and SMP_SetInstance
+ * SEM Library Expert version 4 functions.
+ *
+ * Portability: ANSI-C Compiler.
+ *
+ * Copyright (c) 1999-2006 IAR Systems. All rights reserved.
+ */
+
+/*
+ * Version ! Date ! Status ! Changes
+ *----------------------------------------------------------------------------
+ * 4.0.0.1 ! 021298 ! Closed ! -
+ * 4.0.4 ! 010799 ! Closed ! Minor update, there might be no changes to this particular file.
+ */
+
+#include "SEMLibE.h"
+#include "limits.h"
+
+#if (VS_REALLINKMODE == 1)
+#include "RealLink.h"
+#endif
+
+unsigned char SMP_InitInstances (SEM_CONTEXT VS_TQ_CONTEXT *Context)
+{
+ unsigned long i;
+
+ if (!Context)
+ return (SES_NOT_LOADED);
+
+#if VS_USE_HEAP
+ if (Context->pIns)
+ free (Context->pIns);
+ if ((unsigned long) ULONG_MAX / Context->nNofInstances < (unsigned long) Context->nNofStateMachines)
+ return (SES_TYPE_OVERFLOW);
+#endif
+ if (Context->nNofInstances > 1)
+ {
+#if VS_USE_HEAP
+ Context->pIns = (SEM_STATE_TYPE *)malloc ((Context->nNofInstances * Context->nNofStateMachines) * sizeof (SEM_STATE_TYPE));
+ if (!Context->pIns)
+ return (SES_MEM_ERR);
+
+#endif
+ Context->pCSV = Context->pIns;
+ Context->ActIns = 0;
+
+ for (i = 0; i < (unsigned long)Context->nNofStateMachines * Context->nNofInstances; i++)
+ Context->pIns[i] = STATE_UNDEFINED;
+ }
+
+ return (SES_OKAY);
+}
+
+
+unsigned char SMP_SetInstance (SEM_CONTEXT VS_TQ_CONTEXT *Context, SEM_INSTANCE_TYPE Instance)
+{
+ if (!Context)
+ return (SES_NOT_LOADED);
+ if (Instance >= Context->nNofInstances)
+ return (SES_RANGE_ERR);
+ if ((Context->State != STATE_SEM_INITIALIZE) || (Context->InqAct))
+ return (SES_ACTIVE);
+ if (Context->nNofInstances > 1)
+ {
+ Context->pCSV = (Context->pIns + Instance * Context->nNofStateMachines);
+ Context->ActIns = Instance;
+ }
+
+#if (VS_REALLINKMODE == 1)
+ VS_WAIT_ELM(Context, VS_ENABLE_INSTANCE, Ind_INSTANCE_SET, &Instance);
+#endif
+ return (SES_OKAY);
+}
diff --git a/cesar/lib/visual_state_api/src/SMPMach.c b/cesar/lib/visual_state_api/src/SMPMach.c
new file mode 100644
index 0000000000..8a154790c9
--- /dev/null
+++ b/cesar/lib/visual_state_api/src/SMPMach.c
@@ -0,0 +1,32 @@
+/*
+ * Type: Source Code File
+ *
+ * Id: SMPMach.c
+ *
+ * Function: Contains the SMP_Machine SEM Library Expert version 4 function.
+ *
+ * Portability: ANSI-C Compiler.
+ *
+ * Copyright (c) 1999-2006 IAR Systems. All rights reserved.
+ */
+
+/*
+ * Version ! Date ! Status ! Changes
+ *----------------------------------------------------------------------------
+ * 4.0.0.1 ! 301198 ! Closed ! -
+ * 4.0.4 ! 010799 ! Closed ! Minor update, there might be no changes to this particular file.
+ */
+
+#include "SEMLibE.h"
+
+
+unsigned char SMP_Machine (SEM_CONTEXT VS_TQ_CONTEXT *Context, SEM_STATE_TYPE StateNo,
+ SEM_STATE_MACHINE_TYPE *StateMachineNo)
+{
+ if (!Context)
+ return (SES_NOT_LOADED);
+ if (Context->nNofStates <= StateNo)
+ return (SES_RANGE_ERR);
+ *StateMachineNo = Context->pSMI[StateNo];
+ return (SES_FOUND);
+}
diff --git a/cesar/lib/visual_state_api/src/SMPMain.c b/cesar/lib/visual_state_api/src/SMPMain.c
new file mode 100644
index 0000000000..4b0d78c835
--- /dev/null
+++ b/cesar/lib/visual_state_api/src/SMPMain.c
@@ -0,0 +1,939 @@
+/*
+ * Type: Source Code File
+ *
+ * Id: SMPMain.c
+ *
+ * Function: Contains the general SEM Library Expert version 4 functions.
+ *
+ * Portability: ANSI-C Compiler.
+ *
+ * Copyright (c) 1999-2006 IAR Systems. All rights reserved.
+ */
+
+/*
+ * Version ! Date ! Status ! Changes
+ *----------------------------------------------------------------------------
+ * 4.0.0.17 ! 290199 ! Closed ! -
+ * 4.0.4 ! 010799 ! Closed ! Minor update, there might be no changes to this particular file.
+ */
+
+#include "SEMLibE.h"
+
+#if (VS_REALLINKMODE == 1)
+#include "RealLink.h"
+#endif
+
+
+
+#if (VS_REALLINKMODE == 1)
+extern VS_VOID volatile const * const vsrl_aVspInfo[];
+extern SEM_CONTEXT * vsrl_aVspContextPointer[];
+#endif
+
+
+
+#ifdef VS_RUNTIME_INFO
+VSRunTimeInfo volatile const VS_RUNTIME_INFO_EXTKW vsRunTimeInfo =
+{
+ VS_SIGNATURE_VERSION,
+ VS_SIGNATURE_CONTENT
+};
+#endif
+
+
+
+#ifdef SE_EXPERTDLL
+static unsigned char _SMP_ReadTP (FILE *pRBF, unsigned long **Pos, unsigned long NbR, unsigned long FPos)
+{
+ unsigned long *p;
+
+ if (FPos)
+ {
+ if ((p = (unsigned long *)malloc (NbR * sizeof (unsigned long))) == NULL)
+ return (SES_MEM_ERR);
+ *Pos = p;
+ if (fseek (pRBF, (long)FPos, SEEK_SET))
+ return (SES_FILE_ERR);
+ if (fread (p, sizeof (unsigned long) * NbR, 1, pRBF) != 1)
+ return (SES_FILE_ERR);
+ }
+ return (SES_OKAY);
+}
+#endif
+
+
+
+static unsigned char _SMP_Connect (SEM_CONTEXT VS_TQ_CONTEXT *Context, void VS_TQ_RULEBASE *VSData)
+{
+ RBH VS_TQ_RULEBASE *pRBH;
+ unsigned char CC;
+
+ pRBH = (RBH VS_TQ_RULEBASE *)VSData;
+ if ((pRBH->IdAndEventGroupType & 0x0FF) != SEM_VERS_ID)
+ goto FileError;
+
+#ifdef SE_EXPERTDLL
+ if (!((pRBH->IdAndEventGroupType >> 12) & 1))
+ goto FileError;
+#endif
+
+ Context->nNofEvents = (SEM_EVENT_TYPE) pRBH->nNofEvents;
+#if (SEM_SIGNAL)
+ Context->nNofSignals = (SEM_EVENT_TYPE) pRBH->nNofSignals;
+ Context->SSize = (SEM_SIGNAL_QUEUE_TYPE) pRBH->SSize;
+#endif
+ Context->nNofStates = (SEM_STATE_TYPE) pRBH->nNofStates;
+ Context->nNofStateMachines = (SEM_STATE_MACHINE_TYPE) pRBH->nNofStateMachines;
+ Context->nNofActionFunctions = (SEM_ACTION_FUNCTION_TYPE) pRBH->nNofActionFunctions;
+ Context->nNofInstances = (SEM_INSTANCE_TYPE) pRBH->nNofInstances;
+ Context->EventGroupType = (unsigned char)((pRBH->IdAndEventGroupType >> 8) & 0x0F);
+
+#if VS_USE_HEAP
+ Context->pCSV = NULL;
+ Context->pWSV = NULL;
+ Context->pIns = NULL;
+#if (SEM_SIGNAL)
+ Context->pSQueue = NULL;
+#endif
+#endif
+ Context->pENIPos = NULL;
+ Context->pSNIPos = NULL;
+ Context->pANIPos = NULL;
+ Context->pEEIPos = NULL;
+ Context->pSEIPos = NULL;
+ Context->pAEIPos = NULL;
+
+#if (SEM_GUARD_EXPRESSION)
+ Context->pGuard = NULL;
+#endif
+#if (SEM_SIGNAL_DB)
+ Context->pSEM_SignalDB = NULL;
+#endif
+
+#if VS_USE_HEAP
+ if (Context->nNofStates)
+ {
+ if (Context->nNofInstances == 1)
+ {
+ if ((Context->pCSV = (SEM_STATE_TYPE *)malloc (sizeof (SEM_STATE_TYPE) * Context->nNofStateMachines)) == NULL)
+ goto MemoryError;
+ }
+ if ((Context->pWSV = (SEM_STATE_TYPE *)malloc (sizeof (SEM_STATE_TYPE) * Context->nNofStateMachines)) == NULL)
+ goto MemoryError;
+ }
+#if (SEM_SIGNAL)
+ if (Context->SSize)
+ {
+ if ((Context->pSQueue = (SEM_EVENT_TYPE *)malloc (sizeof (SEM_EVENT_TYPE) * Context->SSize)) == NULL)
+ goto MemoryError;
+ }
+#endif
+#endif
+
+ if (Context->nNofStates)
+ Context->pSMI = (SEM_STATE_MACHINE_TYPE VS_TQ_RULEBASE *)((char VS_TQ_RULEBASE *)pRBH + pRBH->SMIPos);
+ if (Context->EventGroupType != 0)
+ Context->pEGT = (SEM_EVENT_GROUP_TYPE VS_TQ_RULEBASE *)((char VS_TQ_RULEBASE *)pRBH + pRBH->EGTPos);
+ if (Context->EventGroupType == 2)
+ Context->pEGTI = (SEM_EGTI_TYPE VS_TQ_RULEBASE *)((char VS_TQ_RULEBASE *)pRBH + pRBH->EGTIPos);
+ Context->pRD = (SEM_RULE_DATA_TYPE VS_TQ_RULEBASE *)((char VS_TQ_RULEBASE *)pRBH + pRBH->RDPos);
+ Context->pRI = (SEM_RULE_INDEX_TYPE VS_TQ_RULEBASE *)((char VS_TQ_RULEBASE *)pRBH + pRBH->RIPos);
+ Context->pRTI = (SEM_RULE_TABLE_INDEX_TYPE VS_TQ_RULEBASE *)((char VS_TQ_RULEBASE *)pRBH + pRBH->RTIPos);
+
+ if (!Context->pVSFile)
+ {
+ if (pRBH->ENIPos && pRBH->nNofEvents)
+ Context->pENIPos = (unsigned long VS_TQ_RULEBASE *)((char VS_TQ_RULEBASE *)pRBH + pRBH->ENIPos);
+ if (pRBH->SNIPos && pRBH->nNofStates)
+ Context->pSNIPos = (unsigned long VS_TQ_RULEBASE *)((char VS_TQ_RULEBASE *)pRBH + pRBH->SNIPos);
+ if (pRBH->ANIPos && pRBH->nNofActionFunctions)
+ Context->pANIPos = (unsigned long VS_TQ_RULEBASE *)((char VS_TQ_RULEBASE *)pRBH + pRBH->ANIPos);
+ if (pRBH->EEIPos && pRBH->nNofEvents)
+ Context->pEEIPos = (unsigned long VS_TQ_RULEBASE *)((char VS_TQ_RULEBASE *)pRBH + pRBH->EEIPos);
+ if (pRBH->SEIPos && pRBH->nNofStates)
+ Context->pSEIPos = (unsigned long VS_TQ_RULEBASE *)((char VS_TQ_RULEBASE *)pRBH + pRBH->SEIPos);
+ if (pRBH->AEIPos && pRBH->nNofActionFunctions)
+ Context->pAEIPos = (unsigned long VS_TQ_RULEBASE *)((char VS_TQ_RULEBASE *)pRBH + pRBH->AEIPos);
+ }
+ else
+ {
+#ifndef SE_EXPERTDLL
+ CC = SES_NOT_LOADED;
+ goto CCError;
+#else
+ if ((CC = _SMP_ReadTP (Context->pVSFile, &Context->pENIPos, pRBH->nNofEvents, pRBH->ENIPos)) != SES_OKAY)
+ goto CCError;
+ if ((CC = _SMP_ReadTP (Context->pVSFile, &Context->pSNIPos, pRBH->nNofStates, pRBH->SNIPos)) != SES_OKAY)
+ goto CCError;
+ if ((CC = _SMP_ReadTP (Context->pVSFile, &Context->pANIPos, pRBH->nNofActionFunctions, pRBH->ANIPos)) != SES_OKAY)
+ goto CCError;
+ if ((CC = _SMP_ReadTP (Context->pVSFile, &Context->pEEIPos, pRBH->nNofEvents, pRBH->EEIPos)) != SES_OKAY)
+ goto CCError;
+ if ((CC = _SMP_ReadTP (Context->pVSFile, &Context->pSEIPos, pRBH->nNofStates, pRBH->SEIPos)) != SES_OKAY)
+ goto CCError;
+ if ((CC = _SMP_ReadTP (Context->pVSFile, &Context->pAEIPos, pRBH->nNofActionFunctions, pRBH->AEIPos)) != SES_OKAY)
+ goto CCError;
+#endif
+ }
+ SMP_Init (Context);
+#if (SEM_SIGNAL)
+ SMP_InitSignalQueue (Context);
+#endif
+
+#if (VS_REALLINKMODE == 1)
+ Context->systemNo = (VS_UINT8)((pRBH->IdAndEventGroupType >> 24) & 0x0FF);
+ vsrl_aVspContextPointer[Context->systemNo] = Context;
+#endif
+
+ return (SES_OKAY);
+
+CCError :
+ SMP_Free (Context);
+ return (CC);
+
+#if VS_USE_HEAP
+MemoryError :
+ SMP_Free (Context);
+ return (SES_MEM_ERR);
+#endif
+
+FileError :
+ SMP_Free (Context);
+ return (SES_FILE_ERR);
+}
+
+
+
+unsigned char SMP_Connect (SEM_CONTEXT VS_TQ_CONTEXT **Context, void VS_TQ_RULEBASE *VSData)
+{
+ SEM_CONTEXT VS_TQ_CONTEXT *pCont;
+
+#if VS_USE_HEAP
+ if ((pCont = (SEM_CONTEXT VS_TQ_CONTEXT *)malloc (sizeof (SEM_CONTEXT))) == NULL)
+ return (SES_MEM_ERR);
+#else
+ pCont = *(SEM_CONTEXT VS_TQ_CONTEXT * VS_TQ_RULEBASE *)((char VS_TQ_RULEBASE *)VSData + ((RBH VS_TQ_RULEBASE *)VSData)->contextPtrOffset);
+#endif
+ pCont->pVSData = VSData;
+ pCont->pVSFile = NULL;
+ *Context = pCont;
+ return (_SMP_Connect (pCont, VSData));
+}
+
+
+#ifdef SE_EXPERTDLL
+unsigned char SMP_Load (SEM_CONTEXT VS_TQ_CONTEXT **Context, const char *FileName)
+{
+ FILE *pVSF;
+ RBH RBHe;
+ char *pc;
+ long Bytes;
+ size_t Chunk;
+ SEM_CONTEXT VS_TQ_CONTEXT *pCont;
+
+ if ((pCont = (SEM_CONTEXT VS_TQ_CONTEXT *)malloc (sizeof (SEM_CONTEXT))) == NULL)
+ return (SES_MEM_ERR);
+
+ pCont->pCSV = NULL;
+ pCont->pWSV = NULL;
+ pCont->pIns = NULL;
+#if (SEM_SIGNAL)
+ pCont->pSQueue = NULL;
+#endif
+ pCont->pENIPos = NULL;
+ pCont->pSNIPos = NULL;
+ pCont->pANIPos = NULL;
+ pCont->pEEIPos = NULL;
+ pCont->pSEIPos = NULL;
+ pCont->pAEIPos = NULL;
+
+ pVSF = fopen (FileName, "rb");
+ pCont->pVSFile = pVSF;
+ if (!pVSF)
+ goto FileError;
+ if (fread (&RBHe, sizeof (RBHe), 1, pVSF) != 1)
+ goto FileError;
+ if ((RBHe.IdAndEventGroupType & 0x0FF) != SEM_VERS_ID)
+ goto FileError;
+ if (((RBHe.IdAndEventGroupType >> 16) & 0x0FF) != SEM_RDFM_NUMBER)
+ goto FileError;
+ if (fseek (pVSF, 0L, SEEK_SET))
+ goto FileError;
+
+ Bytes = RBHe.TSPos;
+
+ if ((sizeof(size_t) == sizeof (short)) * (Bytes >> 16))
+ goto MemoryError;
+ if ((pCont->pVSData = (void *)malloc ((size_t)Bytes)) == NULL)
+ goto MemoryError;
+
+ pc = (char *)pCont->pVSData;
+ while (Bytes)
+ {
+ if (Bytes > 0x04000)
+ Chunk = 0x04000;
+ else
+ Chunk = (size_t)Bytes;
+ Bytes -= Chunk;
+ if (fread (pc, Chunk, 1, pVSF) != 1)
+ goto FileError;
+ pc += Chunk;
+ }
+
+ *Context = pCont;
+ return (_SMP_Connect (pCont, pCont->pVSData));
+
+MemoryError:
+ SMP_Free (pCont);
+ return (SES_MEM_ERR);
+
+FileError:
+ SMP_Free (pCont);
+ return (SES_FILE_ERR);
+}
+#endif
+
+
+void SMP_Free (SEM_CONTEXT VS_TQ_CONTEXT *Context)
+{
+ if (!Context)
+ return;
+
+#if (VS_REALLINKMODE == 1)
+ VS_WAIT_ELM(Context, VS_ENABLE_SYSTEM, Ind_SYSTEM_FREE, &Context->systemNo);
+ vsrl_aVspContextPointer[Context->systemNo] = NULL;
+#endif
+
+#if VS_USE_HEAP
+ if (Context->pCSV && Context->nNofInstances == 1)
+ free (Context->pCSV);
+ if (Context->pWSV)
+ free (Context->pWSV);
+ if (Context->pIns)
+ free (Context->pIns);
+#if (SEM_SIGNAL)
+ if (Context->pSQueue)
+ free (Context->pSQueue);
+#endif
+#endif
+#ifdef SE_EXPERTDLL
+ if (Context->pVSFile)
+ {
+ fclose (Context->pVSFile);
+ if (Context->pVSData)
+ free (Context->pVSData);
+ if (Context->pENIPos)
+ free (Context->pENIPos);
+ if (Context->pSNIPos)
+ free (Context->pSNIPos);
+ if (Context->pANIPos)
+ free (Context->pANIPos);
+ if (Context->pEEIPos)
+ free (Context->pEEIPos);
+ if (Context->pSEIPos)
+ free (Context->pSEIPos);
+ if (Context->pAEIPos)
+ free (Context->pAEIPos);
+ }
+#endif
+#if VS_USE_HEAP
+ free (Context);
+#endif
+}
+
+
+unsigned char SMP_Init (SEM_CONTEXT VS_TQ_CONTEXT *Context)
+{
+ SEM_STATE_MACHINE_TYPE i;
+
+#ifdef VS_RUNTIME_INFO
+ *vsRunTimeInfo.pSignatureVersion;
+#endif
+ if (!Context)
+ return (SES_NOT_LOADED);
+ for (i = 0; i < Context->nNofStateMachines; i++)
+ {
+ Context->pWSV[i] = STATE_UNDEFINED;
+ if (Context->nNofInstances == 1)
+ Context->pCSV[i] = STATE_UNDEFINED;
+ }
+ Context->State = STATE_SEM_INITIALIZE;
+ Context->InqAct = VS_FALSE;
+#if (SEM_SIGNAL)
+ Context->SignalStateChg = 0;
+#endif
+ Context->StateChange = VS_FALSE;
+ return (SES_OKAY);
+}
+
+
+#if (SEM_GUARD_EXPRESSION)
+#if (SEM_FUNCEXPHANDLING == 0)
+void SMP_InitGuardCallBack (SEM_CONTEXT VS_TQ_CONTEXT *Context, VS_GUARDEXPR_TYPE VS_TQ_GUARDEXPRCOL * Guard)
+#else
+void SMP_InitGuardCallBack (SEM_CONTEXT VS_TQ_CONTEXT *Context, unsigned char (* Guard)(SEM_CONTEXT VS_TQ_CONTEXT *Context, SEM_GUARD_EXPRESSION_TYPE i))
+#endif
+{
+ Context->pGuard = Guard;
+}
+#endif
+
+
+#if (SEM_SIGNAL_DB)
+void SMP_InitSignalDBCallBack (SEM_CONTEXT VS_TQ_CONTEXT *Context,
+ void (*SEM_SignalDB)(SEM_CONTEXT VS_TQ_CONTEXT *Context, SEM_EVENT_TYPE SignalNo))
+{
+ Context->pSEM_SignalDB = SEM_SignalDB;
+}
+#endif
+
+
+#if (SEM_SIGNAL)
+void SMP_InitSignalQueue (SEM_CONTEXT VS_TQ_CONTEXT *Context)
+{
+ Context->SPut = 0;
+ Context->SGet = 0;
+ Context->SUsed = 0;
+}
+
+
+static unsigned char SMP_SignalQueuePut (SEM_CONTEXT VS_TQ_CONTEXT *Context,
+ SEM_EVENT_TYPE SignalNo)
+{
+ if (Context->SUsed == Context->SSize)
+ return (SES_SIGNAL_QUEUE_FULL);
+ Context->SUsed++;
+ Context->pSQueue[Context->SPut] = SignalNo;
+ if (++Context->SPut == Context->SSize)
+ Context->SPut = 0;
+ return (SES_OKAY);
+}
+
+
+static SEM_EVENT_TYPE SMP_SignalQueueGet (SEM_CONTEXT VS_TQ_CONTEXT *Context)
+{
+ SEM_EVENT_TYPE SignalNo;
+
+ if (!Context->SUsed)
+ return (EVENT_UNDEFINED);
+ Context->SUsed--;
+ SignalNo = Context->pSQueue[Context->SGet];
+
+ if (++Context->SGet == Context->SSize)
+ Context->SGet = 0;
+
+ return (SignalNo);
+}
+#endif
+
+
+unsigned char SMP_Deduct (SEM_CONTEXT VS_TQ_CONTEXT *Context, SEM_EVENT_TYPE EventNo)
+{
+ if (!Context)
+ return (SES_NOT_LOADED);
+ if (Context->nNofEvents <= EventNo)
+ return (SES_RANGE_ERR);
+ Context->EventNo = EventNo;
+ Context->State = STATE_SEM_PREPARE;
+ Context->DIt = 2;
+ if (Context->InqAct)
+ return (SES_ACTIVE);
+
+#if (VS_REALLINKMODE == 1)
+ VS_WAIT_ELM(Context, VS_ENABLE_EVENT, Ind_EVENT, &EventNo);
+#endif
+
+ return (SES_OKAY);
+}
+
+
+unsigned char SMP_GetOutput (SEM_CONTEXT VS_TQ_CONTEXT *Context,
+ SEM_ACTION_EXPRESSION_TYPE *ActionNo)
+{
+ SEM_RULE_DATA_TYPE rd;
+ unsigned char i, nPos, nNxt;
+#if (SEM_RDHW_TYPE_2 || SEM_RDHW_TYPE_3)
+ unsigned char nGuard;
+#endif
+#if (SEM_SIGNAL)
+ unsigned char nSignal;
+#endif
+ SEM_STATE_MACHINE_TYPE m;
+#if (SEM_RMN_NEGATIVE_STATE_SYNCS || defined VISUALSTATE_EXPERT_DLL)
+ unsigned char nNeg;
+ SEM_STATE_TYPE s;
+#endif
+
+ if (!Context)
+ return (SES_NOT_LOADED);
+ for(;;)
+ {
+ switch (Context->State)
+ {
+#if (SEM_SIGNAL)
+ case STATE_SEM_SIGNAL :
+Signal :
+ Context->EventNo = SMP_SignalQueueGet (Context);
+ if (Context->EventNo == EVENT_UNDEFINED)
+ {
+ Context->State = STATE_SEM_OKAY;
+ return (SES_OKAY);
+ }
+#if (SEM_SIGNAL_DB)
+ if (Context->pSEM_SignalDB)
+ (*Context->pSEM_SignalDB) (Context, Context->EventNo);
+#endif
+ for (m = 0; m < Context->nNofStateMachines; m++)
+ {
+ if (Context->pWSV[m] != STATE_UNDEFINED)
+ {
+#ifdef SEM_NEXT_STATE_CHG
+ if (Context->pCSV[m] != Context->pWSV[m])
+ Context->SignalStateChg = 2;
+ else
+#endif
+ Context->SignalStateChg = 1;
+
+ Context->pCSV[m] = Context->pWSV[m];
+ Context->pWSV[m] = STATE_UNDEFINED;
+ }
+ }
+#if (VS_REALLINKMODE == 1)
+ VS_WAIT_ELM(Context, VS_ENABLE_SIGNAL, Ind_SIGNAL, &Context->EventNo);
+#endif
+ goto FirstRule;
+#endif
+ case STATE_SEM_PREPARE :
+#if (SEM_EVENT_GROUP_INDEX) || defined VISUALSTATE_EXPERT_DLL
+ if (Context->EventGroupType == 1)
+ {
+ if (Context->DIt == 1)
+ {
+ Context->EventNo = (SEM_EVENT_TYPE) Context->pEGT[Context->EventNo];
+ if (Context->EventNo == EVENT_UNDEFINED)
+ {
+#if (SEM_SIGNAL)
+ if (Context->nNofSignals != 0)
+ {
+ Context->DIt = 0;
+ goto Signal;
+ }
+ else
+#endif
+ {
+ Context->State = STATE_SEM_OKAY;
+ return (SES_OKAY);
+ }
+ }
+ Context->EventNo = (SEM_EVENT_TYPE) (Context->EventNo + Context->nNofEvents);
+ }
+ else if (Context->DIt == 0)
+ {
+#if (SEM_SIGNAL)
+ if (Context->nNofSignals != 0)
+ goto Signal;
+ else
+#endif
+ {
+ Context->State = STATE_SEM_OKAY;
+ return (SES_OKAY);
+ }
+ }
+ Context->DIt--;
+ }
+#endif
+#if (SEM_EVENT_GROUP_TABLE_INDEX) || defined VISUALSTATE_EXPERT_DLL
+ if (Context->EventGroupType == 2)
+ {
+ if (Context->DIt == 0)
+ {
+ if (++Context->iFirstEgi >= Context->iLastEgi)
+ {
+#if (SEM_SIGNAL)
+ if (Context->nNofSignals != 0)
+ goto Signal;
+ else
+#endif
+ {
+ Context->State = STATE_SEM_OKAY;
+ return (SES_OKAY);
+ }
+ }
+ Context->EventNo = Context->pEGT[Context->iFirstEgi];
+ Context->EventNo = (SEM_EVENT_TYPE) (Context->EventNo + Context->nNofEvents);
+ }
+ else if (Context->DIt == 1)
+ {
+ Context->iFirstEgi = Context->pEGTI[Context->EventNo];
+ Context->iLastEgi = Context->pEGTI[Context->EventNo + 1];
+ if (Context->iFirstEgi == Context->iLastEgi)
+ {
+#if (SEM_SIGNAL)
+ if (Context->nNofSignals != 0)
+ {
+ Context->DIt = 0;
+ goto Signal;
+ }
+ else
+#endif
+ {
+ Context->State = STATE_SEM_OKAY;
+ return (SES_OKAY);
+ }
+ }
+ Context->EventNo = Context->pEGT[Context->iFirstEgi];
+ Context->EventNo = (SEM_EVENT_TYPE) (Context->EventNo + Context->nNofEvents);
+ Context->DIt--;
+ }
+ else if (Context->DIt == 2)
+ {
+ Context->DIt--;
+ }
+ }
+#endif
+#if (SEM_SIGNAL)
+FirstRule :
+#endif
+ Context->iFirstR = Context->pRTI[Context->EventNo];
+ Context->iLastR = Context->pRTI[Context->EventNo + 1];
+ Context->State = STATE_SEM_CONSULT;
+ case STATE_SEM_CONSULT :
+ while (Context->iFirstR < Context->iLastR)
+ {
+ Context->iRI = Context->pRI[Context->iFirstR++];
+#if (SEM_RD_WIDTH_8_BIT && SEM_RDHW_TYPE_1 && SEM_RDHW_WIDTH_16_BIT)
+ rd = Context->pRD[Context->iRI++];
+ nNxt = (unsigned char)(rd & 0x0F);
+ Context->nNofActions = (unsigned char)(rd >> 4);
+ rd = Context->pRD[Context->iRI++];
+ nPos = (unsigned char)(rd & 0x0F);
+#if (SEM_RMN_NEGATIVE_STATE_SYNCS || defined VISUALSTATE_EXPERT_DLL)
+ nNeg = (unsigned char)(rd >> 4);
+#endif
+#endif
+#if (SEM_RD_WIDTH_8_BIT && SEM_RDHW_TYPE_2 && SEM_RDHW_WIDTH_24_BIT)
+ rd = Context->pRD[Context->iRI++];
+ nPos = (unsigned char)(rd & 0x0F);
+#if (SEM_RMN_NEGATIVE_STATE_SYNCS || defined VISUALSTATE_EXPERT_DLL)
+ nNeg = (unsigned char)(rd >> 4);
+#endif
+ rd = Context->pRD[Context->iRI++];
+ nGuard = (unsigned char)(rd & 0x0F);
+ nNxt = (unsigned char)(rd >> 4);
+ rd = Context->pRD[Context->iRI++];
+ Context->nNofActions = (unsigned char)(rd & 0x0F);
+#if (SEM_SIGNAL)
+ nSignal = (unsigned char)(rd >> 4);
+#endif
+#endif
+#if (SEM_RD_WIDTH_8_BIT && SEM_RDHW_TYPE_1 && SEM_RDHW_WIDTH_32_BIT)
+ Context->nNofActions = (unsigned char)Context->pRD[Context->iRI++];
+ nNxt = (unsigned char)Context->pRD[Context->iRI++];
+#if (SEM_RMN_NEGATIVE_STATE_SYNCS || defined VISUALSTATE_EXPERT_DLL)
+ nNeg = (unsigned char)Context->pRD[Context->iRI++];
+#else
+ Context->iRI++;
+#endif
+ nPos = (unsigned char)Context->pRD[Context->iRI++];
+#endif
+#if (SEM_RD_WIDTH_8_BIT && SEM_RDHW_TYPE_2 && SEM_RDHW_WIDTH_48_BIT)
+#if (SEM_RMN_NEGATIVE_STATE_SYNCS || defined VISUALSTATE_EXPERT_DLL)
+ nNeg = (unsigned char)Context->pRD[Context->iRI++];
+#else
+ Context->iRI++;
+#endif
+ nPos = (unsigned char)Context->pRD[Context->iRI++];
+ nNxt = (unsigned char)Context->pRD[Context->iRI++];
+ nGuard = (unsigned char)Context->pRD[Context->iRI++];
+#if (SEM_SIGNAL)
+ nSignal = (unsigned char)Context->pRD[Context->iRI++];
+#else
+ Context->iRI++;
+#endif
+ Context->nNofActions = (unsigned char)Context->pRD[Context->iRI++];
+#endif
+#if (SEM_RD_WIDTH_16_BIT && SEM_RDHW_TYPE_1 && SEM_RDHW_WIDTH_16_BIT)
+ rd = Context->pRD[Context->iRI++];
+ nPos = (unsigned char)(rd & 0x0F);
+#if (SEM_RMN_NEGATIVE_STATE_SYNCS || defined VISUALSTATE_EXPERT_DLL)
+ nNeg = (unsigned char)((rd >> 4) & 0x0F);
+#endif
+ nNxt = (unsigned char)((rd >> 8) & 0x0F);
+ Context->nNofActions = (unsigned char)((rd >> 12) & 0x0F);
+#endif
+#if (SEM_RD_WIDTH_16_BIT && SEM_RDHW_TYPE_3 && SEM_RDHW_WIDTH_32_BIT)
+ rd = Context->pRD[Context->iRI++];
+ nPos = (unsigned char)(rd & 0x0F);
+#if (SEM_RMN_NEGATIVE_STATE_SYNCS || defined VISUALSTATE_EXPERT_DLL)
+ nNeg = (unsigned char)((rd >> 4) & 0x0F);
+#endif
+ nGuard = (unsigned char)((rd >> 8) & 0x0F);
+ nNxt = (unsigned char)(rd >> 12);
+ rd = Context->pRD[Context->iRI++];
+ Context->nNofActions = (unsigned char)(rd & 0x0F);
+#if (SEM_SIGNAL)
+ nSignal = (unsigned char)((rd >> 4) & 0x0F);
+#endif
+#endif
+#if (SEM_RD_WIDTH_16_BIT && SEM_RDHW_TYPE_1 && SEM_RDHW_WIDTH_32_BIT)
+ rd = Context->pRD[Context->iRI++];
+ nNxt = (unsigned char)(rd & 0x0FF);
+ Context->nNofActions = (unsigned char)(rd >> 8);
+ rd = Context->pRD[Context->iRI++];
+ nPos = (unsigned char)(rd & 0x0FF);
+#if (SEM_RMN_NEGATIVE_STATE_SYNCS || defined VISUALSTATE_EXPERT_DLL)
+ nNeg = (unsigned char)(rd >> 8);
+#endif
+#endif
+#if (SEM_RD_WIDTH_16_BIT && SEM_RDHW_TYPE_2 && SEM_RDHW_WIDTH_48_BIT)
+ rd = Context->pRD[Context->iRI++];
+ nPos = (unsigned char)(rd & 0x0FF);
+#if (SEM_RMN_NEGATIVE_STATE_SYNCS || defined VISUALSTATE_EXPERT_DLL)
+ nNeg = (unsigned char)(rd >> 8);
+#endif
+ rd = Context->pRD[Context->iRI++];
+ nGuard = (unsigned char)(rd & 0x0FF);
+ nNxt = (unsigned char)(rd >> 8);
+ rd = Context->pRD[Context->iRI++];
+ Context->nNofActions = (unsigned char)(rd & 0x0FF);
+#if (SEM_SIGNAL)
+ nSignal = (unsigned char)(rd >> 8);
+#endif
+#endif
+#if (SEM_RD_WIDTH_32_BIT && SEM_RDHW_TYPE_1 && SEM_RDHW_WIDTH_32_BIT)
+ rd = Context->pRD[Context->iRI++];
+ nPos = (unsigned char)(rd & 0X0FF);
+#if (SEM_RMN_NEGATIVE_STATE_SYNCS || defined VISUALSTATE_EXPERT_DLL)
+ nNeg = (unsigned char)((rd >> 8) & 0X0FF);
+#endif
+ nNxt = (unsigned char)((rd >> 16) & 0x0FF);
+ Context->nNofActions = (unsigned char)(rd >> 24);
+#endif
+#if (SEM_RD_WIDTH_32_BIT && SEM_RDHW_TYPE_3 && SEM_RDHW_WIDTH_64_BIT)
+ rd = Context->pRD[Context->iRI++];
+ nPos = (unsigned char)(rd & 0x0FF);
+#if (SEM_RMN_NEGATIVE_STATE_SYNCS || defined VISUALSTATE_EXPERT_DLL)
+ nNeg = (unsigned char)((rd >> 8) & 0x0FF);
+#endif
+ nGuard = (unsigned char)((rd >> 16) & 0x0FF);
+ nNxt = (unsigned char)(rd >> 24);
+ rd = Context->pRD[Context->iRI++];
+ Context->nNofActions = (unsigned char)(rd & 0x0FF);
+#if (SEM_SIGNAL)
+ nSignal = (unsigned char)((rd >> 8) & 0x0FF);
+#endif
+#endif
+ for (i = 0; i < nPos; i++)
+ {
+ rd = Context->pRD[Context->iRI++];
+ if (rd != Context->pCSV[Context->pSMI[rd]])
+ goto NextRule;
+ }
+#if (SEM_RMN_NEGATIVE_STATE_SYNCS || defined VISUALSTATE_EXPERT_DLL)
+ for (i = 0; i < nNeg; i++)
+ {
+ rd = Context->pRD[Context->iRI++];
+ s = Context->pCSV[Context->pSMI[rd]];
+ if ((s == STATE_UNDEFINED) || (s == (SEM_STATE_TYPE) rd))
+ goto NextRule;
+ }
+#endif
+#if (SEM_GUARD_EXPRESSION)
+ if (nGuard)
+ {
+ if (Context->pGuard)
+ for (i = 0; i < nGuard; i++)
+#if (SEM_FUNCEXPHANDLING == 0)
+ if ((*Context->pGuard[Context->pRD[Context->iRI++]])(Context) == VS_FALSE)
+#else
+ if ((*Context->pGuard)(Context, (SEM_GUARD_EXPRESSION_TYPE) Context->pRD[Context->iRI++]) == VS_FALSE)
+#endif
+ goto NextRule;
+ }
+#endif
+
+#if (VS_REALLINKMODE == 1)
+ {
+ SEM_RULE_TABLE_INDEX_TYPE ri = Context->iFirstR - 1;
+ VS_WAIT_ELM(Context, VS_ENABLE_TRANS, Ind_TRANS, &ri);
+ }
+#endif
+
+ for (i = 0; i < nNxt; i++)
+ {
+ rd = Context->pRD[Context->iRI++];
+ m = Context->pSMI[rd];
+ if (Context->pWSV[m] == STATE_UNDEFINED)
+ Context->pWSV[m] = (SEM_STATE_TYPE) rd;
+ else if (Context->pWSV[m] != rd)
+ return (SES_CONTRADICTION);
+ }
+#if (SEM_SIGNAL)
+ if (nSignal)
+ {
+ for (i = 0; i < nSignal; i++)
+ {
+ rd = Context->pRD[Context->iRI++];
+#if (SEM_SIGNAL_QUEUE_ERROR_IF_FULL)
+ if (SMP_SignalQueuePut (Context, (SEM_EVENT_TYPE)rd) == SES_SIGNAL_QUEUE_FULL)
+ return (SES_SIGNAL_QUEUE_FULL);
+#endif
+#if (SEM_SIGNAL_QUEUE_NO_ERROR_IF_FULL)
+ SMP_SignalQueuePut (Context, (SEM_EVENT_TYPE)rd);
+#endif
+ }
+ }
+#endif
+ if (Context->nNofActions)
+ {
+ *ActionNo = (SEM_ACTION_EXPRESSION_TYPE)Context->pRD[Context->iRI];
+ if (Context->nNofActions > 1)
+ {
+ Context->iRI++;
+ Context->nNofActions--;
+ Context->State = STATE_SEM_OUTPUT;
+ }
+
+#if (VS_REALLINKMODE == 1)
+ VS_WAIT_ELM(Context, VS_ENABLE_ACTION, Ind_ACTION, ActionNo);
+#endif
+
+ return (SES_FOUND);
+ }
+NextRule :
+ ;
+ }
+#if (SEM_EVENT_GROUP_INDEX || SEM_EVENT_GROUP_TABLE_INDEX) || defined VISUALSTATE_EXPERT_DLL
+ if (Context->EventGroupType != 0)
+ {
+ Context->State = STATE_SEM_PREPARE;
+ break;
+ }
+ else
+ {
+#if (SEM_SIGNAL)
+ if (Context->nNofSignals != 0)
+ goto Signal;
+ else
+#endif
+ {
+ Context->State = STATE_SEM_OKAY;
+ return (SES_OKAY);
+ }
+ }
+#else
+#if (SEM_SIGNAL)
+ if (Context->nNofSignals != 0)
+ goto Signal;
+ else
+#endif
+ {
+ Context->State = STATE_SEM_OKAY;
+ return (SES_OKAY);
+ }
+#endif
+ case STATE_SEM_OUTPUT :
+ if (Context->nNofActions)
+ {
+ *ActionNo = (SEM_ACTION_EXPRESSION_TYPE)Context->pRD[Context->iRI++];
+ Context->nNofActions--;
+
+#if (VS_REALLINKMODE == 1)
+ VS_WAIT_ELM(Context, VS_ENABLE_ACTION, Ind_ACTION, ActionNo);
+#endif
+
+ return (SES_FOUND);
+ }
+ Context->State = STATE_SEM_CONSULT;
+ break;
+ case STATE_SEM_OKAY :
+ return (SES_OKAY);
+ default :
+ return (SES_EMPTY);
+ }
+ }
+}
+
+
+#if defined SEM_GET_OUTPUT_ALL || defined VISUALSTATE_EXPERT_DLL
+#if (SEM_SIGNAL)
+#ifndef VISUALSTATE_EXPERT_DLL
+#error SMP_GetOutputAll cannot be used when the Project contains signals.
+#endif
+#endif
+unsigned char SMP_GetOutputAll (SEM_CONTEXT VS_TQ_CONTEXT *Context,
+ SEM_ACTION_EXPRESSION_TYPE *ActionExprVector,
+ SEM_ACTION_EXPRESSION_TYPE MaxSize)
+{
+ SEM_ACTION_EXPRESSION_TYPE i;
+ unsigned char CC;
+
+ if (!Context)
+ return (SES_NOT_LOADED);
+
+ for (i = 0; ((CC = SMP_GetOutput (Context, &ActionExprVector[i])) == SES_FOUND) && i < MaxSize - 1; i++);
+
+ if (CC == SES_OKAY)
+ {
+ ActionExprVector[i] = ACTION_EXPRESSION_TERMINATION_ID;
+ return (SES_OKAY);
+ }
+ if (CC == SES_FOUND)
+ return (SES_BUFFER_OVERFLOW);
+ return (CC);
+}
+#endif
+
+
+
+#if defined SEM_NEXT_STATE_CHG || defined VISUALSTATE_EXPERT_DLL
+unsigned char _SMP_NextStateChg (SEM_CONTEXT VS_TQ_CONTEXT *Context, unsigned char nextStateChg)
+#else
+unsigned char _SMP_NextStateChg (SEM_CONTEXT VS_TQ_CONTEXT *Context)
+#endif
+{
+ unsigned char CC;
+ SEM_STATE_MACHINE_TYPE i;
+ SEM_ACTION_EXPRESSION_TYPE ActionNo;
+
+ if (!Context)
+ return (SES_NOT_LOADED);
+ if (Context->State != STATE_SEM_OKAY)
+ {
+ while ((CC = SMP_GetOutput (Context, &ActionNo)) == SES_FOUND);
+ if (CC != SES_OKAY)
+ return (CC);
+ }
+ CC = SES_OKAY;
+
+#if (SEM_SIGNAL)
+ if (Context->SignalStateChg != 0)
+ {
+#if defined SEM_NEXT_STATE_CHG || defined VISUALSTATE_EXPERT_DLL
+ if (nextStateChg && Context->SignalStateChg == 2)
+ CC = SES_FOUND;
+#endif
+ Context->StateChange = VS_TRUE;
+ Context->SignalStateChg = 0;
+ }
+ else
+#endif
+ Context->StateChange = VS_FALSE;
+
+ for (i = 0; i < Context->nNofStateMachines; i++)
+ {
+ if (Context->pWSV[i] != STATE_UNDEFINED)
+ {
+#if defined SEM_NEXT_STATE_CHG || defined VISUALSTATE_EXPERT_DLL
+ if (nextStateChg && Context->pCSV[i] != Context->pWSV[i])
+ CC = SES_FOUND;
+#endif
+ Context->pCSV[i] = Context->pWSV[i];
+ Context->pWSV[i] = STATE_UNDEFINED;
+ Context->StateChange = VS_TRUE;
+ }
+ }
+ Context->State = STATE_SEM_INITIALIZE;
+
+ return CC;
+}
diff --git a/cesar/lib/visual_state_api/src/SMPName.c b/cesar/lib/visual_state_api/src/SMPName.c
new file mode 100644
index 0000000000..4562f9573e
--- /dev/null
+++ b/cesar/lib/visual_state_api/src/SMPName.c
@@ -0,0 +1,92 @@
+/*
+ * Type: Source Code File
+ *
+ * Id: SMPName.c
+ *
+ * Function: Contains the SMP_Name SEM Library Expert version 4 function.
+ *
+ * Portability: ANSI-C Compiler.
+ *
+ * Copyright (c) 1999-2006 IAR Systems. All rights reserved.
+ */
+
+/*
+ * Version ! Date ! Status ! Changes
+ *----------------------------------------------------------------------------
+ * 4.0.0.1 ! 101298 ! Closed ! -
+ * 4.0.4 ! 010799 ! Closed ! Minor update, there might be no changes to this particular file.
+ */
+
+#include "SEMLibE.h"
+
+
+unsigned char SMP_Name (SEM_CONTEXT VS_TQ_CONTEXT *Context, unsigned char IdentType,
+ SEM_EXPLANATION_TYPE IdentNo, char *Text, unsigned short MaxSize)
+{
+ int c;
+ unsigned long Pos;
+ unsigned short i;
+ char VS_TQ_RULEBASE * pT = NULL; /* initialization may be necessary to avoid compiler warnings */
+
+ if (!Context)
+ return (SES_NOT_LOADED);
+ if (!MaxSize)
+ return (SES_TEXT_TOO_LONG);
+ switch (IdentType)
+ {
+ case EVENT_TYPE :
+ if (!Context->pENIPos)
+ return (SES_TYPE_ERR);
+ if (Context->nNofEvents <= (SEM_EVENT_TYPE)IdentNo)
+ return (SES_RANGE_ERR);
+ Pos = Context->pENIPos[IdentNo];
+ break;
+ case STATE_TYPE :
+ if (!Context->pSNIPos)
+ return (SES_TYPE_ERR);
+ if (Context->nNofStates <= (SEM_STATE_TYPE)IdentNo)
+ return (SES_RANGE_ERR);
+ Pos = Context->pSNIPos[IdentNo];
+ break;
+ case ACTION_TYPE :
+ if (!Context->pANIPos)
+ return (SES_TYPE_ERR);
+ if (Context->nNofActionFunctions <= (SEM_ACTION_FUNCTION_TYPE)IdentNo)
+ return (SES_RANGE_ERR);
+ Pos = Context->pANIPos[IdentNo];
+ break;
+ default :
+ return (SES_TYPE_ERR);
+ }
+ if (Context->pVSFile)
+ {
+#ifndef SE_EXPERTDLL
+ return (SES_NOT_LOADED);
+#else
+ if (fseek (Context->pVSFile, (long)Pos, SEEK_SET))
+ return (SES_FILE_ERR);
+#endif
+ }
+ else
+ pT = (char VS_TQ_RULEBASE *)((char VS_TQ_RULEBASE *)Context->pVSData + Pos);
+
+ for (i = 0; i < MaxSize; i++)
+ {
+#ifdef SE_EXPERTDLL
+ if (Context->pVSFile)
+ {
+ c = fgetc (Context->pVSFile);
+ if (c == EOF)
+ return (SES_FILE_ERR);
+ }
+ else
+#endif
+ c = *pT++;
+ *Text++ = (char)c;
+ if (c == '\0')
+ return (SES_OKAY);
+ }
+ Text--;
+ *Text = '\0';
+ return (SES_TEXT_TOO_LONG);
+}
diff --git a/cesar/lib/visual_state_api/src/SMPNameA.c b/cesar/lib/visual_state_api/src/SMPNameA.c
new file mode 100644
index 0000000000..f2c50b6d2f
--- /dev/null
+++ b/cesar/lib/visual_state_api/src/SMPNameA.c
@@ -0,0 +1,67 @@
+/*
+ * Type: Source Code File
+ *
+ * Id: SMPNameA.c
+ *
+ * Function: Contains the SMP_NameAbs SEM Library Expert version 4 function.
+ *
+ * Portability: ANSI-C Compiler.
+ *
+ * Copyright (c) 1999-2006 IAR Systems. All rights reserved.
+ */
+
+/*
+ * Version ! Date ! Status ! Changes
+ *----------------------------------------------------------------------------
+ * 4.0.0.1 ! 101298 ! Closed ! -
+ * 4.0.4 ! 010799 ! Closed ! Minor update, there might be no changes to this particular file.
+ */
+
+#include "SEMLibE.h"
+
+
+unsigned char SMP_NameAbs (SEM_CONTEXT VS_TQ_CONTEXT *Context, unsigned char IdentType,
+ SEM_EXPLANATION_TYPE IdentNo, char VS_TQ_RULEBASE **Text)
+{
+ unsigned long Pos;
+
+ if (!Context)
+ return (SES_NOT_LOADED);
+ switch (IdentType)
+ {
+ case EVENT_TYPE :
+ if (!Context->pENIPos)
+ return (SES_TYPE_ERR);
+ if (Context->nNofEvents <= (SEM_EVENT_TYPE)IdentNo)
+ return (SES_RANGE_ERR);
+ Pos = Context->pENIPos[IdentNo];
+ break;
+ case STATE_TYPE :
+ if (!Context->pSNIPos)
+ return (SES_TYPE_ERR);
+ if (Context->nNofStates <= (SEM_STATE_TYPE)IdentNo)
+ return (SES_RANGE_ERR);
+ Pos = Context->pSNIPos[IdentNo];
+ break;
+ case ACTION_TYPE :
+ if (!Context->pANIPos)
+ return (SES_TYPE_ERR);
+ if (Context->nNofActionFunctions <= (SEM_ACTION_FUNCTION_TYPE)IdentNo)
+ return (SES_RANGE_ERR);
+ Pos = Context->pANIPos[IdentNo];
+ break;
+ default :
+ return (SES_TYPE_ERR);
+ }
+ if (Context->pVSFile)
+ {
+#ifndef SE_EXPERTDLL
+ return (SES_NOT_LOADED);
+#else
+ return (SES_NOT_COMPATIBLE);
+#endif
+ }
+ else
+ *Text = (char VS_TQ_RULEBASE *)((char VS_TQ_RULEBASE *)Context->pVSData + Pos);
+ return (SES_OKAY);
+}
diff --git a/cesar/lib/visual_state_api/src/SMPStAll.c b/cesar/lib/visual_state_api/src/SMPStAll.c
new file mode 100644
index 0000000000..318fd74dc5
--- /dev/null
+++ b/cesar/lib/visual_state_api/src/SMPStAll.c
@@ -0,0 +1,36 @@
+/*
+ * Type: Source Code File
+ *
+ * Id: SMPStAll.c
+ *
+ * Function: Contains the SMP_StateAll SEM Library Expert version 4
+ * function.
+ *
+ * Portability: ANSI-C Compiler.
+ *
+ * Copyright (c) 1999-2006 IAR Systems. All rights reserved.
+ */
+
+/*
+ * Version ! Date ! Status ! Changes
+ *----------------------------------------------------------------------------
+ * 4.0.0.0 ! 011198 ! Closed ! -
+ * 4.0.4 ! 010799 ! Closed ! Minor update, there might be no changes to this particular file.
+ */
+
+#include "SEMLibE.h"
+
+
+unsigned char SMP_StateAll (SEM_CONTEXT VS_TQ_CONTEXT *Context,
+ SEM_STATE_TYPE *StateVector, SEM_STATE_MACHINE_TYPE MaxSize)
+{
+ SEM_STATE_MACHINE_TYPE i;
+
+ if (!Context)
+ return (SES_NOT_LOADED);
+ if (Context->nNofStateMachines > MaxSize)
+ return (SES_BUFFER_OVERFLOW);
+ for (i = 0; i < Context->nNofStateMachines; i++)
+ StateVector[i] = Context->pCSV[i];
+ return (SES_FOUND);
+}
diff --git a/cesar/lib/visual_state_api/src/SMPState.c b/cesar/lib/visual_state_api/src/SMPState.c
new file mode 100644
index 0000000000..180000e320
--- /dev/null
+++ b/cesar/lib/visual_state_api/src/SMPState.c
@@ -0,0 +1,32 @@
+/*
+ * Type: Source Code File
+ *
+ * Id: SMPState.c
+ *
+ * Function: Contains the SEM_State SEM Library Expert version 4 function.
+ *
+ * Portability: ANSI-C Compiler.
+ *
+ * Copyright (c) 1999-2006 IAR Systems. All rights reserved.
+ */
+
+/*
+ * Version ! Date ! Status ! Changes
+ *----------------------------------------------------------------------------
+ * 4.0.0.0 ! 011198 ! Closed ! -
+ * 4.0.4 ! 010799 ! Closed ! Minor update, there might be no changes to this particular file.
+ */
+
+#include "SEMLibE.h"
+
+
+unsigned char SMP_State (SEM_CONTEXT VS_TQ_CONTEXT *Context,
+ SEM_STATE_MACHINE_TYPE StateMachineNo, SEM_STATE_TYPE *StateNo)
+{
+ if (!Context)
+ return (SES_NOT_LOADED);
+ if (Context->nNofStateMachines <= StateMachineNo)
+ return (SES_RANGE_ERR);
+ *StateNo = Context->pCSV[StateMachineNo];
+ return (SES_FOUND);
+}