protogen: factor out argument type conversion.
[disorder] / scripts / protocol
index 13c9f3c..ac47a7e 100755 (executable)
@@ -193,6 +193,30 @@ sub simple {
         $cmdc =~ s/-/_/g;
     }
     print STDERR "Processing $cmd... ";
+    # C argument types and conversions
+    my @cargs = ();
+    my @conversions = ();
+    for my $arg (@$args) {
+        if($arg->[0] eq 'body' or $arg->[0] eq 'list') {
+            push(@cargs, "disorder_$arg->[0]", $arg->[1], "n$arg->[1]");
+        } elsif($arg->[0] eq 'string') {
+            push(@cargs, $arg->[1]);
+        } elsif($arg->[0] eq 'integer') {
+            push(@cargs, "buf_$arg->[1]");
+            push(@conversions,
+                "  char buf_$arg->[1]\[16];\n",
+                 "  byte_snprintf(buf_$arg->[1], sizeof buf_$arg->[1], \"%ld\", $arg->[1]);\n");
+        } elsif($arg->[0] eq 'time') {
+            push(@cargs, "buf_$arg->[1]");
+            push(@conversions,
+                "  char buf_$arg->[1]\[16];\n",
+                 "  byte_snprintf(buf_$arg->[1], sizeof buf_$arg->[1], \"%lld\", (long long)$arg->[1]);\n");
+        } elsif($arg->[0] eq 'literal') {
+            push(@cargs, "\"$arg->[1]\"");
+        } else {
+            die "$0: unsupported arg type '$arg->[0]' for '$cmd'\n";
+        }
+    }
     # Synchronous C API
     print STDERR "H ";
     push(@h, "/** \@brief $summary\n",
@@ -214,27 +238,8 @@ sub simple {
         join(", ", "disorder_client *c",
                    map(c_in_decl($_), @$args),
                     map(c_out_decl($_), @$returns)),
-        ") {\n");
-    my @cargs = ();
-    for my $arg (@$args) {
-        if($arg->[0] eq 'body' or $arg->[0] eq 'list') {
-            push(@cargs, "disorder_$arg->[0]", $arg->[1], "n$arg->[1]");
-        } elsif($arg->[0] eq 'string') {
-            push(@cargs, $arg->[1]);
-        } elsif($arg->[0] eq 'integer') {
-            push(@cargs, "buf_$arg->[1]");
-            push(@c, "  char buf_$arg->[1]\[16];\n",
-                 "  byte_snprintf(buf_$arg->[1], sizeof buf_$arg->[1], \"%ld\", $arg->[1]);\n");
-        } elsif($arg->[0] eq 'time') {
-            push(@cargs, "buf_$arg->[1]");
-            push(@c, "  char buf_$arg->[1]\[16];\n",
-                 "  byte_snprintf(buf_$arg->[1], sizeof buf_$arg->[1], \"%lld\", (long long)$arg->[1]);\n");
-        } elsif($arg->[0] eq 'literal') {
-            push(@cargs, "\"$arg->[1]\"");
-        } else {
-            die "$0: unsupported arg type '$arg->[0]' for '$cmd'\n";
-        }
-    }
+        ") {\n",
+       @conversions);
     if(!defined $returns or scalar @$returns == 0) {
         # Simple case
        push(@c, "  return disorder_simple(",
@@ -262,7 +267,7 @@ sub simple {
                   "(char *)NULL"),
              ");\n");
     } else {
-        my $split = 0;
+        my $expected = 0;
         for(my $n = 0; $n < scalar @$returns; ++$n) {
             my $return = $returns->[$n];
             my $type = $return->[0];
@@ -272,39 +277,44 @@ sub simple {
                or $type eq 'integer'
                or $type eq 'time'
                or $type eq 'user') {
-                $split = 1;
+               ++$expected;
             }
         }
-        if($split) {
-            push(@c, "  char **v, *r;\n",
-                 "  int nv;\n");
-        }
-        push(@c, 
-             "  int rc = disorder_simple(",
-             join(", ",
-                  "c",
-                  $split ? "&r" : "NULL",
-                  "\"$cmd\"",
-                  @cargs,
-                  "(char *)NULL"),
-             ");\n",
-             "  if(rc)\n",
-             "    return rc;\n");
-        if($split) {
-            push(@c,
-                 "  v = split(r, &nv, SPLIT_QUOTES, 0, 0);\n",
-                 "  if(nv != ", scalar @$returns, ") {\n",
-                 "    disorder_error(0, \"malformed reply to %s\", \"$cmd\");\n",
-                 "    return -1;\n",
-                 "  }\n");
-        }
+        if($expected) {
+            push(@c, "  char **v;\n",
+                "  int nv, rc = disorder_simple_split(",
+                join(", ",
+                     "c",
+                     "&v",
+                     "&nv",
+                     $expected,
+                     "\"$cmd\"",
+                     @cargs,
+                     "(char *)NULL"),
+                ");\n",
+                "  if(rc)\n",
+                "    return rc;\n");
+        } else {
+           push(@c,
+                "  int rc = disorder_simple(",
+                join(", ",
+                     "c",
+                     "NULL",
+                     "\"$cmd\"",
+                     @cargs,
+                     "(char *)NULL"),
+                ");\n",
+                "  if(rc)\n",
+                "    return rc;\n");
+       }
         for(my $n = 0; $n < scalar @$returns; ++$n) {
             my $return = $returns->[$n];
             my $type = $return->[0];
             my $name = $return->[1];
             if($type eq 'string') {
                 push(@c,
-                     "  *${name}p = v[$n];\n");
+                     "  *${name}p = v[$n];\n",
+                    "  v[$n] = NULL;\n");
             } elsif($type eq 'boolean') {
                 push(@c,
                      "  if(boolean(\"$cmd\", v[$n], ${name}p))\n",
@@ -317,7 +327,8 @@ sub simple {
                      "  *${name}p = atoll(v[$n]);\n");
             } elsif($type eq 'user') {
                 push(@c,
-                     "  c->user = v[$n];\n");
+                     "  c->user = v[$n];\n",
+                    "  v[$n] = NULL;\n");
             } elsif($type eq 'body') {
                 push(@c,
                      "  if(readlist(c, ${name}p, n${name}p))\n",
@@ -330,8 +341,11 @@ sub simple {
                 die "$0: C API: unknown return type '$type' for '$name'\n";
             }
         }
+       if($expected) {
+           push(@c,
+                "  free_strings(nv, v);\n");
+       }
         push(@c, "  return 0;\n");
-        # TODO xfree unconsumed split output
     }
     push(@c, "}\n\n");