diff --git a/compiler/2014/C_CodeGen.jrag b/compiler/2014/C_CodeGen.jrag
index c4c934b4c30ae30844bd46f627afcac9fbca2573..b4709aab962612e4c2826a46f50925f7ba900d60 100644
--- a/compiler/2014/C_CodeGen.jrag
+++ b/compiler/2014/C_CodeGen.jrag
@@ -1130,11 +1130,34 @@ aspect C_Encoder {
   		    " not declared");
   }
   
+  protected void Decl.C_emitEncoderTypeRegister(C_env env) {
+    env.println("int labcomm"+env.verStr+"_encoder_type_register_" + 
+		env.prefix + getName() + "(");
+    env.indent();
+    env.println("struct labcomm"+env.verStr+"_encoder *e");
+    env.unindent();
+    env.println(")");
+    env.println("{");
+    env.indent();
+    env.println("//TODO: add error handling for dependencies");
+    C_emitUserTypeDeps(env, null, true); //XXX HERE BE DRAGONS
+                                          //currently set to false to turn off
+                                          //outputting of code
+    env.println("return labcomm"+env.verStr+"_internal_encoder_type_register(");
+    env.indent();
+    env.println("e,");
+    env.println("&signature_" + env.prefix + getName() + "");
+    env.unindent();
+    env.println(");");
+    env.unindent();
+    env.println("}");
+  }
   public void TypeDecl.C_emitEncoderRegisterHandler(C_env env) {
-    // do nothing for type decls
+    C_emitEncoderTypeRegister(env);
   }
   
   public void SampleDecl.C_emitEncoderRegisterHandler(C_env env) {
+    C_emitEncoderTypeRegister(env);
     env.println("int labcomm"+env.verStr+"_encoder_register_" + 
 		env.prefix + getName() + "(");
     env.indent();
@@ -1146,17 +1169,23 @@ aspect C_Encoder {
     C_emitUserTypeDeps(env, null, false); //XXX HERE BE DRAGONS
                                           //currently set to false to turn off
                                           //outputting of code
-    env.println("return labcomm"+env.verStr+"_internal_encoder_register(");
+    env.println("int result = labcomm"+env.verStr+"_internal_encoder_register(");
     env.indent();
     env.println("e,");
     env.println("&signature_" + env.prefix + getName() + ",");
     env.println("(labcomm"+env.verStr+"_encoder_function)encode_" + env.prefix + getName());
     env.unindent();
     env.println(");");
+    env.println("labcomm"+env.verStr+"_encoder_type_register_" + env.prefix + getName()+"(e);");
+    env.println("labcomm"+env.verStr+"_internal_encoder_type_bind(");
+    env.indent();
+    env.println("e,");
+    env.println("&signature_" + env.prefix + getName() + ");");
+    env.unindent();
+    env.println("return result;");
     env.unindent();
     env.println("}");
   }
-
 }
 
 aspect C_EncoderIoctl {
@@ -1206,7 +1235,7 @@ aspect C_TypeDependencies {
             t.C_emitUserTypeDeps(env, t.getName(), outputCode);
             if(outputCode) {
                System.out.println("Decl.C_emitUserTypeDeps registering "+t.getName());
-               env.println("labcomm"+env.verStr+"_encoder_register_"+env.prefix + t.getName()+"(e);");
+               env.println("labcomm"+env.verStr+"_encoder_type_register_"+env.prefix + t.getName()+"(e);");
             } else {  // Just output a comment
 	        String refpath = (via == null) ? "directly" : "indirectly via "+via;
 	       env.println(" //Depends ("+refpath+") on "+t.getName() );
@@ -1222,7 +1251,7 @@ aspect C_TypeDependencies {
 
             t.C_emitUserTypeRefs(env, t.getName(), outputCode);
             if(outputCode) {
-               env.println("labcomm"+env.verStr+"_encoder_register_"+env.prefix + t.getName()+"(e);");
+               env.println("labcomm"+env.verStr+"_encoder_type_register_"+env.prefix + t.getName()+"(e);");
             } else {  // Just output a comment
 	        String refpath = (via == null) ? "directly" : "indirectly via "+via;
 	       env.println(" //Is referenced ("+refpath+")  by "+t.getName() );
@@ -1454,9 +1483,9 @@ aspect C_Constructor {
   }
 
   public void Decl.C_emitConstructor(C_env env) {
-  }
+//  }
 //XXX
-  public void SampleDecl.C_emitConstructor(C_env env) {
+//  public void SampleDecl.C_emitConstructor(C_env env) {
     env.println("labcomm"+env.verStr+"_set_local_index(&signature_" + 
 		env.prefix + getName() + ");");
   }
diff --git a/lib/c/2014/Makefile b/lib/c/2014/Makefile
index 6742429773437384c38c06148fc6af2bd9f78dc5..f71c29275557e18c4902a765884bcf67801a1a7d 100644
--- a/lib/c/2014/Makefile
+++ b/lib/c/2014/Makefile
@@ -20,6 +20,7 @@ OBJS=labcomm$(VERSION).o \
      labcomm$(VERSION)_decoder.o \
      labcomm$(VERSION)_dynamic_buffer_writer.o \
      labcomm$(VERSION)_fd_reader.o \
+	 labcomm$(VERSION)_type_signature.o \
      labcomm$(VERSION)_fd_writer.o \
      labcomm$(VERSION)_pthread_scheduler.o 
 
diff --git a/lib/c/2014/labcomm.c b/lib/c/2014/labcomm.c
index a1994aff1ec08e7356295f4d3dcd6d12408e9446..22da2e1ebbf60d41ae96ac8b52682201ff53f8d2 100644
--- a/lib/c/2014/labcomm.c
+++ b/lib/c/2014/labcomm.c
@@ -257,6 +257,11 @@ int labcomm_get_local_index(const struct labcomm_signature *signature)
   return signature->index;
 }
 
+int labcomm_get_local_type_index(const struct labcomm_signature *signature)
+{
+    return labcomm_get_local_index(signature);
+}
+
 int labcomm_internal_sizeof(const struct labcomm_signature *signature,
                             void *v)
 {
diff --git a/lib/c/2014/labcomm.h b/lib/c/2014/labcomm.h
index 5499184b90abf2e49ac392d6bde9b40015d274e5..8018c5b3b18299732848d185ea835bf7baeb3570 100644
--- a/lib/c/2014/labcomm.h
+++ b/lib/c/2014/labcomm.h
@@ -39,59 +39,6 @@
 struct labcomm_encoder;
 struct labcomm_decoder;
 
-/*
- * Signature entry
- */
-#ifndef LABCOMM_NO_TYPEDECL
-#ifdef USE_UNIONS
-
-/* Useful for C99 and up (or GCC without -pedantic) */ 
-
-#define LABCOMM_SIGDEF_BYTES_OR_SIGNATURE          \
-  union {                                   \
-    char *bytes;                            \
-    struct labcomm_signature* signature;            \
-  } u;
-
-#define LABCOMM_SIGDEF_BYTES(l, b) { l, .u.bytes=b }
-#define LABCOMM_SIGDEF_SIGNATURE(s) { 0, .u.signature=&s } // addressof, as s is pointing at the sig struct, not directly the the sig_bytes[]
-#define LABCOMM_SIGDEF_END { -1, .u.bytes=0 }
-
-#else
-
-#define LABCOMM_SIGDEF_BYTES_OR_SIGNATURE          \
-  struct {                                  \
-    char *bytes;                            \
-    const struct labcomm_signature *signature;            \
-  } u;
-
-#define LABCOMM_SIGDEF_BYTES(l, b) { l, { b, 0 } }
-#define LABCOMM_SIGDEF_SIGNATURE(s) { 0, { 0, &s } }
-#define LABCOMM_SIGDEF_END { -1, { 0, 0 } }
-
-#endif
-
-struct labcomm_signature_data {
-  int length;
-  LABCOMM_SIGDEF_BYTES_OR_SIGNATURE
-};
-
-#endif
-struct labcomm_signature {
-  char *name;
-  int (*encoded_size)(void *); /* void* refers to sample_data */
-  int size;
-  unsigned char *signature; 
-  int index;
-#ifndef LABCOMM_NO_TYPEDECL
-  int tdsize;
-  struct labcomm_signature_data *treedata;
-#endif  
-#ifdef LABCOMM_EXPERIMENTAL_CACHED_ENCODED_SIZE
-  int cached_encoded_size; // -1 if not initialized or type is variable size
-#endif
-};
-
 #include "labcomm_type_signature.h"
 /*
  * Error handling.
diff --git a/lib/c/2014/labcomm_decoder.c b/lib/c/2014/labcomm_decoder.c
index 54575ee1eaf7fbb62fecc0dc0427b4696f08cb39..1d3c1f06a2fb77c3796850a7a50aa87e0c11ed0a 100644
--- a/lib/c/2014/labcomm_decoder.c
+++ b/lib/c/2014/labcomm_decoder.c
@@ -374,11 +374,15 @@ int labcomm_decoder_decode_one(struct labcomm_decoder *d)
     result = decode_sample_def_or_ref(d, LABCOMM_SAMPLE_DEF); 
   } else if (remote_index == LABCOMM_SAMPLE_REF) {
     result = decode_sample_def_or_ref(d, LABCOMM_SAMPLE_REF); 
+  } else if (remote_index == LABCOMM_TYPE_DEF) {
+    result = decoder_skip(d, length, remote_index);
+  } else if (remote_index == LABCOMM_TYPE_BINDING) {
+    result = decoder_skip(d, length, remote_index);
   } else if (remote_index == LABCOMM_PRAGMA) {
     result = decode_pragma(d, d, length);
   } else if (remote_index < LABCOMM_USER) {
     fprintf(stderr, "SKIP %d %d\n", remote_index, length);
-    result = remote_index;
+    result = decoder_skip(d, length, remote_index);
   } else {
     result = decode_and_handle(d, d, remote_index);
   }
diff --git a/lib/c/2014/labcomm_encoder.c b/lib/c/2014/labcomm_encoder.c
index 4085bbd38c30a93af55714f54ead443ebaf563a3..f8fd9ae8553b560dde77e3daf526a684823d7e79 100644
--- a/lib/c/2014/labcomm_encoder.c
+++ b/lib/c/2014/labcomm_encoder.c
@@ -24,6 +24,7 @@
 #include "labcomm.h"
 #include "labcomm_private.h"
 #include "labcomm_ioctl.h"
+#include "labcomm_dynamic_buffer_writer.h"
 
 struct labcomm_encoder {
   struct labcomm_writer *writer;
@@ -32,13 +33,15 @@ struct labcomm_encoder {
   struct labcomm_scheduler *scheduler;
   LABCOMM_SIGNATURE_ARRAY_DEF(registered, int);
   LABCOMM_SIGNATURE_ARRAY_DEF(sample_ref, int);
+  LABCOMM_SIGNATURE_ARRAY_DEF(typedefs, int);
 };
 
-struct labcomm_encoder *labcomm_encoder_new(
+static struct labcomm_encoder *internal_encoder_new(
   struct labcomm_writer *writer,
   struct labcomm_error_handler *error,
   struct labcomm_memory *memory,
-  struct labcomm_scheduler *scheduler)
+  struct labcomm_scheduler *scheduler,
+  labcomm_bool outputVer)
 {
   struct labcomm_encoder *result;
 
@@ -58,25 +61,36 @@ struct labcomm_encoder *labcomm_encoder_new(
     result->scheduler = scheduler;
     LABCOMM_SIGNATURE_ARRAY_INIT(result->registered, int);
     LABCOMM_SIGNATURE_ARRAY_INIT(result->sample_ref, int);
+    LABCOMM_SIGNATURE_ARRAY_INIT(result->typedefs, int);
     labcomm_writer_alloc(result->writer,
 			 result->writer->action_context);
-    labcomm_writer_start(result->writer, 
-                         result->writer->action_context, 
-                         LABCOMM_VERSION, NULL, CURRENT_VERSION);
-    labcomm_write_packed32(result->writer, LABCOMM_VERSION);
+    if(outputVer) {
+        labcomm_writer_start(result->writer, 
+                            result->writer->action_context, 
+                            LABCOMM_VERSION, NULL, CURRENT_VERSION);
+        labcomm_write_packed32(result->writer, LABCOMM_VERSION);
 #ifdef LENGTH_INCL_TAG    
-    length = (labcomm_size_packed32(LABCOMM_VERSION) +
-              labcomm_size_string(CURRENT_VERSION));
+        length = (labcomm_size_packed32(LABCOMM_VERSION) +
+                labcomm_size_string(CURRENT_VERSION));
 #else
-    length = labcomm_size_string(CURRENT_VERSION);
+        length = labcomm_size_string(CURRENT_VERSION);
 #endif
-    labcomm_write_packed32(result->writer, length);
-    labcomm_write_string(result->writer, CURRENT_VERSION);
-    labcomm_writer_end(result->writer, result->writer->action_context);
+        labcomm_write_packed32(result->writer, length);
+        labcomm_write_string(result->writer, CURRENT_VERSION);
+        labcomm_writer_end(result->writer, result->writer->action_context);
+    }
   }
   return result;
 }
 
+struct labcomm_encoder *labcomm_encoder_new(
+  struct labcomm_writer *writer,
+  struct labcomm_error_handler *error,
+  struct labcomm_memory *memory,
+  struct labcomm_scheduler *scheduler)
+{
+    return internal_encoder_new(writer,error,memory,scheduler,TRUE);
+}
 void labcomm_encoder_free(struct labcomm_encoder* e)
 {
   struct labcomm_memory *memory = e->memory;
@@ -86,7 +100,219 @@ void labcomm_encoder_free(struct labcomm_encoder* e)
   LABCOMM_SIGNATURE_ARRAY_FREE(e->memory, e->sample_ref, int);
   labcomm_memory_free(memory, 0, e);
 }
+//================
+static struct labcomm_encoder * wrapped_begin(
+                    struct labcomm_encoder *e) {
+    struct labcomm_writer *dyn_writer = labcomm_dynamic_buffer_writer_new(
+                                                 e->memory);
+    struct labcomm_encoder *wrapped = internal_encoder_new(dyn_writer,
+                                                          e->error,
+                                                          e->memory,
+                                                          e->scheduler,
+                                                          FALSE);
+    return wrapped;
+}
+//HERE BE DRAGONS! Copied from decoder.c
+//Should this be moved to private_h?
+static int writer_ioctl(struct labcomm_writer *writer,
+            uint32_t action,
+            ...)
+{
+  int result;
+  va_list va;
+
+  if (LABCOMM_IOC_SIG(action) != LABCOMM_IOC_NOSIG) {
+    result = -EINVAL;
+    goto out;
+  }
+
+  va_start(va, action);
+  result = labcomm_writer_ioctl(writer, writer->action_context,
+                0, NULL, action, va);
+  va_end(va);
+out:
+  return result;
+}
+
+
+int wrapped_end(struct labcomm_encoder *e, int tag, struct labcomm_encoder* wrapped)
+{
+//HERE BE DRAGONS!
+//We assume that the writer is a dynamic_buffer_writer
+  char*  wrapped_data;
+  int err,len;
+  labcomm_writer_end(wrapped->writer, wrapped->writer->action_context);
+  err = writer_ioctl(wrapped->writer,
+             LABCOMM_IOCTL_WRITER_GET_BYTES_WRITTEN,
+             &len);
+  if (err < 0) {
+
+// HERE BE DRAGONS! 
+// What is the difference between error_handler (where is it defined?)
+// and error_handler_callback. And why is the latter only in 
+// the decoder struct?
+//
+//    wrapped->on_error(LABCOMM_ERROR_BAD_WRITER, 2,
+//      "Failed to get size: %s\n", strerror(-err));
+    fprintf(stderr, "BAD WRITER, Failed to get size> %s\n", strerror(-err));
+    err = -ENOENT;
+    goto free_encoder;
+  }
+  err = writer_ioctl(wrapped->writer,
+                 LABCOMM_IOCTL_WRITER_GET_BYTE_POINTER,
+                 &wrapped_data);
+  if (err < 0) {
+//    wrapped->on_error(LABCOMM_ERROR_BAD_WRITER, 2,
+//          "Failed to get pointer: %s\n", strerror(-err));
+    fprintf(stderr, "BAD WRITER, Failed to get pointer> %s\n", strerror(-err));
+    err = -ENOENT;
+    goto free_encoder;
+  }
+  { 
+      int i;
+      err = labcomm_writer_start(e->writer, e->writer->action_context, 
+			     LABCOMM_TYPE_DEF, NULL, NULL);
+      if(err < 0) {
+          goto free_encoder;
+      }
+      labcomm_write_packed32(e->writer, tag);
+      labcomm_write_packed32(e->writer, len);
+      for(i=0; i<len;i++){
+          labcomm_write_byte(e->writer, wrapped_data[i]);
+      }
+      labcomm_writer_end(e->writer, e->writer->action_context);
+      err = e->writer->error;
+  }
+free_encoder:
+  //labcomm_memory_free(wrapped->memory, 1, ctx);  
+  labcomm_encoder_free(wrapped);
+  return err;
+}
+//================
+
+// --------------
+#define TEST_MAP
+
+#ifdef TEST_MAP
+static void write_sig_byte(char b, const struct labcomm_signature *signature,
+                           void *context)
+{
+  struct labcomm_encoder *e = context;
+  if(signature) {
+    labcomm_write_packed32(e->writer, labcomm_get_local_index(signature));
+  }else {
+    if (e->writer->pos >= e->writer->count) {
+     labcomm_writer_flush(e->writer, e->writer->action_context);
+    }
+    e->writer->data[e->writer->pos] = b;
+    e->writer->pos++;
+  }
+}
+#endif
+
+static void do_write_signature(struct labcomm_encoder * e, const struct labcomm_signature *signature, unsigned char flatten)
+{
+#ifdef TEST_MAP
+  map_signature(write_sig_byte, e, signature, flatten);
+#else
+  struct labcomm_signature_data* p = signature->signature;
+  while (p->length != -1) {
+    if (p->length) {
+      int i;
+      for ( i = 0 ; i < p->length ; i++) {
+        if (e->writer->pos >= e->writer->count) {
+         labcomm_writer_flush(e->writer, e->writer->action_context);
+        }
+        e->writer->data[e->writer->pos] = p->u.bytes[i];
+        e->writer->pos++;
+      }
+    } else {
+      if(p->u.signature == 0) printf("p->u.signature == null\n");
+      if(flatten) {
+        do_write_signature(e, p->u.signature, flatten);
+      } else {
+        labcomm_write_packed32(e->writer, labcomm_get_local_index(p->u.signature));
+      }
 
+    }
+    p+=1;
+  }
+#endif
+}
+
+static int internal_reg_type(
+  struct labcomm_encoder *e,
+  const struct labcomm_signature *signature,
+  labcomm_bool flatten)
+{
+  int result = -EINVAL;
+  int index, *done, err;
+  //int i:
+
+  index = labcomm_get_local_index(signature);
+  labcomm_scheduler_writer_lock(e->scheduler);
+  if (index <= 0) { goto out; }
+  done = LABCOMM_SIGNATURE_ARRAY_REF(e->memory, e->typedefs, int, index);
+  if (*done) { goto out; }
+  *done = 1;
+  err = labcomm_writer_start(e->writer, e->writer->action_context,
+                 index, signature, NULL);
+  if (err == -EALREADY) { result = 0; goto out; }
+  if (err != 0) { result = err; goto out; }
+  labcomm_write_packed32(e->writer, index);
+  labcomm_write_string(e->writer, signature->name);
+  //XXX flush for debugging, can be removed when working
+  //    labcomm_writer_flush(e->writer, e->writer->action_context);
+  do_write_signature(e, signature, FALSE);
+//  for (i = 0 ; i < signature->size ; i++) {
+//    if (e->writer->pos >= e->writer->count) {
+//      labcomm_writer_flush(e->writer, e->writer->action_context);
+//    }
+//    e->writer->data[e->writer->pos] = signature->signature[i];
+//    e->writer->pos++;
+//  }
+  labcomm_writer_end(e->writer, e->writer->action_context);
+  result = e->writer->error;
+out:
+  labcomm_scheduler_writer_unlock(e->scheduler);
+  return result;
+}
+//--------------
+int labcomm_internal_encoder_type_register(
+  struct labcomm_encoder *e,
+  const struct labcomm_signature *signature)
+{
+  struct labcomm_encoder *w = wrapped_begin(e);
+  internal_reg_type(w, signature, FALSE);
+  return wrapped_end(e, LABCOMM_TYPE_DEF, w);  
+}
+int labcomm_internal_encoder_type_bind(
+  struct labcomm_encoder *e,
+  const struct labcomm_signature *signature)
+{
+  int result = -EINVAL;
+  int err;
+  int sindex = labcomm_get_local_index(signature);
+  int tindex = labcomm_get_local_type_index(signature);
+  labcomm_scheduler_writer_lock(e->scheduler);
+  if(sindex <= 0 || tindex <= 0) {goto out;}
+  err = labcomm_writer_start(e->writer, e->writer->action_context, 
+			     LABCOMM_TYPE_BINDING, signature, NULL);
+  if (err == -EALREADY) { result = 0; goto out; }
+  if (err != 0) { result = err; goto out; }
+  int length = (labcomm_size_packed32(sindex) +
+                labcomm_size_packed32(tindex)); 
+  labcomm_write_packed32(e->writer, LABCOMM_TYPE_BINDING);
+  labcomm_write_packed32(e->writer, length);
+  labcomm_write_packed32(e->writer, sindex);
+  labcomm_write_packed32(e->writer, tindex);
+  labcomm_writer_end(e->writer, e->writer->action_context);
+  result = e->writer->error;
+
+out:
+  labcomm_scheduler_writer_unlock(e->scheduler);
+  return result;
+}
 int labcomm_internal_encoder_register(
   struct labcomm_encoder *e,
   const struct labcomm_signature *signature,
diff --git a/lib/c/2014/labcomm_private.h b/lib/c/2014/labcomm_private.h
index 95900fe29b81cc282494628737300ba0694d8247..a1792d0877a12e45ba5abbc776474084b62995fa 100644
--- a/lib/c/2014/labcomm_private.h
+++ b/lib/c/2014/labcomm_private.h
@@ -42,8 +42,8 @@
 #define LABCOMM_VERSION      0x01
 #define LABCOMM_SAMPLE_DEF   0x02
 #define LABCOMM_SAMPLE_REF   0x03
-#define LABCOMM_TYPEDEF      0x04
-#define LABCOMM_TYPEBINDING  0x05
+#define LABCOMM_TYPE_DEF     0x04
+#define LABCOMM_TYPE_BINDING 0x05
 #define LABCOMM_PRAGMA       0x3f
 #define LABCOMM_USER         0x40 /* ..0xffffffff */
 
@@ -364,6 +364,14 @@ int labcomm_writer_ioctl(struct labcomm_writer *w,
 			 int index, const struct labcomm_signature *signature, 
 			 uint32_t ioctl_action, va_list args);
 
+int labcomm_internal_encoder_type_register(
+  struct labcomm_encoder *e,
+  const struct labcomm_signature *signature);
+
+int labcomm_internal_encoder_type_bind(
+  struct labcomm_encoder *e,
+  const struct labcomm_signature *signature);
+
 int labcomm_internal_encoder_register(
   struct labcomm_encoder *encoder, 
   const struct labcomm_signature *signature, 
@@ -543,4 +551,6 @@ void labcomm_set_local_index(struct labcomm_signature *signature);
 /* Get the local index for a signature */
 int labcomm_get_local_index(const struct labcomm_signature *s);
 
+int labcomm_get_local_type_index(const struct labcomm_signature *s);
+
 #endif
diff --git a/lib/c/2014/labcomm_type_signature.c b/lib/c/2014/labcomm_type_signature.c
new file mode 100644
index 0000000000000000000000000000000000000000..3cb9cc36e266b32977491b049fea0a1141234f6a
--- /dev/null
+++ b/lib/c/2014/labcomm_type_signature.c
@@ -0,0 +1,128 @@
+#include "labcomm.h"
+#include <string.h>   // for memcmp
+#include <stdio.h>   // for debug printf
+
+/* Dump signature bytes on stdout 
+ */
+
+void labcomm_signature_print(struct labcomm_signature_data *signature)
+{
+  struct labcomm_signature_data *p = signature ;
+  while (p->length != -1) {
+    if (p->length) {
+      int i;
+      for ( i = 0 ; i < p->length ; i++) {
+        printf("%02x ", p->u.bytes[i]);
+      }
+    } else if(p->u.signature){
+      labcomm_signature_print(p->u.signature->treedata);
+    } else {
+      printf("neither data nor ref, bailing out.\n");
+      return;
+    }
+    p+=1;
+  }
+  printf("\n");
+}
+static labcomm_bool sig_dump_checked(struct labcomm_signature_data *signature, 
+                            char *buf, int *len, int buflen);
+
+/* buf (out)   : byte array to write signature into
+   len (in/out): input: buf size, out: signature length
+
+   return TRUE if aborted due to overrun
+ */
+labcomm_bool labcomm_signature_dump(struct labcomm_signature_data *signature, 
+                           char *buf, int *len)
+{
+  int buflen = *len;
+  *len = 0;
+  return sig_dump_checked(signature, buf, len, buflen);
+}
+
+/* internal function with bounds checking for buf.
+ * buflen: capacity of buf
+ */
+static labcomm_bool sig_dump_checked(struct labcomm_signature_data *signature, 
+                            char *buf, int *len, int buflen)
+{
+  struct labcomm_signature_data *p = signature;
+  while ( (p->length != -1) && (*len < buflen)) {
+    if (p->length) {
+      int i;
+      for ( i = 0 ; (i < p->length) && (*len < buflen); i++) {
+        *buf++ = p->u.bytes[i];
+        ++*len;
+      }
+    } else if(p->u.signature){
+      int tmplen=*len;
+      //recursing. c.f. dump()
+      sig_dump_checked(p->u.signature->treedata, buf, len, buflen);
+      int inner_len = *len-tmplen;
+      buf += inner_len;
+    } else {
+      //printf("neither data nor ref, bailing out.\n");
+      return TRUE;
+    }
+    p+=1;
+  }
+  return (*len >= buflen);
+}
+
+/* compare signature (flattened, if needed) to other
+   return TRUE if equal
+*/
+labcomm_bool labcomm_signature_cmp( struct labcomm_signature_data *s1,
+                           struct labcomm_signature_data *s2)
+{
+  int buflen=512;
+  char buf1[buflen];
+  int len1=buflen;
+  char buf2[buflen];
+  int len2=buflen;
+  labcomm_bool res1 = labcomm_signature_dump(s1, buf1, &len1);
+  labcomm_bool res2 = labcomm_signature_dump(s2, buf2, &len2);
+  if(res1 || res2) {
+    printf("WARNING: OVERRUN\n");
+    return FALSE;
+  } else {
+    return(len1 == len2 && memcmp(buf1, buf2, len1)==0);
+  }
+}
+/* maps a function f(char b, struct labcomm_signature *s, void *context) 
+ * on each byte (or type ref) in the signature. 
+ *
+ * If flatten, the signature is flattened to a byte array, and the 
+ * second argument to f is always zero.
+ *
+ * Otherwise, when a type ref is encountered, f is called with the first
+ * argument zero and the referenced type as the second argument.
+ *
+ * The context parameter is passed on, unaltered, to f
+ */ 
+void map_signature( void(*f)(char, const struct labcomm_signature *, void *), 
+                    void *context,
+                    const struct labcomm_signature *signature, labcomm_bool flatten)
+{
+  struct labcomm_signature_data* p = signature->treedata;
+  while (p->length != -1) {
+    //fprintf(stderr, "%p %x\n", p, p->length);
+    if (p->length) {
+      int i;
+      for ( i = 0 ; i < p->length ; i++) {
+        (*f)(p->u.bytes[i], 0, context);
+      }
+    } else if (p->u.signature) {
+      if(p->u.signature == 0) printf("p->u.signature == null\n");
+      if(flatten) {
+        map_signature(f, context, p->u.signature, flatten);
+      } else {
+        (*f)(0, p->u.signature, context);
+      }
+    } else {
+      fprintf(stderr, "neither data nor ref, bailing out.\n");
+      return;
+    }
+    p+=1;
+  }
+}
diff --git a/lib/c/2014/labcomm_type_signature.h b/lib/c/2014/labcomm_type_signature.h
new file mode 100644
index 0000000000000000000000000000000000000000..44549aa0e45e4b0b03e49779817cf99ca836f1ae
--- /dev/null
+++ b/lib/c/2014/labcomm_type_signature.h
@@ -0,0 +1,155 @@
+#ifndef LABCOMM_TYPE_SIGNATURE_H
+#define LABCOMM_TYPE_SIGNATURE_H
+
+//XXX move to common.h
+#ifndef labcomm_bool
+#define labcomm_bool char
+#define TRUE 1
+#define FALSE 0
+#endif
+
+/*
+ * Signature entry
+ */
+#ifndef LABCOMM_NO_TYPEDECL
+#ifdef USE_UNIONS
+
+/* Useful for C99 and up (or GCC without -pedantic) */ 
+
+#define LABCOMM_SIGDEF_BYTES_OR_SIGNATURE          \
+  union {                                   \
+    char *bytes;                            \
+    struct labcomm_signature* signature;            \
+  } u;
+
+#define LABCOMM_SIGDEF_BYTES(l, b) { l, .u.bytes=b }
+#define LABCOMM_SIGDEF_SIGNATURE(s) { 0, .u.signature=&s } // addressof, as s is pointing at the sig struct, not directly the the sig_bytes[]
+#define LABCOMM_SIGDEF_END { -1, .u.bytes=0 }
+
+#else
+
+#define LABCOMM_SIGDEF_BYTES_OR_SIGNATURE          \
+  struct {                                  \
+    char *bytes;                            \
+    const struct labcomm_signature *signature;            \
+  } u;
+
+#define LABCOMM_SIGDEF_BYTES(l, b) { l, { b, 0 } }
+#define LABCOMM_SIGDEF_SIGNATURE(s) { 0, { 0, &s } }
+#define LABCOMM_SIGDEF_END { -1, { 0, 0 } }
+
+#endif
+
+struct labcomm_signature_data {
+  int length;
+  LABCOMM_SIGDEF_BYTES_OR_SIGNATURE
+};
+
+#endif
+struct labcomm_signature {
+  char *name;
+  int (*encoded_size)(void *); /* void* refers to sample_data */
+  int size;
+  unsigned char *signature; 
+  int index;
+#ifndef LABCOMM_NO_TYPEDECL
+  int tdsize;
+  struct labcomm_signature_data *treedata;
+#endif  
+#ifdef LABCOMM_EXPERIMENTAL_CACHED_ENCODED_SIZE
+  int cached_encoded_size; // -1 if not initialized or type is variable size
+#endif
+};
+
+#if 0
+/*
+ * Signature entry
+ */
+
+#ifdef USE_UNIONS
+
+/* Useful for C99 and up (or GCC without -pedantic) */ 
+
+#define LABCOMM_SIGDEF_BYTES_OR_SIGNATURE          \
+  union {                                   \
+    char *bytes;                            \
+    struct labcomm_signature* signature;            \
+  } u;
+
+#define LABCOMM_SIGDEF_BYTES(l, b) { l, .u.bytes=b }
+#define LABCOMM_SIGDEF_SIGNATURE(s) { 0, .u.signature=&s } // addressof, as s is pointing at the sig struct, not directly the the sig_bytes[]
+#define LABCOMM_SIGDEF_END { -1, .u.bytes=0 }
+
+#else
+
+#define LABCOMM_SIGDEF_BYTES_OR_SIGNATURE          \
+  struct {                                  \
+    char *bytes;                            \
+    struct labcomm_signature *signature;            \
+  } u;
+
+#define LABCOMM_SIGDEF_BYTES(l, b) { l, { b, 0 } }
+#define LABCOMM_SIGDEF_SIGNATURE(s) { 0, { 0, &s } }
+#define LABCOMM_SIGDEF_END { -1, { 0, 0 } }
+
+#endif
+
+struct labcomm_signature_data {
+  int length;
+  LABCOMM_SIGDEF_BYTES_OR_SIGNATURE
+};
+
+struct labcomm_signature {
+  int type;
+  char *name;
+  int (*encoded_size)(struct labcomm_signature *, void *); // void * == encoded_sample *
+  struct {
+    int size;
+    unsigned char *data; 
+  } flat;
+  struct {
+    int size;
+    struct labcomm_signature_data *data;
+  } tree;
+  int index;
+#ifdef LABCOMM_EXPERIMENTAL_CACHED_ENCODED_SIZE
+  int cached_encoded_size; // -1 if not initialized or type is variable size
+#endif
+};
+#endif
+/*
+ * functions
+ */
+
+
+/* Dump signature bytes on stdout 
+ */
+
+void labcomm_signature_print(struct labcomm_signature_data *signature);
+
+/* compare signatures (flattened, if needed) to other
+*  return TRUE if equal
+*/
+labcomm_bool labcomm_signature_cmp( struct labcomm_signature_data *s2,
+                           struct labcomm_signature_data *s1);
+
+/* flatten and dump signature to a byte array.
+ * buf (out)   : byte array to write signature into
+ * len (in/out): input: buf size, out: signature length
+ *
+ * return TRUE if aborted due to overrun
+ */
+labcomm_bool labcomm_signature_dump(struct labcomm_signature_data *signature, 
+                           char *buf, int *len);
+
+/* maps function f on each byte in the signature
+ * if flatten, the signature is flattened, and the second argument of
+ * f is always zero
+ * otherwise, when a type ref is encountered, f is called with the first
+ * argument zero and the type ref as the second argument.
+ */ 
+void map_signature( void(*f)(char, const struct labcomm_signature *, void *), 
+                    void *context,
+                    const struct labcomm_signature *signature, labcomm_bool flatten);
+
+#endif