Commit 7a46bd4200e0fb7045b5dbf60bbe5b943dcad8fa

Thomas de Grivel 2023-07-10T15:32:46

wip buf_parse_array

diff --git a/libc3/buf_parse.c b/libc3/buf_parse.c
index 373fd50..853e892 100644
--- a/libc3/buf_parse.c
+++ b/libc3/buf_parse.c
@@ -17,14 +17,20 @@
 #include "../libtommath/tommath.h"
 #include "c3.h"
 
+sw buf_parse_array_data_rec (s_buf *buf, s_array *dest,
+                             uw dimension, uw *address,
+                             f_buf_parse parse, u8 **data);
 sw buf_parse_array_dimensions_rec (s_buf *buf, s_array *dest,
                                    uw dimension, uw *address,
                                    f_buf_parse parse, void *data);
 sw buf_parse_cfn_arg_types (s_buf *buf, s_list **dest);
 
-sw buf_parse_array_dimension_count (s_buf *buf, s_array *dest)
+sw buf_parse_array_data (s_buf *buf, s_array *dest)
 {
-  sw r = 1;
+  uw *address;
+  u8 *data;
+  f_buf_parse parse;
+  sw r;
   sw result = 0;
   s_buf_save save;
   s_array tmp;
@@ -32,49 +38,51 @@ sw buf_parse_array_dimension_count (s_buf *buf, s_array *dest)
   assert(dest);
   tmp = *dest;
   buf_save_init(buf, &save);
-  tmp.dimensions = 0;
-  if ((r = buf_read_1(buf, "[")) <= 0)
-    goto clean;
-  result += r;
-  if ((r = buf_ignore_spaces(buf)) < 0)
-    goto restore;
-  result += r;
-  while ((r = buf_read_1(buf, "[")) > 0) {
-    result += r;
-    tmp.dimensions++;
-    if ((r = buf_ignore_spaces(buf)) < 0)
-      goto restore;
-    result += r;
+  if (! (address = calloc(tmp.dimension, sizeof(sw)))) {
+    err(1, "buf_parse_array_data: address: %lu %lu",
+        tmp.dimension, sizeof(sw));
+    return -1;
   }
+  parse = tag_type_to_buf_parse(tmp.type);
+  if (! (tmp.data = calloc(tmp.dimensions[0].count,
+                           tmp.dimensions[0].item_size))) {
+    err(1, "buf_parse_array_data: data");
+    return -1;
+  }
+  data = tmp.data;
+  if ((r = buf_parse_array_data_rec(buf, &tmp,
+                                    tmp.dimension - 1,
+                                    address, parse, &data)) <= 0)
+    goto clean;
   r = result;
   *dest = tmp;
-  goto clean;
- restore:
-  buf_save_restore_rpos(buf, &save);
  clean:
+  buf_save_restore_rpos(buf, &save);
   buf_save_clean(buf, &save);
   return r;
 }
 
-sw buf_parse_array_dimensions_rec (s_buf *buf, s_array *dest,
-                                   uw dimension, uw *address,
-                                   f_buf_parse parse, void *data)
+sw buf_parse_array_data_rec (s_buf *buf, s_array *dest,
+                             uw dimension, uw *address,
+                             f_buf_parse parse, u8 **data)
 {
+  uw item_size;
   sw r = 0;
   sw result = 0;
   s_buf_save save;
   s_array tmp;
   assert(buf);
   assert(dest);
-  assert(dimension);
   assert(address);
   tmp = *dest;
+  item_size = tag_type_size(tmp.type);
   buf_save_init(buf, &save);
  start:
   if (dimension == dest->dimension - 1) {
-    if ((r = parse(buf, data)) < 0)
+    if ((r = parse(buf, *data)) < 0)
       goto clean;
     result += r;
+    *data += item_size;
     goto ok;
   }
   if ((r = buf_read_1(buf, "[")) < 0)
@@ -83,28 +91,22 @@ sw buf_parse_array_dimensions_rec (s_buf *buf, s_array *dest,
     result += r;
     dimension++;
     address[dimension] = 0;
-    if ((r = buf_parse_array_dimensions_rec(buf, &tmp, dimension,
-                                            address, parse,
-                                            data)) <= 0)
+    if ((r = buf_parse_array_data_rec(buf, &tmp, dimension,
+                                      address, parse,
+                                      data)) <= 0)
       goto clean;
     result += r;
     goto ok;
   }
-  if (! dimension)
-    goto ok;
   if ((r = buf_read_1(buf, "]")) < 0)
     goto clean;
   if (r) {
     result += r;
     dimension--;
-    if (! tmp.dimensions[dimension].count) {
-      tmp.dimensions[dimension].count = address[dimension];
-      tmp.dimensions[dimension].item_size = tmp.dimensions[dimension + 1].count * tmp.dimensions[dimension + 1].item_size;
-    }
-    else if (tmp.dimensions[dimension].count != address[dimension]) {
+    if (tmp.dimensions[dimension].count != address[dimension]) {
       assert(! "buf_parse_array_dimensions_rec: dimension mismatch");
       errx(1, "buf_parse_array_dimensions_rec: dimension mismatch"
-             ": %lu", dimension);
+           ": %lu", dimension);
       r = -1;
       goto clean;
     }
@@ -114,7 +116,8 @@ sw buf_parse_array_dimensions_rec (s_buf *buf, s_array *dest,
     goto clean;
   result += r;
   address[dimension]++;
-  goto start;
+  if (dimension)
+    goto start;
  ok:
   r = result;
   goto clean;
@@ -123,6 +126,41 @@ sw buf_parse_array_dimensions_rec (s_buf *buf, s_array *dest,
   return r;
 }
 
+sw buf_parse_array_dimension_count (s_buf *buf, s_array *dest)
+{
+  sw r = 1;
+  sw result = 0;
+  s_buf_save save;
+  s_array tmp;
+  assert(buf);
+  assert(dest);
+  tmp = *dest;
+  buf_save_init(buf, &save);
+  if ((r = buf_read_1(buf, "[")) <= 0)
+    goto clean;
+  result += r;
+  tmp.dimension = 1;
+  if ((r = buf_ignore_spaces(buf)) < 0)
+    goto restore;
+  result += r;
+  while ((r = buf_read_1(buf, "[")) > 0) {
+    result += r;
+    tmp.dimension++;
+    if ((r = buf_ignore_spaces(buf)) < 0)
+      goto restore;
+    result += r;
+  }
+  r = result;
+  tmp.dimensions = calloc(tmp.dimension, sizeof(s_array_dimension));
+  *dest = tmp;
+  goto clean;
+ restore:
+  buf_save_restore_rpos(buf, &save);
+ clean:
+  buf_save_clean(buf, &save);
+  return r;
+}
+
 sw buf_parse_array_dimensions (s_buf *buf, s_array *dest)
 {
   uw *address;
@@ -138,29 +176,86 @@ sw buf_parse_array_dimensions (s_buf *buf, s_array *dest)
   buf_save_init(buf, &save);
   tmp = *dest;
   address = calloc(tmp.dimension, sizeof(sw));
-  tmp.dimensions = calloc(tmp.dimension, sizeof(s_array_dimension));
   size = tag_type_size(tmp.type);
   parse = tag_type_to_buf_parse(tmp.type);
   data = calloc(1, size);
   tmp.dimensions[tmp.dimension - 1].item_size = size;
   if ((r = buf_parse_array_dimensions_rec(buf, dest,
-                                          dest->dimension - 1,
+                                          tmp.dimension - 1,
                                           address, parse, data)) <= 0)
     goto clean;
   r = result;
   *dest = tmp;
  clean:
   buf_save_restore_rpos(buf, &save);
+  buf_save_clean(buf, &save);
   return r;
 }
 
-sw buf_peek_array_dimensions (s_buf *buf, s_array *dest)
+sw buf_parse_array_dimensions_rec (s_buf *buf, s_array *dest,
+                                   uw dimension, uw *address,
+                                   f_buf_parse parse, void *data)
 {
-  sw r;
+  sw r = 0;
+  sw result = 0;
   s_buf_save save;
+  s_array tmp;
+  assert(buf);
+  assert(dest);
+  assert(address);
+  tmp = *dest;
   buf_save_init(buf, &save);
-  r = buf_parse_array_dimensions(buf, dest);
-  buf_save_restore_rpos(buf, &save);
+ start:
+  if (dimension == dest->dimension - 1) {
+    if ((r = parse(buf, data)) < 0)
+      goto clean;
+    result += r;
+    goto ok;
+  }
+  if ((r = buf_read_1(buf, "[")) < 0)
+    goto clean;
+  if (r) {
+    result += r;
+    dimension++;
+    address[dimension] = 0;
+    if ((r = buf_parse_array_dimensions_rec(buf, &tmp, dimension,
+                                            address, parse,
+                                            data)) <= 0)
+      goto clean;
+    result += r;
+    goto ok;
+  }
+  if (! dimension)
+    goto ok;
+  if ((r = buf_read_1(buf, "]")) < 0)
+    goto clean;
+  if (r) {
+    result += r;
+    dimension--;
+    if (! tmp.dimensions[dimension].count) {
+      tmp.dimensions[dimension].count = address[dimension];
+      tmp.dimensions[dimension].item_size = tmp.dimensions[dimension + 1].count * tmp.dimensions[dimension + 1].item_size;
+    }
+    else if (tmp.dimensions[dimension].count != address[dimension]) {
+      assert(! "buf_parse_array_dimensions_rec: dimension mismatch");
+      errx(1, "buf_parse_array_dimensions_rec: dimension mismatch"
+             ": %lu", dimension);
+      r = -1;
+      goto clean;
+    }
+    goto ok;
+  }
+  if ((r = buf_read_1(buf, ",")) <= 0)
+    goto clean;
+  result += r;
+  address[dimension]++;
+  if (dimension)
+    goto start;
+ ok:
+  r = result;
+  goto clean;
+ clean:
+  buf_save_clean(buf, &save);
   return r;
 }
 
@@ -213,6 +308,8 @@ sw buf_parse_array (s_buf *buf, s_array *dest)
   if ((r = buf_parse_array_type(buf, &tmp)) <= 0)
     goto clean;
   result += r;
+  if ((r = buf_parse_array_dimension_count(buf, &tmp)) <= 0)
+    goto restore;
   if ((r = buf_peek_array_dimensions(buf, &tmp)) < 0)
     goto restore;
   if ((r = buf_parse_array_data(buf, &tmp)) < 0)
@@ -2327,3 +2424,13 @@ sw buf_parse_f64 (s_buf *buf, f64 *dest) {
   buf_save_clean(buf, &save);
   return r;
 }
+
+sw buf_peek_array_dimensions (s_buf *buf, s_array *dest)
+{
+  sw r;
+  s_buf_save save;
+  buf_save_init(buf, &save);
+  r = buf_parse_array_dimensions(buf, dest);
+  buf_save_restore_rpos(buf, &save);
+  return r;
+}