$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",
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(",
"(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];
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",
" *${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",
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");