From 2f426104c6b7cf0a7bf8a8e401a71525b0a6752b Mon Sep 17 00:00:00 2001
From: Sven Gestegard Robertz <sven.robertz@cs.lth.se>
Date: Sat, 31 Jan 2015 14:33:34 +0100
Subject: [PATCH] handling of typedefs implemented in C

---
 examples/user_types/example_decoder.c |  5 ++
 lib/c/2014/labcomm_decoder.c          | 88 ++++++++++++++++++++++++++-
 lib/c/2014/labcomm_type_signature.h   | 70 ++++++---------------
 3 files changed, 110 insertions(+), 53 deletions(-)

diff --git a/examples/user_types/example_decoder.c b/examples/user_types/example_decoder.c
index 830a4c5..56a7fb4 100644
--- a/examples/user_types/example_decoder.c
+++ b/examples/user_types/example_decoder.c
@@ -20,6 +20,10 @@ static void handle_test_theSecondInt(int *v,void *context) {
   printf("Got theSecondInt. (%d) \n", *v); 
 }
 
+static void handle_typedef(struct labcomm_raw_typedef *v,void *context) {
+  printf("Got typedef. (%d) %s\n", v->index, v->name); 
+}
+
 static void handle_test_twoLines(test_twoLines *v,void *context) {
   printf("Got twoLines. (%d,%d) -> (%d,%d), (%d,%d) -> (%d,%d)\n", v->l1.start.x.val, v->l1.start.y.val, 
                                                                      v->l1.end.x.val, v->l1.end.y.val,    
@@ -49,6 +53,7 @@ int main(int argc, char *argv[]) {
   labcomm_decoder_register_test_theFirstInt(decoder, handle_test_theFirstInt, context);
   labcomm_decoder_register_test_theSecondInt(decoder, handle_test_theSecondInt, context);
   labcomm_decoder_register_test_twoLines(decoder, handle_test_twoLines, context);
+  labcomm_decoder_register_labcomm_typedef(decoder, handle_typedef, context);
 
   printf("Decoding:\n");
   labcomm_decoder_run(decoder);
diff --git a/lib/c/2014/labcomm_decoder.c b/lib/c/2014/labcomm_decoder.c
index 2c3e567..8c240c9 100644
--- a/lib/c/2014/labcomm_decoder.c
+++ b/lib/c/2014/labcomm_decoder.c
@@ -443,7 +443,11 @@ int labcomm_decoder_decode_one(struct labcomm_decoder *d)
   } 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 = decode_type_def(d, LABCOMM_TYPE_DEF); 
+    result = decode_and_handle(d, d, remote_index);
+    if(result == -ENOENT) {
+        printf("*** no handler for typedef...");
+        result = decode_type_def(d, LABCOMM_TYPE_DEF); 
+    }
   } else if (remote_index == LABCOMM_TYPE_BINDING) {
     result = decode_type_binding(d, LABCOMM_TYPE_BINDING); 
   } else if (remote_index == LABCOMM_PRAGMA) {
@@ -525,6 +529,88 @@ int labcomm_internal_decoder_ioctl(struct labcomm_decoder *d,
   return result;
 }
 
+#ifndef LABCOMM_NO_TYPEDECL
+//// Code for allowing user code to handle typedefs 
+//// (should perhaps be moved to another file)
+
+static void decode_raw_typedef(
+  struct labcomm_reader *r,
+  void (*handle)(
+    struct labcomm_raw_typedef *v,
+    void *context
+  ),
+  void *context
+)
+{
+  struct labcomm_raw_typedef v;
+  v.index = labcomm_read_packed32(r);
+  if (r->error < 0) {
+    goto out;
+  }
+  v.name  = labcomm_read_string(r);
+  if (r->error < 0) {
+    goto free_name;
+  }
+  v.length = labcomm_read_packed32(r);
+  if (r->error < 0) {
+    goto free_name;
+  }
+  int i;
+  v.signature_data = labcomm_memory_alloc(r->memory, 1, v.length);
+  if(v.signature_data) {
+    for(i=0; i<v.length; i++) {
+      v.signature_data[i] = labcomm_read_byte(r);
+      if (r->error < 0) {
+        goto free_sig;
+      }
+    }  
+    handle(&v, context);
+    }
+free_sig:
+  labcomm_memory_free(r->memory, 1, v.signature_data);
+free_name:
+  labcomm_memory_free(r->memory, 1, v.name);
+out:
+  return;
+}
+
+int labcomm_decoder_register_labcomm_typedef(
+  struct labcomm_decoder *d,
+  void (*handler)(
+    struct labcomm_raw_typedef *v,
+    void *context
+  ),
+  void *context
+)
+{
+  int tag = LABCOMM_TYPE_DEF;
+  struct sample_entry *entry;
+  int *remote_to_local;
+ 
+  labcomm_scheduler_data_lock(d->scheduler);
+  entry = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
+				      d->local, struct sample_entry,
+				      tag);
+  if (entry == NULL) { tag = -ENOMEM; goto unlock; }
+  entry->remote_index = LABCOMM_TYPE_DEF;
+  entry->signature = NULL;
+  entry->decode = (labcomm_decoder_function) decode_raw_typedef;
+  entry->handler =(labcomm_handler_function) handler;
+  entry->context = context;
+
+  remote_to_local = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
+                                                    d->remote_to_local, int,
+                                                    tag);
+  *remote_to_local = tag;
+unlock:
+  labcomm_scheduler_data_unlock(d->scheduler);
+
+  return tag;
+}
+
+//// End typedef handling
+#endif
+
 int labcomm_internal_decoder_register(
   struct labcomm_decoder *d,
   const struct labcomm_signature *signature,
diff --git a/lib/c/2014/labcomm_type_signature.h b/lib/c/2014/labcomm_type_signature.h
index 44549aa..3f2ecfe 100644
--- a/lib/c/2014/labcomm_type_signature.h
+++ b/lib/c/2014/labcomm_type_signature.h
@@ -61,67 +61,33 @@ struct labcomm_signature {
 #endif
 };
 
-#if 0
-/*
- * Signature entry
+/* a struct for "raw" typedefs, to be used as an intermediate representation
+ * between decoder and signature parser
  */
 
-#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_raw_typedef {
+    char *name;
+    int index;
+    int length;
+    char *signature_data;
 };
 
-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
  */
 
 
+/* register a handler for typedefs
+ */
+
+int labcomm_decoder_register_labcomm_typedef(
+  struct labcomm_decoder *d,
+  void (*handler)(
+    struct labcomm_raw_typedef *v,
+    void *context
+  ),
+  void *context
+);
 /* Dump signature bytes on stdout 
  */
 
-- 
GitLab