From 61b2291fdda31e4131ae74b3b102194be2c1d9a6 Mon Sep 17 00:00:00 2001
From: Anders Blomdell <anders.blomdell@control.lth.se>
Date: Wed, 5 Jun 2013 11:06:13 +0200
Subject: [PATCH] Changed low-level ioctl argument ordering, and added
 signature_index. Added dynamic macros and code for dynamic arrays indexed by
 signature index.

---
 compiler/C_CodeGen.jrag                      |  8 +--
 lib/c/labcomm.c                              | 62 ++++++++++++++++----
 lib/c/labcomm_dynamic_buffer_writer.c        |  4 +-
 lib/c/labcomm_fd_reader.c                    | 11 +++-
 lib/c/labcomm_fd_writer.c                    |  9 ++-
 lib/c/labcomm_private.h                      | 45 +++++++++++---
 lib/c/test/test_labcomm_generated_encoding.c |  5 +-
 7 files changed, 114 insertions(+), 30 deletions(-)

diff --git a/compiler/C_CodeGen.jrag b/compiler/C_CodeGen.jrag
index beb7309..428657f 100644
--- a/compiler/C_CodeGen.jrag
+++ b/compiler/C_CodeGen.jrag
@@ -673,8 +673,8 @@ aspect C_DecoderIoctl {
     env.println("va_start(va, ioctl_action);");
     env.println("result = labcomm_internal_decoder_ioctl(");
     env.indent();
-    env.println("d, ioctl_action,");
-    env.println("&labcomm_signature_" + env.prefix + getName() + ", va);");
+    env.println("d, &labcomm_signature_" + env.prefix + getName() + ", ");
+    env.println("ioctl_action, va);");
     env.unindent();
     env.println("va_end(va);");
     env.println("return result;");
@@ -851,8 +851,8 @@ aspect C_EncoderIoctl {
     env.println("va_start(va, ioctl_action);");
     env.println("result = labcomm_internal_encoder_ioctl(");
     env.indent();
-    env.println("e, ioctl_action,");
-    env.println("&labcomm_signature_" + env.prefix + getName() + ", va);");
+    env.println("e, &labcomm_signature_" + env.prefix + getName() + ", ");
+    env.println("ioctl_action, va);");
     env.unindent();
     env.println("va_end(va);");
     env.println("return result;");
diff --git a/lib/c/labcomm.c b/lib/c/labcomm.c
index 978640f..9f4f172 100644
--- a/lib/c/labcomm.c
+++ b/lib/c/labcomm.c
@@ -457,7 +457,7 @@ int labcomm_encoder_ioctl(struct labcomm_encoder *encoder,
   va_start(va, action);
   result = encoder->writer->action->ioctl(encoder->writer, 
 					  encoder->writer->context,
-					  action, NULL, va);
+					  0, NULL, action, va);
   va_end(va);
 
 out:
@@ -481,23 +481,23 @@ static int labcomm_writer_ioctl(struct labcomm_writer *writer,
   }
   
   va_start(va, action);
-  result = writer->action->ioctl(writer, writer->context, action, NULL, va);
+  result = writer->action->ioctl(writer, writer->context, 
+				 0, NULL, action, va);
   va_end(va);
 out:
   return result;
 }
 
 int labcomm_internal_encoder_ioctl(struct labcomm_encoder *encoder, 
-				   int action,
 				   struct labcomm_signature *signature,
-                                   va_list va)
+				   int action, va_list va)
 {
   int result = -ENOTSUP;
   
   if (encoder->writer->action->ioctl != NULL) {
     result = encoder->writer->action->ioctl(encoder->writer, 
 					    encoder->writer->context, 
-					    action, signature, va);
+					    -1, signature, action, va);
   }
   return result;
 }
@@ -572,8 +572,6 @@ struct labcomm_decoder *labcomm_decoder_new(
     result->lock = lock;
     result->on_error = on_error_fprintf;
     result->on_new_datatype = on_new_datatype;
-    result->reader->action->alloc(result->reader, result->reader->context,
-				  result, LABCOMM_VERSION);
   }
   return result;
 }
@@ -604,7 +602,14 @@ void labcomm_internal_decoder_register(
 int labcomm_decoder_decode_one(struct labcomm_decoder *d)
 {
   int result;
-
+  
+  if (d->reader->data == NULL) {
+    result = d->reader->action->alloc(d->reader, d->reader->context,
+				      d, LABCOMM_VERSION);
+    if (result <= 0) {
+      goto out;
+    }
+  }
   result = d->reader->action->start(d->reader, d->reader->context);
   if (result > 0) {
     struct labcomm_decoder_context *context = d->context;
@@ -681,6 +686,7 @@ int labcomm_decoder_decode_one(struct labcomm_decoder *d)
     }
   }
   d->reader->action->end(d->reader, d->reader->context);
+out:
   return result;
 }
 
@@ -719,24 +725,56 @@ int labcomm_decoder_ioctl(struct labcomm_decoder *decoder,
     va_start(va, action);
     result = decoder->reader->action->ioctl(decoder->reader, 
 					    decoder->reader->context,
-					    action, NULL, va);
+					    0, NULL, action, va);
     va_end(va);
   }
   return result;
 }
 
 int labcomm_internal_decoder_ioctl(struct labcomm_decoder *decoder, 
-				   int action,
 				   struct labcomm_signature *signature,
-                                   va_list va)
+				   int action, va_list va)
 {
   int result = -ENOTSUP;
   
   if (decoder->reader->action->ioctl != NULL) {
     result = decoder->reader->action->ioctl(decoder->reader, 
 					    decoder->reader->context,
-					    action, NULL, va);
+					    -1, signature, action, va);
   }
   return result;
 }
 
+void *labcomm_signature_array_ref(int *first, int *last, void **data,
+				  int size, int index)
+{
+  if (*first == 0 && *last == 0) {
+    *first = index;
+    *last = index + 1;
+    *data = malloc(size);
+    if (*data) { 
+      memset(*data, 0, size); 
+    }
+  } else if (index < *first || *last <= index) {
+    void *old_data = *data;
+    int old_first = *first;
+    int old_last = *last;
+    int n;
+    *first = (index<old_first)?index:old_first;
+    *last = (old_last<=index)?index+1:old_last;
+    n = (*last - *first);
+    *data = malloc(n * size);
+    if (*data) {
+      memset(*data, 0, n * size);
+      memcpy(*data + (old_first - *first) * size, 
+	     old_data, 
+	     (old_last - old_first) * size);
+    }
+    free(old_data);
+  }
+  if (*data) {
+    return *data + (index - *first) * size;
+  } else {
+    return NULL;
+  }
+}
diff --git a/lib/c/labcomm_dynamic_buffer_writer.c b/lib/c/labcomm_dynamic_buffer_writer.c
index 4a1f3ac..c3ef5cd 100644
--- a/lib/c/labcomm_dynamic_buffer_writer.c
+++ b/lib/c/labcomm_dynamic_buffer_writer.c
@@ -77,9 +77,9 @@ static int dyn_flush(struct labcomm_writer *w, void *context)
 }
 
 static int dyn_ioctl(struct labcomm_writer *w, void *context, 
-		     int action, 
+		     int signature_index,
 		     struct labcomm_signature *signature,
-		     va_list arg)
+		     int action, va_list arg)
 {
   int result = -ENOTSUP;
   switch (action) {
diff --git a/lib/c/labcomm_fd_reader.c b/lib/c/labcomm_fd_reader.c
index d67e6f6..3aa0d63 100644
--- a/lib/c/labcomm_fd_reader.c
+++ b/lib/c/labcomm_fd_reader.c
@@ -102,13 +102,22 @@ static int fd_end(struct labcomm_reader *r, void *context)
   return 0;
 }
 
+static int fd_ioctl(struct labcomm_reader *r, void *context,
+		    int signature_index, 
+		    struct labcomm_signature *signature, 
+		    int action, va_list args)
+{
+  return -ENOTSUP;
+}
+
+
 static const struct labcomm_reader_action action = {
   .alloc = fd_alloc,
   .free = fd_free,
   .start = fd_start,
   .fill = fd_fill,
   .end = fd_end,
-  .ioctl = NULL
+  .ioctl = fd_ioctl
 };
 
 struct labcomm_reader *labcomm_fd_reader_new(int fd, int close_fd_on_free)
diff --git a/lib/c/labcomm_fd_writer.c b/lib/c/labcomm_fd_writer.c
index 6fadb80..c2e1b12 100644
--- a/lib/c/labcomm_fd_writer.c
+++ b/lib/c/labcomm_fd_writer.c
@@ -90,13 +90,20 @@ static int fd_flush(struct labcomm_writer *w, void *context)
   return w->error;
 }
 
+static int fd_ioctl(struct labcomm_writer *w, void *context, 
+		    int signature_index, struct labcomm_signature *signature, 
+		    int action, va_list args)
+{
+  return -ENOTSUP;
+}
+
 static const struct labcomm_writer_action action = {
   .alloc = fd_alloc,
   .free = fd_free,
   .start = fd_start,
   .end = fd_flush,
   .flush = fd_flush,
-  .ioctl = NULL
+  .ioctl = fd_ioctl
 };
 
 struct labcomm_writer *labcomm_fd_writer_new(int fd, int close_fd_on_free)
diff --git a/lib/c/labcomm_private.h b/lib/c/labcomm_private.h
index 695938d..9922e1c 100644
--- a/lib/c/labcomm_private.h
+++ b/lib/c/labcomm_private.h
@@ -78,7 +78,8 @@ struct labcomm_reader_action {
   int (*end)(struct labcomm_reader *r, void *context);
   int (*fill)(struct labcomm_reader *r, void *context); 
   int (*ioctl)(struct labcomm_reader *r, void *context,
-	       int action, struct labcomm_signature *signature, va_list args);
+	       int signature_index, struct labcomm_signature *signature, 
+	       int ioctl_action, va_list args);
 };
 
 struct labcomm_reader {
@@ -105,9 +106,8 @@ void labcomm_internal_decoder_register(
   void *context);
 
 int labcomm_internal_decoder_ioctl(struct labcomm_decoder *decoder, 
-				   int ioctl_action,
 				   struct labcomm_signature *signature,
-				   va_list args);
+				   int ioctl_action, va_list args);
 
 #if __BYTE_ORDER == __LITTLE_ENDIAN
 
@@ -211,8 +211,8 @@ struct labcomm_writer_action {
   int (*end)(struct labcomm_writer *w, void *context);
   int (*flush)(struct labcomm_writer *w, void *context); 
   int (*ioctl)(struct labcomm_writer *w, void *context, 
-	       int index, struct labcomm_signature *, 
-	       va_list);
+	       int signature_index, struct labcomm_signature *signature, 
+	       int ioctl_action, va_list args);
 };
 
 struct labcomm_writer {
@@ -238,9 +238,8 @@ int labcomm_internal_encode(
 
 
 int labcomm_internal_encoder_ioctl(struct labcomm_encoder *encoder, 
-				   int ioctl_action,
 				   struct labcomm_signature *signature,
-				   va_list args);
+				   int ioctl_action, va_list args);
 
 #if __BYTE_ORDER == __LITTLE_ENDIAN
 
@@ -325,4 +324,36 @@ static inline int labcomm_write_string(struct labcomm_writer *w, char *s)
   return 0;
 }
 
+/*
+ * Macros for handling arrays indexed by signature index
+ */
+
+#define LABCOMM_SIGNATURE_ARRAY_DEF(name, kind)	\
+  struct {					\
+    int first;					\
+    int last;					\
+    kind *data;					\
+  } name
+
+#define LABCOMM_SIGNATURE_ARRAY_DEF_INIT(name, kind)		\
+  LABCOMM_SIGNATURE_ARRAY_DEF(name, kind) = { 0, 0, NULL }
+
+#define LABCOMM_SIGNATURE_ARRAY_INIT(name, kind)		\
+  name.first = 0; name.last = 0; name.data = NULL;		\
+  name.data = (kind *)name.data; /* typechecking no-op */
+
+#define LABCOMM_SIGNATURE_ARRAY_FREE(name, kind)		\
+  if (name.data) { free(name.data); }				\
+  name.data = (kind *)NULL; /* typechecking */
+
+#define LABCOMM_SIGNATURE_ARRAY_REF(name, kind, index)			\
+  (name.data = (kind *)name.data, /* typechecking no-op */		\
+   (kind *)(labcomm_signature_array_ref(&name.first, &name.last,	\
+					(void **)&name.data,		\
+					sizeof(kind), index)))
+
+void *labcomm_signature_array_ref(int *first, int *last, void **data,
+				  int size, int index);
+
+
 #endif
diff --git a/lib/c/test/test_labcomm_generated_encoding.c b/lib/c/test/test_labcomm_generated_encoding.c
index 6cb0d34..7de51eb 100644
--- a/lib/c/test/test_labcomm_generated_encoding.c
+++ b/lib/c/test/test_labcomm_generated_encoding.c
@@ -53,9 +53,8 @@ static int buf_writer_flush(struct labcomm_writer *w, void *context)
 
 static int buf_writer_ioctl(
   struct labcomm_writer *w, void *context,
-  int action, 
-  struct labcomm_signature *signature,
-  va_list arg)
+  int signature_index, struct labcomm_signature *signature,
+  int action, va_list arg)
 {
   int result = -ENOTSUP;
   switch (action) {
-- 
GitLab