+ "int disorder_$cmdc(",
+ join(", ", "disorder_client *c",
+ map(c_in_decl($_), @$args),
+ map(c_out_decl($_), @$returns)),
+ ");\n\n");
+ print STDERR "C ";
+ push(@c, "int disorder_$cmdc(",
+ 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";
+ }
+ }
+ if(!defined $returns or scalar @$returns == 0) {
+ # Simple case
+ push(@c, " return disorder_simple(",
+ join(", ", "c", "NULL", "\"$cmd\"", @cargs, "(char *)NULL"),
+ ");\n");
+ } elsif(scalar @$returns == 1
+ and $returns->[0]->[0] eq 'queue-one') {
+ # Special case
+ my $return = $$returns[0];
+ push(@c, " return onequeue(c, \"$cmd\", $return->[1]p);\n");
+ } elsif(scalar @$returns == 1
+ and $returns->[0]->[0] eq 'string-raw') {
+ # Special case
+ my $return = $$returns[0];
+ push(@c, " return disorder_simple(",
+ join(", ", "c", "$return->[1]p", "\"$cmd\"", @cargs, "(char *)NULL"),
+ ");\n");
+ } elsif(scalar @$returns == 1
+ and $returns->[0]->[0] eq 'pair-list') {
+ # Special case
+ my $return = $$returns[0];
+ push(@c, " return pairlist(",
+ join(", ", "c", "$return->[1]p", "\"$cmd\"",
+ @cargs,
+ "(char *)NULL"),
+ ");\n");
+ } else {
+ my $expected = 0;
+ for(my $n = 0; $n < scalar @$returns; ++$n) {
+ my $return = $returns->[$n];
+ my $type = $return->[0];
+ my $name = $return->[1];
+ if($type eq 'string'
+ or $type eq 'boolean'
+ or $type eq 'integer'
+ or $type eq 'time'
+ or $type eq 'user') {
+ ++$expected;
+ }
+ }
+ 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");
+ } elsif($type eq 'boolean') {
+ push(@c,
+ " if(boolean(\"$cmd\", v[$n], ${name}p))\n",
+ " return -1;\n");
+ } elsif($type eq 'integer') {
+ push(@c,
+ " *${name}p = atol(v[$n]);\n");
+ } elsif($type eq 'time') {
+ push(@c,
+ " *${name}p = atoll(v[$n]);\n");
+ } elsif($type eq 'user') {
+ push(@c,
+ " c->user = v[$n];\n");
+ } elsif($type eq 'body') {
+ push(@c,
+ " if(readlist(c, ${name}p, n${name}p))\n",
+ " return -1;\n");
+ } elsif($type eq 'queue') {
+ push(@c,
+ " if(readqueue(c, ${name}p))\n",
+ " return -1;\n");
+ } else {
+ die "$0: C API: unknown return type '$type' for '$name'\n";
+ }
+ }
+ push(@c, " return 0;\n");
+ # TODO xfree unconsumed split output
+ }
+ push(@c, "}\n\n");