From 8973c6d7e360de81fa25b08d19029f7f60cbb611 Mon Sep 17 00:00:00 2001
From: Anders Blomdell <anders.blomdell@control.lth.se>
Date: Fri, 14 Nov 2014 13:29:10 +0100
Subject: [PATCH] First implementation of sample references, only for C this
 far.

---
 compiler/C_CodeGen.jrag                      |  55 +++++-
 compiler/LabComm.ast                         |   1 +
 compiler/LabComm.java                        |   2 +-
 compiler/LabCommParser.parser                |   5 +
 compiler/LabCommmTokens.jrag                 |  24 +--
 compiler/PrettyPrint.jrag                    |   4 +
 compiler/Signature.jrag                      |   8 +
 examples/twoway/decimating.c                 |   6 +-
 examples/twoway/introspecting.c              |  14 +-
 lib/c/labcomm.c                              |  12 +-
 lib/c/labcomm.h                              |   6 +
 lib/c/labcomm_decoder.c                      | 186 +++++++++++++++----
 lib/c/labcomm_dynamic_buffer_writer.c        |   4 +-
 lib/c/labcomm_encoder.c                      |  64 ++++++-
 lib/c/labcomm_fd_writer.c                    |   2 +-
 lib/c/labcomm_private.h                      |  71 ++++---
 lib/c/test/generated_encoding.lc             |   3 +
 lib/c/test/test_labcomm.c                    |   2 +-
 lib/c/test/test_labcomm_copy.c               |  33 ++++
 lib/c/test/test_labcomm_generated_encoding.c |  43 ++++-
 lib/c/test/test_signature_numbers.c          |   6 +-
 21 files changed, 427 insertions(+), 124 deletions(-)

diff --git a/compiler/C_CodeGen.jrag b/compiler/C_CodeGen.jrag
index 9064f53..7ba35d3 100644
--- a/compiler/C_CodeGen.jrag
+++ b/compiler/C_CodeGen.jrag
@@ -275,6 +275,9 @@ aspect C_Type {
     getType().C_emitType(env, env.prefix + getName());
     env.println(";");
     env.println("#endif");
+    env.println("extern const struct labcomm"+env.verStr+"_signature " +
+                "*labcomm"+env.verStr+"_signature_" + env.prefix + getName() + 
+                ";");
   }
 
   public void Type.C_emitType(C_env env, String name) {
@@ -287,6 +290,10 @@ aspect C_Type {
     env.print("char " + name);
   }
 
+  public void SampleRefType.C_emitType(C_env env, String name) {
+    env.print("const struct labcomm_signature *" + name);
+  }
+
   public void PrimType.C_emitType(C_env env, String name) {
     switch (getToken()) {
       case LABCOMM_BOOLEAN: { env.print("uint8_t"); } break;
@@ -508,6 +515,10 @@ aspect C_Decoder {
   public void VoidType.C_emitDecoder(C_env env) {
   }
 
+  public void SampleRefType.C_emitDecoder(C_env env) {
+    env.println(env.qualid + " = labcomm_internal_decoder_index_to_signature(" +
+                             "r->decoder, labcomm"+env.verStr+"_read_int(r));");
+  }
   public void PrimType.C_emitDecoder(C_env env) {
     env.println(env.qualid + " = labcomm"+env.verStr+"_read_" + getName() + "(r);");
   }
@@ -585,6 +596,9 @@ aspect C_Decoder {
 		    " not declared");
   }
 
+  public void SampleRefType.C_emitDecoderDeallocation(C_env env) {
+  }
+
   public void PrimType.C_emitDecoderDeallocation(C_env env) {
     if (C_isDynamic()) {
       env.println("labcomm"+env.verStr+"_memory_free(r->memory, 1, " + 
@@ -669,7 +683,7 @@ aspect C_Decoder {
     env.println("return labcomm"+env.verStr+"_internal_decoder_register(");
     env.indent();
     env.println("d,");
-    env.println("&labcomm"+env.verStr+"_signature_" + env.prefix + getName() + ",");
+    env.println("&signature_" + env.prefix + getName() + ",");
     env.println("(labcomm"+env.verStr+"_decoder_function)decode_" + env.prefix + getName() + ",");
     env.println("(labcomm"+env.verStr+"_handler_function)handler,");
     env.println("context");
@@ -737,6 +751,12 @@ aspect C_copy {
   public void VoidType.C_emitCopy(C_env env_src, C_env env_dst) {
   }
 
+  public void SampleRefType.C_emitCopy(C_env env_src, C_env env_dst) {
+    env_src.println(env_dst.accessor() + env_dst.qualid + " = " +
+                    env_src.accessor() + env_src.qualid + ";");
+  
+  }
+
   public void PrimType.C_emitCopy(C_env env_src, C_env env_dst) {
     if (C_isDynamic()) {
       env_src.println(String.format(
@@ -880,6 +900,9 @@ aspect C_copy {
   public void VoidType.C_emitCopyDeallocation(C_env env) {
   }
 
+  public void SampleRefType.C_emitCopyDeallocation(C_env env) {
+  }
+
   public void PrimType.C_emitCopyDeallocation(C_env env) {
     if (C_isDynamic()) {
       env.println("labcomm" + env.verStr + "_memory_free(mem, 1, " +
@@ -964,7 +987,7 @@ aspect C_DecoderIoctl {
     env.println("va_start(va, ioctl_action);");
     env.println("result = labcomm"+env.verStr+"_internal_decoder_ioctl(");
     env.indent();
-    env.println("d, &labcomm"+env.verStr+"_signature_" + env.prefix + getName() + ", ");
+    env.println("d, &signature_" + env.prefix + getName() + ", ");
     env.println("ioctl_action, va);");
     env.unindent();
     env.println("va_end(va);");
@@ -1014,7 +1037,7 @@ aspect C_Encoder {
     env.println(")");
     env.println("{");
     env.indent();
-    env.println("return labcomm"+env.verStr+"_internal_encode(e, &labcomm"+env.verStr+"_signature_" + 
+    env.println("return labcomm"+env.verStr+"_internal_encode(e, &signature_" + 
 		env.prefix + getName() + 
 		", (labcomm"+env.verStr+"_encoder_function)encode_" + 
                 env.prefix + getName() +
@@ -1033,6 +1056,13 @@ aspect C_Encoder {
     env.println("result = 0;");
   }
 
+  public void SampleRefType.C_emitEncoder(C_env env) {
+    env.println("result = labcomm"+env.verStr+"_write_int(w, " + 
+                "labcomm_internal_encoder_signature_to_index(w->encoder, " +
+                env.qualid + "));");
+    env.println("if (result != 0) { return result; }");
+  }
+
   public void PrimType.C_emitEncoder(C_env env) {
     env.println("result = labcomm"+env.verStr+"_write_" + getName() + 
                 "(w, " + env.qualid + ");");
@@ -1111,7 +1141,7 @@ aspect C_Encoder {
     env.println("return labcomm"+env.verStr+"_internal_encoder_register(");
     env.indent();
     env.println("e,");
-    env.println("&labcomm"+env.verStr+"_signature_" + env.prefix + getName() + ",");
+    env.println("&signature_" + env.prefix + getName() + ",");
     env.println("(labcomm"+env.verStr+"_encoder_function)encode_" + env.prefix + getName());
     env.unindent();
     env.println(");");
@@ -1147,7 +1177,7 @@ aspect C_EncoderIoctl {
     env.println("va_start(va, ioctl_action);");
     env.println("result = labcomm"+env.verStr+"_internal_encoder_ioctl(");
     env.indent();
-    env.println("e, &labcomm"+env.verStr+"_signature_" + env.prefix + getName() + ", ");
+    env.println("e, &signature_" + env.prefix + getName() + ", ");
     env.println("ioctl_action, va);");
     env.unindent();
     env.println("va_end(va);");
@@ -1189,8 +1219,8 @@ aspect C_Signature {
     }
     env.println("};");
     C_emitSizeofValue(env);
-    env.println("struct labcomm"+env.verStr+"_signature labcomm"+env.verStr+"_signature_" + 
-		env.prefix + getName() + " = {");
+    env.println("static struct labcomm"+env.verStr+"_signature " +
+                "signature_" + env.prefix + getName() + " = {");
     env.indent();
     env.println("\"" + getName() + "\",");
     env.println("sizeof_" + env.prefix + getName() + ",");
@@ -1199,6 +1229,9 @@ aspect C_Signature {
     env.println("0");
     env.unindent();
     env.println(" };");
+    env.println("const struct labcomm"+env.verStr+"_signature " +
+                "*labcomm"+env.verStr+"_signature_" + env.prefix + getName() + 
+                " = &signature_" + env.prefix + getName() + ";");
   }
 
   public void ASTNode.C_emitConstructor(C_env env) {
@@ -1229,7 +1262,7 @@ aspect C_Signature {
   }
 
   public void SampleDecl.C_emitConstructor(C_env env) {
-    env.println("labcomm"+env.verStr+"_set_local_index(&labcomm"+env.verStr+"_signature_" + 
+    env.println("labcomm"+env.verStr+"_set_local_index(&signature_" + 
 		env.prefix + getName() + ");");
   }
 
@@ -1270,7 +1303,7 @@ aspect C_Sizeof {
     env.println("{");
     env.indent();
     env.println("return labcomm"+env.verStr+"_internal_sizeof(" +
-                "&labcomm" + env.verStr+"_signature_" + env.prefix + getName() +
+                "&signature_" + env.prefix + getName() +
                 ", v);");
     env.unindent();
     env.println("}");
@@ -1286,6 +1319,10 @@ aspect C_Sizeof {
     return 0;
   }
 
+  public int SampleRefType.C_fixedSizeof() {
+    return 4;
+  }
+
   public int PrimType.C_fixedSizeof() {
     switch (getToken()) {
       case LABCOMM_BOOLEAN: { return 1; } 
diff --git a/compiler/LabComm.ast b/compiler/LabComm.ast
index 6f290e5..d3b3812 100644
--- a/compiler/LabComm.ast
+++ b/compiler/LabComm.ast
@@ -8,6 +8,7 @@ Field ::= Type <Name:String>;
 
 abstract Type;
 VoidType          : Type;
+SampleRefType     : Type;
 PrimType          : Type ::= <Name:String> <Token:int>;
 UserType          : Type ::= <Name:String>;
 StructType        : Type ::= Field*;
diff --git a/compiler/LabComm.java b/compiler/LabComm.java
index a2250d9..fbb6907 100644
--- a/compiler/LabComm.java
+++ b/compiler/LabComm.java
@@ -33,7 +33,7 @@ public class LabComm {
     println("[ RAPID options ]");
     println(" --rapid                 Generates RAPID code in FILE.sys");
     println("[ Misc options ]");
-    println(" --pretty                Pretty prints on standard output");
+    println(" --pretty=PFILE          Pretty prints to PFILE");
     println(" --typeinfo=TIFILE       Generates typeinfo in TIFILE");
   }
     
diff --git a/compiler/LabCommParser.parser b/compiler/LabCommParser.parser
index dea1194..e885fb2 100644
--- a/compiler/LabCommParser.parser
+++ b/compiler/LabCommParser.parser
@@ -77,6 +77,7 @@ Type type =
   | user_type.u                     {: return u; :}
   | struct_type.s                   {: return s; :}
   | void_type.v                     {: return v; :}
+  | sample_ref_type.s               {: return s; :}
   ;
 
 PrimType prim_type =
@@ -110,6 +111,10 @@ VoidType void_type =
     VOID {: return new VoidType(); :} 
 ;
 
+SampleRefType sample_ref_type = 
+    SAMPLE {: return new SampleRefType(); :} 
+;
+
 List dim_list =
     dim.d                           {: return new List().add(d); :}
   | dim_list.l  dim.d               {: return l.add(d); :}
diff --git a/compiler/LabCommmTokens.jrag b/compiler/LabCommmTokens.jrag
index 351e5b4..69a03b4 100644
--- a/compiler/LabCommmTokens.jrag
+++ b/compiler/LabCommmTokens.jrag
@@ -1,18 +1,18 @@
 aspect LabCommTokens {
 
-  public static final int ASTNode.LABCOMM_TYPEDEF = 0x01;
-  public static final int ASTNode.LABCOMM_SAMPLE =  0x02;
+  public static final int ASTNode.LABCOMM_SAMPLE_DEF = 0x02;
+  public static final int ASTNode.LABCOMM_SAMPLE_REF = 0x03;
 
-  public static final int ASTNode.LABCOMM_ARRAY =   0x10;
-  public static final int ASTNode.LABCOMM_STRUCT =  0x11;
+  public static final int ASTNode.LABCOMM_ARRAY =      0x10;
+  public static final int ASTNode.LABCOMM_STRUCT =     0x11;
 
-  public static final int ASTNode.LABCOMM_BOOLEAN = 0x20; 
-  public static final int ASTNode.LABCOMM_BYTE =    0x21;
-  public static final int ASTNode.LABCOMM_SHORT =   0x22;
-  public static final int ASTNode.LABCOMM_INT =     0x23;
-  public static final int ASTNode.LABCOMM_LONG =    0x24;
-  public static final int ASTNode.LABCOMM_FLOAT =   0x25;
-  public static final int ASTNode.LABCOMM_DOUBLE =  0x26;
-  public static final int ASTNode.LABCOMM_STRING =  0x27;
+  public static final int ASTNode.LABCOMM_BOOLEAN =    0x20; 
+  public static final int ASTNode.LABCOMM_BYTE =       0x21;
+  public static final int ASTNode.LABCOMM_SHORT =      0x22;
+  public static final int ASTNode.LABCOMM_INT =        0x23;
+  public static final int ASTNode.LABCOMM_LONG =       0x24;
+  public static final int ASTNode.LABCOMM_FLOAT =      0x25;
+  public static final int ASTNode.LABCOMM_DOUBLE =     0x26;
+  public static final int ASTNode.LABCOMM_STRING =     0x27;
 
 }
\ No newline at end of file
diff --git a/compiler/PrettyPrint.jrag b/compiler/PrettyPrint.jrag
index 371a76c..a7fa877 100644
--- a/compiler/PrettyPrint.jrag
+++ b/compiler/PrettyPrint.jrag
@@ -68,6 +68,10 @@ aspect PrettyPrint {
     out.print("void");
   }
 
+  public void SampleRefType.ppPrefix(PrintStream out) { 
+    out.print("sample");
+  }
+
   public void PrimType.ppPrefix(PrintStream out) { 
     out.print(getName());
   }
diff --git a/compiler/Signature.jrag b/compiler/Signature.jrag
index 8004f2f..e6c16ac 100644
--- a/compiler/Signature.jrag
+++ b/compiler/Signature.jrag
@@ -134,6 +134,10 @@ aspect Signature {
     list.addInt(0, null);
   }
 
+  public void SampleRefType.flatSignature(SignatureList list) {
+    list.addInt(LABCOMM_SAMPLE_REF, "sample");
+  }
+
   public void PrimType.flatSignature(SignatureList list) {
     list.addInt(getToken(), null);
   }
@@ -200,6 +204,10 @@ aspect Signature {
     return getType().signatureComment() + " '" + getName() +"'";
   }
 
+  public String SampleRefType.signatureComment() {
+    return "sample";
+  }
+
   public String PrimType.signatureComment() {
     return getName();
   }
diff --git a/examples/twoway/decimating.c b/examples/twoway/decimating.c
index 32d1ab0..ea3cfab 100644
--- a/examples/twoway/decimating.c
+++ b/examples/twoway/decimating.c
@@ -106,7 +106,7 @@ static void enqueue_decimation(struct decimating_private *decimating,
 static int wrap_reader_start(
   struct labcomm_reader *r, 
   struct labcomm_reader_action_context *action_context,
-  int local_index, int remote_index, struct labcomm_signature *signature,
+  int local_index, int remote_index, const struct labcomm_signature *signature,
   void *value)
 {
   struct decimating_private *decimating = action_context->context;
@@ -133,7 +133,7 @@ static int wrap_reader_ioctl(
   struct labcomm_reader *r,   
   struct labcomm_reader_action_context *action_context,
   int local_index, int remote_index,
-  struct labcomm_signature *signature, 
+  const struct labcomm_signature *signature, 
   uint32_t action, va_list args)
 {
   struct decimating_private *decimating = action_context->context;
@@ -197,7 +197,7 @@ static int wrap_writer_alloc(
 static int wrap_writer_start(
   struct labcomm_writer *w, 
   struct labcomm_writer_action_context *action_context, 
-  int index, struct labcomm_signature *signature,
+  int index, const struct labcomm_signature *signature,
   void *value)
 {
   struct decimating_private *decimating = action_context->context;
diff --git a/examples/twoway/introspecting.c b/examples/twoway/introspecting.c
index 0f90b2b..3c64c19 100644
--- a/examples/twoway/introspecting.c
+++ b/examples/twoway/introspecting.c
@@ -44,13 +44,13 @@ struct introspecting_private {
   LABCOMM_SIGNATURE_ARRAY_DEF(local, 
 			      struct local {
 				enum introspecting_status status;
-				struct labcomm_signature *signature;
+				const struct labcomm_signature *signature;
 			      });
 };
 
 static struct local *get_local(struct introspecting_private *introspecting,
 			       int index,
-			       struct labcomm_signature *signature)
+			       const struct labcomm_signature *signature)
 {
   /* Called with data_lock held */
   struct local *local;
@@ -137,7 +137,7 @@ static int wrap_reader_alloc(
 struct handles_signature {
   struct introspecting_private *introspecting;
   int index;
-  struct labcomm_signature *signature;
+  const struct labcomm_signature *signature;
 };
 
 static void send_handles_signature(void *arg)
@@ -156,7 +156,7 @@ static void send_handles_signature(void *arg)
 static int wrap_reader_start(
   struct labcomm_reader *r, 
   struct labcomm_reader_action_context *action_context,
-  int local_index, int remote_index, struct labcomm_signature *signature,
+  int local_index, int remote_index, const struct labcomm_signature *signature,
   void *value)
 {
   struct introspecting_private *introspecting = action_context->context;
@@ -180,7 +180,7 @@ static int wrap_reader_start(
   struct labcomm_encoder *encoder,
   void *context)
 {
-  struct labcomm_signature *signature = context;
+  const struct labcomm_signature *signature = context;
   introspecting_messages_handles_signature handles_signature;
   int index = 0;
 
@@ -224,7 +224,7 @@ static int wrap_writer_alloc(
 static int wrap_writer_start(
   struct labcomm_writer *w, 
   struct labcomm_writer_action_context *action_context, 
-  int index, struct labcomm_signature *signature,
+  int index, const struct labcomm_signature *signature,
   void *value)
 {
   struct introspecting_private *introspecting = action_context->context;
@@ -243,7 +243,7 @@ static int wrap_writer_start(
 static int wrap_writer_ioctl(
   struct labcomm_writer *w, 
   struct labcomm_writer_action_context *action_context, 
-  int index, struct labcomm_signature *signature, 
+  int index, const struct labcomm_signature *signature, 
   uint32_t ioctl_action, va_list args)
 {
   struct introspecting_private *introspecting = action_context->context;
diff --git a/lib/c/labcomm.c b/lib/c/labcomm.c
index 416574f..e14a980 100644
--- a/lib/c/labcomm.c
+++ b/lib/c/labcomm.c
@@ -64,7 +64,7 @@ int labcomm_reader_free(struct labcomm_reader *r,
 int labcomm_reader_start(struct labcomm_reader *r, 
                          struct labcomm_reader_action_context *action_context,
 			 int local_index, int remote_index,
-			 struct labcomm_signature *signature,
+			 const struct labcomm_signature *signature,
 			 void *value)
 {
   UNWRAP(start, r, action_context, local_index, remote_index, signature, value);
@@ -85,7 +85,7 @@ int labcomm_reader_fill(struct labcomm_reader *r,
 int labcomm_reader_ioctl(struct labcomm_reader *r, 
                          struct labcomm_reader_action_context *action_context,
                          int local_index, int remote_index,
-                         struct labcomm_signature *signature, 
+                         const struct labcomm_signature *signature, 
                          uint32_t ioctl_action, va_list args)
 {
   UNWRAP(ioctl, r, action_context, 
@@ -106,7 +106,7 @@ int labcomm_writer_free(struct labcomm_writer *w,
 
 int labcomm_writer_start(struct labcomm_writer *w, 
                          struct labcomm_writer_action_context *action_context,
-                         int index, struct labcomm_signature *signature,
+                         int index, const struct labcomm_signature *signature,
                          void *value)
 {
   UNWRAP(start, w, action_context, index, signature, value);
@@ -127,7 +127,7 @@ int labcomm_writer_flush(struct labcomm_writer *w,
 int labcomm_writer_ioctl(struct labcomm_writer *w, 
                          struct labcomm_writer_action_context *action_context, 
                          int index, 
-                         struct labcomm_signature *signature, 
+                         const struct labcomm_signature *signature, 
                          uint32_t ioctl_action, va_list args)
 {
   UNWRAP(ioctl, w, action_context, index, signature, ioctl_action, args);
@@ -250,7 +250,7 @@ void labcomm_set_local_index(struct labcomm_signature *signature)
   local_index++;
 }
 
-int labcomm_get_local_index(struct labcomm_signature *signature)
+int labcomm_get_local_index(const struct labcomm_signature *signature)
 {
   if (signature->index == 0) {
     labcomm_error_fatal_global(LABCOMM_ERROR_SIGNATURE_NOT_SET,
@@ -259,7 +259,7 @@ int labcomm_get_local_index(struct labcomm_signature *signature)
   return signature->index;
 }
 
-int labcomm_internal_sizeof(struct labcomm_signature *signature,
+int labcomm_internal_sizeof(const struct labcomm_signature *signature,
                             void *v)
 {
   int length = signature->encoded_size(v);
diff --git a/lib/c/labcomm.h b/lib/c/labcomm.h
index ce28ac5..5b60299 100644
--- a/lib/c/labcomm.h
+++ b/lib/c/labcomm.h
@@ -119,6 +119,9 @@ int labcomm_decoder_decode_one(
   struct labcomm_decoder *decoder);
 void labcomm_decoder_run(
   struct labcomm_decoder *decoder);
+int labcomm_decoder_sample_ref_register(
+  struct labcomm_decoder *decoder,
+  const struct labcomm_signature *signature);
 
 /* See labcomm_ioctl.h for predefined ioctl_action values */
 int labcomm_decoder_ioctl(struct labcomm_decoder *decoder, 
@@ -137,6 +140,9 @@ struct labcomm_encoder *labcomm_encoder_new(
   struct labcomm_scheduler *scheduler);
 void labcomm_encoder_free(
   struct labcomm_encoder *encoder);
+int labcomm_encoder_sample_ref_register(
+  struct labcomm_encoder *encoder,
+  const struct labcomm_signature *signature);
 
 /* See labcomm_ioctl.h for predefined ioctl_action values */
 int labcomm_encoder_ioctl(struct labcomm_encoder *encoder, 
diff --git a/lib/c/labcomm_decoder.c b/lib/c/labcomm_decoder.c
index 8a3e1ba..234d38e 100644
--- a/lib/c/labcomm_decoder.c
+++ b/lib/c/labcomm_decoder.c
@@ -28,7 +28,7 @@
 
 struct sample_entry {
   int remote_index;
-  struct labcomm_signature *signature;
+  const struct labcomm_signature *signature;
   labcomm_decoder_function decode;
   labcomm_handler_function handler;
   void *context;
@@ -45,6 +45,8 @@ struct labcomm_decoder {
   labcomm_handle_new_datatype_callback on_new_datatype;
   LABCOMM_SIGNATURE_ARRAY_DEF(local, struct sample_entry);
   LABCOMM_SIGNATURE_ARRAY_DEF(remote_to_local, int);
+  LABCOMM_SIGNATURE_ARRAY_DEF(local_ref, const struct labcomm_signature *);
+  LABCOMM_SIGNATURE_ARRAY_DEF(remote_to_local_ref, int);
 };
 
 struct labcomm_decoder *labcomm_decoder_new(
@@ -72,6 +74,9 @@ struct labcomm_decoder *labcomm_decoder_new(
     result->on_error = on_error_fprintf;
     LABCOMM_SIGNATURE_ARRAY_INIT(result->local, struct sample_entry);
     LABCOMM_SIGNATURE_ARRAY_INIT(result->remote_to_local, int);
+    LABCOMM_SIGNATURE_ARRAY_INIT(result->local_ref, 
+                                 const struct labcomm_signature*);
+    LABCOMM_SIGNATURE_ARRAY_INIT(result->remote_to_local_ref, int);
   }
   return result;
 }
@@ -83,17 +88,91 @@ void labcomm_decoder_free(struct labcomm_decoder* d)
   labcomm_reader_free(d->reader, d->reader->action_context);
   LABCOMM_SIGNATURE_ARRAY_FREE(memory, d->local, struct sample_entry);
   LABCOMM_SIGNATURE_ARRAY_FREE(memory, d->remote_to_local, int);
+  LABCOMM_SIGNATURE_ARRAY_FREE(memory, d->local_ref, 
+                               const struct labcomm_signature*);
+  LABCOMM_SIGNATURE_ARRAY_FREE(memory, d->remote_to_local_ref, int);
   labcomm_memory_free(memory, 0, d);
 }
 
-static int decode_sample(struct labcomm_decoder *d, int kind)
+static int handle_sample_def(struct labcomm_decoder *d, int remote_index,
+                             const struct labcomm_signature *signature)
 {
   int result;
-  struct labcomm_signature signature, *local_signature;
-  int remote_index, local_index, i;
-  
-  local_signature = NULL;
-  local_index = 0;
+  int i;
+  const struct labcomm_signature *local_signature = NULL;
+  int local_index = 0;
+
+  labcomm_scheduler_data_lock(d->scheduler);
+  LABCOMM_SIGNATURE_ARRAY_FOREACH(d->local, struct sample_entry, i) {
+    struct sample_entry *s;
+    int *remote_to_local;
+
+    result = -ENOENT;
+    s = LABCOMM_SIGNATURE_ARRAY_REF(d->memory, 
+                                    d->local, struct sample_entry, i);
+    if (s->signature &&
+        s->signature->size == signature->size &&
+        strcmp(s->signature->name, signature->name) == 0 &&
+        memcmp((void*)s->signature->signature, (void*)signature->signature,
+	       signature->size) == 0) {
+      s->remote_index = remote_index;
+      local_signature = s->signature;
+      local_index = i;
+      remote_to_local = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
+                                                    d->remote_to_local, int,
+                                                    remote_index);
+      *remote_to_local = i;
+      result = remote_index;
+      break;
+    }
+  }
+  labcomm_scheduler_data_unlock(d->scheduler);
+  if (local_signature) {
+    labcomm_reader_start(d->reader, d->reader->action_context,
+                         local_index, remote_index, local_signature,
+                         NULL);
+    labcomm_reader_end(d->reader, d->reader->action_context);
+  }
+  return result;
+}
+
+static int handle_sample_ref(struct labcomm_decoder *d, int remote_index,
+                             const struct labcomm_signature *signature)
+{
+  int result;
+  int i;
+
+  labcomm_scheduler_data_lock(d->scheduler);
+  LABCOMM_SIGNATURE_ARRAY_FOREACH(d->local_ref, const struct labcomm_signature *, i) {
+    const struct labcomm_signature *s;
+    int *remote_to_local_ref;
+
+    result = -ENOENT;
+    s = LABCOMM_SIGNATURE_ARRAY_GET(d->local_ref, const struct labcomm_signature *, i, 0);
+    if (s &&
+        s->signature &&
+        s->size == signature->size &&
+        strcmp(s->name, signature->name) == 0 &&
+        memcmp((void*)s->signature, (void*)signature->signature, signature->size) == 0) {
+      remote_to_local_ref = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
+                                                        d->remote_to_local_ref, int,
+                                                        remote_index);
+      *remote_to_local_ref = i;
+      result = remote_index;
+      break;
+    }
+  }
+  labcomm_scheduler_data_unlock(d->scheduler);
+  return result;
+}
+
+
+static int decode_sample_def_or_ref(struct labcomm_decoder *d, int kind)
+{
+  int result;
+  struct labcomm_signature signature;
+  int i, remote_index;
+
   remote_index = labcomm_read_packed32(d->reader);
   if (d->reader->error < 0) {
     result = d->reader->error;
@@ -121,36 +200,16 @@ static int decode_sample(struct labcomm_decoder *d, int kind)
       goto free_signature_signature;
     }
   }
-  labcomm_scheduler_data_lock(d->scheduler);
-  LABCOMM_SIGNATURE_ARRAY_FOREACH(d->local, struct sample_entry, i) {
-    struct sample_entry *s;
-    int *remote_to_local;
-      
-    result = -ENOENT;
-    s = LABCOMM_SIGNATURE_ARRAY_REF(d->memory, 
-				      d->local,  struct sample_entry, i);
-    if (s->signature &&
-        s->signature->size == signature.size &&
-        strcmp(s->signature->name, signature.name) == 0 &&
-        memcmp((void*)s->signature->signature, (void*)signature.signature,
-	       signature.size) == 0) {
-      s->remote_index = remote_index;
-      local_signature = s->signature;
-      local_index = i;
-      remote_to_local = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
-                                                    d->remote_to_local, int,
-                                                    remote_index);
-      *remote_to_local = i;
-      result = remote_index;
-      break;
+  if (kind == LABCOMM_SAMPLE_DEF) {
+    result = handle_sample_def(d, remote_index, &signature);
+  } else if (kind == LABCOMM_SAMPLE_REF) {
+    result = handle_sample_ref(d, remote_index, &signature);
+    if (result == -ENOENT) {
+      /* Dummy value to silently continue */
+      result = LABCOMM_SAMPLE_REF;
     }
-  }
-  labcomm_scheduler_data_unlock(d->scheduler);
-  if (local_signature) {
-    labcomm_reader_start(d->reader, d->reader->action_context,
-                         local_index, remote_index, local_signature,
-                         NULL);
-    labcomm_reader_end(d->reader, d->reader->action_context);
+  } else {
+    result = -EINVAL;
   }
 free_signature_signature:
   labcomm_memory_free(d->memory, 1,  signature.signature);
@@ -164,7 +223,7 @@ struct call_handler_context {
   struct labcomm_reader *reader;
   int local_index;
   int remote_index;
-  struct labcomm_signature *signature;
+  const struct labcomm_signature *signature;
   labcomm_handler_function handler;
   void *context;
 };
@@ -221,8 +280,10 @@ int labcomm_decoder_decode_one(struct labcomm_decoder *d)
   } else if (! d->version_ok) {
     fprintf(stderr, "No VERSION %d %d\n", remote_index, length);
     result = -ECONNRESET;
-  } else if (remote_index == LABCOMM_SAMPLE) {
-    result = decode_sample(d, remote_index); 
+  } else if (remote_index == LABCOMM_SAMPLE_DEF) {
+    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_PRAGMA && 0 /* d->pragma_handler*/) {
     /* d->prama_handler(...); */
   } else if (remote_index < LABCOMM_USER) {
@@ -291,8 +352,34 @@ int labcomm_decoder_ioctl(struct labcomm_decoder *d,
   return result;
 }
 
+int labcomm_decoder_sample_ref_register(
+  struct labcomm_decoder *d,
+  const struct labcomm_signature *signature)
+{
+  int local_index, *remote_to_local_ref;
+  const struct labcomm_signature **s;
+
+  local_index = labcomm_get_local_index(signature);
+  if (local_index <= 0) { goto out; }
+  labcomm_scheduler_data_lock(d->scheduler);
+  s = LABCOMM_SIGNATURE_ARRAY_REF(d->memory, 
+                                  d->local_ref, 
+                                  const struct labcomm_signature*, local_index);
+  if (s == NULL) { local_index = -ENOMEM; goto unlock; };
+  if (*s) { goto unlock; }
+  *s = signature;	
+  remote_to_local_ref = LABCOMM_SIGNATURE_ARRAY_REF(d->memory, 
+                                                    d->remote_to_local_ref, 
+                                                    int, local_index);
+  *remote_to_local_ref = 0;
+unlock:
+  labcomm_scheduler_data_unlock(d->scheduler);
+out:
+  return local_index;
+}
+
 int labcomm_internal_decoder_ioctl(struct labcomm_decoder *d, 
-				   struct labcomm_signature *signature,
+				   const struct labcomm_signature *signature,
 				   uint32_t action, va_list va)
 {
   int result;
@@ -313,7 +400,7 @@ int labcomm_internal_decoder_ioctl(struct labcomm_decoder *d,
 
 int labcomm_internal_decoder_register(
   struct labcomm_decoder *d,
-  struct labcomm_signature *signature,
+  const struct labcomm_signature *signature,
   labcomm_decoder_function decode, 
   labcomm_handler_function handler,
   void *context)
@@ -345,3 +432,20 @@ out:
   return local_index;
 }
 
+const struct labcomm_signature *labcomm_internal_decoder_index_to_signature(
+  struct labcomm_decoder *d, int index)
+{
+  const struct labcomm_signature *result = 0;
+  int local_index;
+
+  labcomm_scheduler_data_lock(d->scheduler);
+  local_index = LABCOMM_SIGNATURE_ARRAY_GET(d->remote_to_local_ref, 
+                                            int, index, 0);
+  if (local_index) {
+    result = LABCOMM_SIGNATURE_ARRAY_GET(d->local_ref, 
+                                         const struct labcomm_signature*, 
+                                         local_index, 0);
+  }
+  labcomm_scheduler_data_unlock(d->scheduler);
+  return result;
+}
diff --git a/lib/c/labcomm_dynamic_buffer_writer.c b/lib/c/labcomm_dynamic_buffer_writer.c
index 8a9b6d1..32501e1 100644
--- a/lib/c/labcomm_dynamic_buffer_writer.c
+++ b/lib/c/labcomm_dynamic_buffer_writer.c
@@ -56,7 +56,7 @@ static int dyn_free(struct labcomm_writer *w,
 static int dyn_start(struct labcomm_writer *w, 
 		     struct labcomm_writer_action_context *action_context,
 		     int index,
-		     struct labcomm_signature *signature,
+		     const struct labcomm_signature *signature,
 		     void *value)
 {
   void *tmp;
@@ -103,7 +103,7 @@ static int dyn_flush(struct labcomm_writer *w,
 static int dyn_ioctl(struct labcomm_writer *w, 
 		     struct labcomm_writer_action_context *action_context, 
 		     int signature_index,
-		     struct labcomm_signature *signature,
+		     const struct labcomm_signature *signature,
 		     uint32_t action, va_list arg)
 {
   int result = -ENOTSUP;
diff --git a/lib/c/labcomm_encoder.c b/lib/c/labcomm_encoder.c
index 5526421..1318e5a 100644
--- a/lib/c/labcomm_encoder.c
+++ b/lib/c/labcomm_encoder.c
@@ -31,6 +31,7 @@ struct labcomm_encoder {
   struct labcomm_memory *memory;
   struct labcomm_scheduler *scheduler;
   LABCOMM_SIGNATURE_ARRAY_DEF(registered, int);
+  LABCOMM_SIGNATURE_ARRAY_DEF(sample_ref, int);
 };
 
 struct labcomm_encoder *labcomm_encoder_new(
@@ -56,6 +57,7 @@ struct labcomm_encoder *labcomm_encoder_new(
     result->memory = memory;
     result->scheduler = scheduler;
     LABCOMM_SIGNATURE_ARRAY_INIT(result->registered, int);
+    LABCOMM_SIGNATURE_ARRAY_INIT(result->sample_ref, int);
     labcomm_writer_alloc(result->writer,
 			 result->writer->action_context);
     labcomm_writer_start(result->writer, 
@@ -77,12 +79,13 @@ void labcomm_encoder_free(struct labcomm_encoder* e)
 
   labcomm_writer_free(e->writer, e->writer->action_context);
   LABCOMM_SIGNATURE_ARRAY_FREE(e->memory, e->registered, int);
+  LABCOMM_SIGNATURE_ARRAY_FREE(e->memory, e->sample_ref, int);
   labcomm_memory_free(memory, 0, e);
 }
 
 int labcomm_internal_encoder_register(
   struct labcomm_encoder *e,
-  struct labcomm_signature *signature,
+  const struct labcomm_signature *signature,
   labcomm_encoder_function encode)
 {
   int result = -EINVAL;
@@ -98,7 +101,7 @@ int labcomm_internal_encoder_register(
 			     index, signature, NULL);
   if (err == -EALREADY) { result = 0; goto out; }
   if (err != 0) { result = err; goto out; }
-  labcomm_write_packed32(e->writer, LABCOMM_SAMPLE);
+  labcomm_write_packed32(e->writer, LABCOMM_SAMPLE_DEF);
   length = (labcomm_size_packed32(index) +
             labcomm_size_string(signature->name) +
             labcomm_size_packed32(signature->size) +
@@ -123,7 +126,7 @@ out:
 
 int labcomm_internal_encode(
   struct labcomm_encoder *e,
-  struct labcomm_signature *signature,
+  const struct labcomm_signature *signature,
   labcomm_encoder_function encode,
   void *value)
 {
@@ -147,6 +150,47 @@ no_end:
   return result;
 }
 
+int labcomm_encoder_sample_ref_register(
+  struct labcomm_encoder *e,
+  const struct labcomm_signature *signature)
+{
+  int result = -EINVAL;
+  int index, *done, err, i, length;
+
+  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->sample_ref, 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, LABCOMM_SAMPLE_REF);
+  length = (labcomm_size_packed32(index) +
+            labcomm_size_string(signature->name) +
+            labcomm_size_packed32(signature->size) +
+            signature->size);
+  labcomm_write_packed32(e->writer, length);
+  labcomm_write_packed32(e->writer, index);
+  labcomm_write_string(e->writer, signature->name);
+  labcomm_write_packed32(e->writer, signature->size);
+  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_encoder_ioctl(struct labcomm_encoder *encoder, 
 			  uint32_t action,
 			  ...)
@@ -170,7 +214,7 @@ out:
 }
 
 int labcomm_internal_encoder_ioctl(struct labcomm_encoder *encoder, 
-				   struct labcomm_signature *signature,
+				   const struct labcomm_signature *signature,
 				   uint32_t action, va_list va)
 {
   int result = -ENOTSUP;
@@ -182,3 +226,15 @@ int labcomm_internal_encoder_ioctl(struct labcomm_encoder *encoder,
 				index, signature, action, va);
   return result;
 }
+
+int labcomm_internal_encoder_signature_to_index(
+  struct labcomm_encoder *e, const struct labcomm_signature *signature)
+{
+  /* writer_lock should be held at this point */
+  int index = labcomm_get_local_index(signature);
+  if (! LABCOMM_SIGNATURE_ARRAY_GET(e->sample_ref, int, index, 0)) {
+    index = 0;
+  }
+  return index;
+}
+
diff --git a/lib/c/labcomm_fd_writer.c b/lib/c/labcomm_fd_writer.c
index a395c54..5833acc 100644
--- a/lib/c/labcomm_fd_writer.c
+++ b/lib/c/labcomm_fd_writer.c
@@ -79,7 +79,7 @@ static int fd_free(struct labcomm_writer *w,
 static int fd_start(struct labcomm_writer *w, 
 		    struct labcomm_writer_action_context *action_context,
 		    int index,
-		    struct labcomm_signature *signature,
+		    const struct labcomm_signature *signature,
 		    void *value)
 {
   w->pos = 0;
diff --git a/lib/c/labcomm_private.h b/lib/c/labcomm_private.h
index 1ba35c7..3079a59 100644
--- a/lib/c/labcomm_private.h
+++ b/lib/c/labcomm_private.h
@@ -39,29 +39,30 @@
 /*
  * Allowed packet tags
  */
-#define LABCOMM_VERSION  0x01
-#define LABCOMM_SAMPLE   0x02
-#define LABCOMM_PRAGMA   0x3f
-#define LABCOMM_USER     0x40 /* ..0xffffffff */
+#define LABCOMM_VERSION      0x01
+#define LABCOMM_SAMPLE_DEF   0x02
+#define LABCOMM_SAMPLE_REF   0x03
+#define LABCOMM_PRAGMA       0x3f
+#define LABCOMM_USER         0x40 /* ..0xffffffff */
 
 
 /*
  * Predefined aggregate type indices
  */
-#define LABCOMM_ARRAY    0x10
-#define LABCOMM_STRUCT   0x11
+#define LABCOMM_ARRAY        0x10
+#define LABCOMM_STRUCT       0x11
 
 /*
  * Predefined primitive type indices
  */
-#define LABCOMM_BOOLEAN  0x20 
-#define LABCOMM_BYTE     0x21
-#define LABCOMM_SHORT    0x22
-#define LABCOMM_INT      0x23
-#define LABCOMM_LONG     0x24
-#define LABCOMM_FLOAT    0x25
-#define LABCOMM_DOUBLE   0x26
-#define LABCOMM_STRING   0x27
+#define LABCOMM_BOOLEAN      0x20 
+#define LABCOMM_BYTE         0x21
+#define LABCOMM_SHORT        0x22
+#define LABCOMM_INT          0x23
+#define LABCOMM_LONG         0x24
+#define LABCOMM_FLOAT        0x25
+#define LABCOMM_DOUBLE       0x26
+#define LABCOMM_STRING       0x27
 
 
 /*
@@ -127,7 +128,7 @@ struct labcomm_reader_action {
   int (*start)(struct labcomm_reader *r, 
 	       struct labcomm_reader_action_context *action_context,
 	       int local_index, int remote_index,
-	       struct labcomm_signature *signature,
+	       const struct labcomm_signature *signature,
 	       void *value);
   int (*end)(struct labcomm_reader *r, 
 	     struct labcomm_reader_action_context *action_context);
@@ -136,7 +137,7 @@ struct labcomm_reader_action {
   int (*ioctl)(struct labcomm_reader *r, 
 	       struct labcomm_reader_action_context *action_context,
 	       int local_index, int remote_index,
-	       struct labcomm_signature *signature, 
+	       const struct labcomm_signature *signature, 
 	       uint32_t ioctl_action, va_list args);
 };
 
@@ -165,7 +166,7 @@ int labcomm_reader_free(struct labcomm_reader *r,
 int labcomm_reader_start(struct labcomm_reader *r, 
 			 struct labcomm_reader_action_context *action_context,
 			 int local_index, int remote_index,
-			 struct labcomm_signature *signature,
+			 const struct labcomm_signature *signature,
 			 void *value);
 int labcomm_reader_end(struct labcomm_reader *r, 
 		       struct labcomm_reader_action_context *action_context);
@@ -174,7 +175,7 @@ int labcomm_reader_fill(struct labcomm_reader *r,
 int labcomm_reader_ioctl(struct labcomm_reader *r, 
 			 struct labcomm_reader_action_context *action_context,
 			 int local_index, int remote_index,
-			 struct labcomm_signature *signature, 
+			 const struct labcomm_signature *signature, 
 			 uint32_t ioctl_action, va_list args);
 
 /*
@@ -183,15 +184,18 @@ int labcomm_reader_ioctl(struct labcomm_reader *r,
  */
 int labcomm_internal_decoder_register(
   struct labcomm_decoder *d, 
-  struct labcomm_signature *s, 
+  const struct labcomm_signature *s, 
   labcomm_decoder_function decoder,
   labcomm_handler_function handler,
   void *context);
 
 int labcomm_internal_decoder_ioctl(struct labcomm_decoder *decoder, 
-				   struct labcomm_signature *signature,
+				   const struct labcomm_signature *signature,
 				   uint32_t ioctl_action, va_list args);
 
+const struct labcomm_signature *labcomm_internal_decoder_index_to_signature(
+  struct labcomm_decoder *decoder, int index);
+
 #if __BYTE_ORDER == __LITTLE_ENDIAN
 
 #define LABCOMM_DECODE(name, type)					\
@@ -312,7 +316,7 @@ struct labcomm_writer_action {
    */
   int (*start)(struct labcomm_writer *w, 
 	       struct labcomm_writer_action_context *action_context,
-	       int index, struct labcomm_signature *signature,
+	       int index, const struct labcomm_signature *signature,
 	       void *value);
   int (*end)(struct labcomm_writer *w, 
 	     struct labcomm_writer_action_context *action_context);
@@ -320,7 +324,7 @@ struct labcomm_writer_action {
 	       struct labcomm_writer_action_context *action_context); 
   int (*ioctl)(struct labcomm_writer *w, 
 	       struct labcomm_writer_action_context *action_context, 
-	       int index, struct labcomm_signature *signature, 
+	       int index, const struct labcomm_signature *signature, 
 	       uint32_t ioctl_action, va_list args);
 };
 
@@ -348,7 +352,7 @@ int labcomm_writer_free(struct labcomm_writer *w,
 			struct labcomm_writer_action_context *action_context);
 int labcomm_writer_start(struct labcomm_writer *w, 
 			 struct labcomm_writer_action_context *action_context,
-			 int index, struct labcomm_signature *signature,
+			 int index, const struct labcomm_signature *signature,
 			 void *value);
 int labcomm_writer_end(struct labcomm_writer *w, 
 		       struct labcomm_writer_action_context *action_context);
@@ -356,27 +360,31 @@ int labcomm_writer_flush(struct labcomm_writer *w,
 			 struct labcomm_writer_action_context *action_context); 
 int labcomm_writer_ioctl(struct labcomm_writer *w, 
 			 struct labcomm_writer_action_context *action_context, 
-			 int index, struct labcomm_signature *signature, 
+			 int index, const struct labcomm_signature *signature, 
 			 uint32_t ioctl_action, va_list args);
 
 int labcomm_internal_encoder_register(
   struct labcomm_encoder *encoder, 
-  struct labcomm_signature *signature, 
+  const struct labcomm_signature *signature, 
   labcomm_encoder_function encode);
 
 int labcomm_internal_encode(
   struct labcomm_encoder *encoder, 
-  struct labcomm_signature *signature, 
+  const struct labcomm_signature *signature, 
   labcomm_encoder_function encode,
   void *value);
 
 int labcomm_internal_encoder_ioctl(struct labcomm_encoder *encoder, 
-				   struct labcomm_signature *signature,
+				   const struct labcomm_signature *signature,
 				   uint32_t ioctl_action, va_list args);
 
-int labcomm_internal_sizeof(struct labcomm_signature *signature,
+int labcomm_internal_encoder_signature_to_index(
+  struct labcomm_encoder *encoder, const struct labcomm_signature *signature);
+
+int labcomm_internal_sizeof(const struct labcomm_signature *signature,
                             void *v);
 
+
 #if __BYTE_ORDER == __LITTLE_ENDIAN
 
 #define LABCOMM_ENCODE(name, type)					\
@@ -519,6 +527,11 @@ void *labcomm_signature_array_ref(struct labcomm_memory * memory,
 					(void **)&name.data,		\
 					sizeof(kind), index)))
 
+#define LABCOMM_SIGNATURE_ARRAY_GET(name, kind, index, nomatch)         \
+  (name.data = (kind *)name.data, /* typechecking no-op */		\
+   (name.first <= index &&                                              \
+    index < name.last) ? name.data[index - name.first] : nomatch)
+
 #define LABCOMM_SIGNATURE_ARRAY_FOREACH(name, kind, var)		\
   for (name.data = (kind *)name.data, /* typechecking no-op */		\
        var = name.first ; var < name.last ; var++)
@@ -527,6 +540,6 @@ void *labcomm_signature_array_ref(struct labcomm_memory * memory,
 void labcomm_set_local_index(struct labcomm_signature *signature);
 
 /* Get the local index for a signature */
-int labcomm_get_local_index(struct labcomm_signature *s);
+int labcomm_get_local_index(const struct labcomm_signature *s);
 
 #endif
diff --git a/lib/c/test/generated_encoding.lc b/lib/c/test/generated_encoding.lc
index f1f4b9b..e561abe 100644
--- a/lib/c/test/generated_encoding.lc
+++ b/lib/c/test/generated_encoding.lc
@@ -5,3 +5,6 @@ sample struct {
 } S1;
 sample int I[_];
 sample struct { int i; } P[_];
+sample void UnusedE;
+sample void UnusedD;
+sample sample R[4];
diff --git a/lib/c/test/test_labcomm.c b/lib/c/test/test_labcomm.c
index 4d158a6..0e60909 100644
--- a/lib/c/test/test_labcomm.c
+++ b/lib/c/test/test_labcomm.c
@@ -43,7 +43,7 @@ static int writer_alloc(struct labcomm_writer *w,
 }
 static int writer_start(struct labcomm_writer *w, 
 			 struct labcomm_writer_action_context *action_context,
-			 int index, struct labcomm_signature *signature,
+			 int index, const struct labcomm_signature *signature,
 			 void *value)
 {
   return 0;
diff --git a/lib/c/test/test_labcomm_copy.c b/lib/c/test/test_labcomm_copy.c
index b7b5e08..8b6e582 100644
--- a/lib/c/test/test_labcomm_copy.c
+++ b/lib/c/test/test_labcomm_copy.c
@@ -40,6 +40,11 @@ static void handle_p(generated_encoding_P *v, void *context)
   labcomm_copy_generated_encoding_P(labcomm_default_memory, context, v);
 }
 
+static void handle_r(generated_encoding_R *v, void *context)
+{
+  labcomm_copy_generated_encoding_R(labcomm_default_memory, context, v);
+}
+
 static void handle_test_var(test_sample_test_var *v, void *context)
 {
   labcomm_copy_test_sample_test_var(labcomm_default_memory, context, v);
@@ -88,6 +93,8 @@ int main(int argc, char **argv)
   more_types_NS cache_ns;
   more_types_AS as;
   more_types_AS cache_as;
+  generated_encoding_R r;
+  generated_encoding_R cache_r;
 
   fd = open(DATA_FILE, O_RDWR | O_CREAT | O_TRUNC, 0644);
   if (fd == -1)
@@ -152,6 +159,17 @@ int main(int argc, char **argv)
   as.a[2] = "string 2";
   labcomm_encode_more_types_AS(encoder, &as);
 
+  labcomm_encoder_register_generated_encoding_R(encoder);
+  labcomm_encoder_sample_ref_register(encoder, labcomm_signature_generated_encoding_V);
+  labcomm_encoder_sample_ref_register(encoder, 
+                                      labcomm_signature_generated_encoding_UnusedD);
+  labcomm_encoder_sample_ref_register(encoder, labcomm_signature_generated_encoding_R);
+  r.a[0] = labcomm_signature_generated_encoding_V;
+  r.a[1] = labcomm_signature_generated_encoding_UnusedE;
+  r.a[2] = labcomm_signature_generated_encoding_UnusedD;
+  r.a[3] = labcomm_signature_generated_encoding_R;
+  labcomm_encode_generated_encoding_R(encoder, &r);
+
   labcomm_encoder_free(encoder);
   encoder = NULL;
   lseek(fd, 0, SEEK_SET);
@@ -171,6 +189,11 @@ int main(int argc, char **argv)
   labcomm_decoder_register_more_types_S(decoder, handle_s, &cache_s);
   labcomm_decoder_register_more_types_NS(decoder, handle_ns, &cache_ns);
   labcomm_decoder_register_more_types_AS(decoder, handle_as, &cache_as);
+  labcomm_decoder_register_generated_encoding_R(decoder, handle_r, &cache_r);
+  labcomm_decoder_sample_ref_register(decoder, labcomm_signature_generated_encoding_V);
+  labcomm_decoder_sample_ref_register(decoder, 
+                                      labcomm_signature_generated_encoding_UnusedE);
+  labcomm_decoder_sample_ref_register(decoder, labcomm_signature_generated_encoding_R);
 
   while (labcomm_decoder_decode_one(decoder) > 0) ;
 
@@ -217,6 +240,16 @@ int main(int argc, char **argv)
   free(as.a);
   puts("AS copied ok");
 
+  fprintf(stderr, "%p %p\n", r.a[0], cache_r.a[0]);
+  fprintf(stderr, "%p %p\n", r.a[1], cache_r.a[1]);
+  fprintf(stderr, "%p %p\n", r.a[2], cache_r.a[2]);
+  fprintf(stderr, "%p %p\n", r.a[3], cache_r.a[3]);
+  assert(cache_r.a[0] == r.a[0]);
+  assert(cache_r.a[1] == NULL); /* UnusedE */
+  assert(cache_r.a[2] == NULL); /* UnusedD */
+  assert(cache_r.a[3] == r.a[3]);
+  puts("R copied ok");
+
   labcomm_decoder_free(decoder);
   close(fd);
   unlink(DATA_FILE);
diff --git a/lib/c/test/test_labcomm_generated_encoding.c b/lib/c/test/test_labcomm_generated_encoding.c
index 8a85ada..e6fff79 100644
--- a/lib/c/test/test_labcomm_generated_encoding.c
+++ b/lib/c/test/test_labcomm_generated_encoding.c
@@ -59,7 +59,7 @@ static int buf_writer_start(
   struct labcomm_writer *w,
   struct labcomm_writer_action_context *action_context,
   int index,
-  struct labcomm_signature *signature,
+  const struct labcomm_signature *signature,
   void *value)
 {
   return 0;
@@ -85,7 +85,7 @@ static int buf_writer_flush(
 static int buf_writer_ioctl(
   struct labcomm_writer *w, 
   struct labcomm_writer_action_context *action_context,
-  int signature_index, struct labcomm_signature *signature,
+  int signature_index, const struct labcomm_signature *signature,
   uint32_t action, va_list arg)
 {
   int result = -ENOTSUP;
@@ -178,9 +178,8 @@ void dump_encoder(struct labcomm_encoder *encoder)
 
 int main(void)
 {
-  //no longer used
-  //generated_encoding_V V;
   generated_encoding_B B = 1;
+  generated_encoding_R R;
 
   struct labcomm_encoder *encoder = labcomm_encoder_new(
     &buffer_writer, 
@@ -198,7 +197,31 @@ int main(void)
   /* Register twice to make sure that only one registration gets encoded */
   labcomm_encoder_register_generated_encoding_B(encoder);
   labcomm_encoder_register_generated_encoding_B(encoder);
-  EXPECT({0x02, 0x05, -1, 0x01, 'B',0x01, 0x21});
+  EXPECT({0x02, 0x05, -1, 0x01, 'B', 0x01, 0x21});
+
+  labcomm_encoder_ioctl(encoder, IOCTL_WRITER_RESET);
+  /* Register twice to make sure that only one registration gets encoded */
+  labcomm_encoder_sample_ref_register(encoder, 
+                                      labcomm_signature_generated_encoding_V);
+  labcomm_encoder_sample_ref_register(encoder, 
+                                      labcomm_signature_generated_encoding_V);
+  EXPECT({0x03, 0x06, -1, 0x01, 'V', 0x02, 0x11, 0x00});
+
+  labcomm_encoder_ioctl(encoder, IOCTL_WRITER_RESET);
+  /* Register twice to make sure that only one registration gets encoded */
+  labcomm_encoder_sample_ref_register(encoder, 
+                                      labcomm_signature_generated_encoding_B);
+  labcomm_encoder_sample_ref_register(encoder, 
+                                      labcomm_signature_generated_encoding_B);
+  EXPECT({0x03, 0x05, -1, 0x01, 'B', 0x01, 0x21});
+
+  labcomm_encoder_ioctl(encoder, IOCTL_WRITER_RESET);
+  /* Register twice to make sure that only one registration gets encoded */
+  labcomm_encoder_sample_ref_register(encoder, 
+                                      labcomm_signature_generated_encoding_R);
+  labcomm_encoder_sample_ref_register(encoder, 
+                                      labcomm_signature_generated_encoding_R);
+  EXPECT({0x03, 0x08, -1, 0x01, 'R', 0x04, 0x10, 0x01, 0x04, 0x03});
 
   labcomm_encoder_ioctl(encoder, IOCTL_WRITER_RESET);
   // was: labcomm_encode_generated_encoding_V(encoder, &V);
@@ -209,6 +232,16 @@ int main(void)
   labcomm_encode_generated_encoding_B(encoder, &B);
   EXPECT({-1, 0x01, 1});
 
+  labcomm_encoder_ioctl(encoder, IOCTL_WRITER_RESET);
+  R.a[0] = labcomm_signature_generated_encoding_V;
+  R.a[1] = labcomm_signature_generated_encoding_B;
+  R.a[2] = labcomm_signature_generated_encoding_UnusedE;
+  R.a[3] = labcomm_signature_generated_encoding_R;
+  labcomm_encode_generated_encoding_R(encoder, &R);
+  EXPECT({-1, 0x10, 0x00, 0x00, 0x00, -1,
+                    0x00, 0x00, 0x00, -1,
+                    0x00, 0x00, 0x00, 0x00,
+                    0x00, 0x00, 0x00, -1});
   return 0;
 }
 
diff --git a/lib/c/test/test_signature_numbers.c b/lib/c/test/test_signature_numbers.c
index b8a6bcf..675088a 100644
--- a/lib/c/test/test_signature_numbers.c
+++ b/lib/c/test/test_signature_numbers.c
@@ -5,7 +5,7 @@
 #include "test/gen/generated_encoding.h"
 
 static void info(char *name, char *full_name, 
-		 struct labcomm_signature *signature) {
+		 const struct labcomm_signature *signature) {
   printf("%s %s %p -> %d\n", name,  full_name, signature, 
 	 labcomm_get_local_index(signature));
   if (labcomm_get_local_index(signature) < 0x40) {
@@ -16,8 +16,8 @@ static void info(char *name, char *full_name,
 int main(int argc, char *argv[])
 {
 #define FUNC(name, full_name) \
-  extern struct labcomm_signature labcomm_signature_##full_name; \
-  info( #name, #full_name, &labcomm_signature_##full_name)
+  info( #name, #full_name, labcomm_signature_##full_name)
+
   LABCOMM_FORALL_SAMPLES_generated_encoding(FUNC, ;);
   LABCOMM_FORALL_SAMPLES_another_encoding(FUNC, ;);
   return 0;
-- 
GitLab