Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: rustyrussell/pettycoin
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 60f0944b0f86
Choose a base ref
...
head repository: rustyrussell/pettycoin
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 6ae4edae3b61
Choose a head ref
  • 2 commits
  • 13 files changed
  • 1 contributor

Commits on Nov 11, 2014

  1. ccan/cdump: import.

    Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
    rustyrussell committed Nov 11, 2014
    Copy the full SHA
    4c1dbd1 View commit details
  2. ecode_names, pkt_names: generate using ccan/cdump.

    The sed command worked, but this is a nice test for cdump.
    
    Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
    rustyrussell committed Nov 11, 2014
    Copy the full SHA
    6ae4eda View commit details
12 changes: 7 additions & 5 deletions Makefile.in
Original file line number Diff line number Diff line change
@@ -19,7 +19,7 @@ PETTYCOIN_GATEWAY_OBJS := pettycoin-gateway.o hex.o json.o pettycoin_dir.o base5
DUMBWALLET_OBJS := dumbwallet.o hex.o json.o pettycoin_dir.o base58.o create_tx.o marshal.o signature.o minimal_log.o shadouble.o tx.o

BINS := pettycoin-generate mkgenesis pettycoin sizes mkpriv pettycoin-tx pettycoin-query petty-addr pettycoin-gateway dumbwallet
CCAN_OBJS := ccan-asort.o ccan-breakpoint.o ccan-tal.o ccan-tal-path.o ccan-tal-str.o ccan-take.o ccan-list.o ccan-str.o ccan-opt-helpers.o ccan-opt.o ccan-opt-parse.o ccan-opt-usage.o ccan-read_write_all.o ccan-htable.o ccan-io-io.o ccan-io-poll.o ccan-timer.o ccan-time.o ccan-noerr.o ccan-hash.o ccan-isaac64.o ccan-net.o ccan-err.o ccan-tal-grab_file.o ccan-strmap.o
CCAN_OBJS := ccan-asort.o ccan-breakpoint.o ccan-tal.o ccan-tal-path.o ccan-tal-str.o ccan-take.o ccan-list.o ccan-str.o ccan-opt-helpers.o ccan-opt.o ccan-opt-parse.o ccan-opt-usage.o ccan-read_write_all.o ccan-htable.o ccan-io-io.o ccan-io-poll.o ccan-timer.o ccan-time.o ccan-noerr.o ccan-hash.o ccan-isaac64.o ccan-net.o ccan-err.o ccan-tal-grab_file.o ccan-strmap.o ccan-cdump.o
CCANDIR=ccan/
VERSION:=$(shell git describe --dirty --always 2>/dev/null || echo Unknown)
CFLAGS = @CFLAGS@ -I$(CCANDIR) -DVERSION=\"$(VERSION)\"
@@ -83,11 +83,11 @@ genesis.c: mkgenesis
.PHONY: test
check test: check-include-order

ecode_names.c: protocol_ecode.h Makefile
(echo '#include "ecode_names.h"'; echo 'struct ecode_names ecode_names[] = {'; sed -n 's/^\t\(PROTOCOL_ECODE_[A-Z0-9_]*\)/\t{ \1, "\1" }/p' < $<; echo ' { 0, NULL } };') > $@
ecode_names.c: protocol_ecode.h Makefile tools/cdump-enum-names
tools/cdump-enum-names $< protocol_ecode ecode > $@

pkt_names.c: protocol_net.h Makefile
(echo '#include "pkt_names.h"'; echo 'struct pkt_names pkt_names[] = {'; sed -n 's/^\t\(PROTOCOL_PKT_[A-Z0-9_]*\)/\t{ \1, "\1" }/p' < $<; echo ' { 0, NULL } };') > $@
pkt_names.c: protocol_net.h Makefile tools/cdump-enum-names
tools/cdump-enum-names $< protocol_pkt_type pkt > $@

check-include-order:
@for f in *.c; do if [ "$$(grep '^#include' < $$f)" != "$$(grep '^#include' < $$f | LC_ALL=C sort)" ]; then echo "$$f:1: includes out of order"; grep '^#include' < $$f; echo VERSUS; grep '^#include' < $$f | LC_ALL=C sort; exit 1; fi; done
@@ -153,6 +153,8 @@ ccan-err.o: $(CCANDIR)/ccan/err/err.c
$(CC) $(CFLAGS) -c -o $@ $<
ccan-strmap.o: $(CCANDIR)/ccan/strmap/strmap.c
$(CC) $(CFLAGS) -c -o $@ $<
ccan-cdump.o: $(CCANDIR)/ccan/cdump/cdump.c
$(CC) $(CFLAGS) -c -o $@ $<

include tools/Makefile
include test/Makefile
1 change: 1 addition & 0 deletions ccan/ccan/cdump/LICENSE
94 changes: 94 additions & 0 deletions ccan/ccan/cdump/_info
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#include "config.h"
#include <stdio.h>
#include <string.h>

/**
* cdump - routines to parse simple C structures.
*
* This code is designed to produce data structures summarizing C code.
* It only operates on simple, well-formed C code (eg. specific headers
* which you want to autogenerate from), but it should be fairly easy to
* enhance if desired.
*
* Author: Rusty Russell <rusty@rustcorp.com.au>
* License: BSD-MIT
*
* Example:
* // Creates a simple print function for a structure.
* #include <ccan/cdump/cdump.h>
* #include <ccan/tal/grab_file/grab_file.h>
* #include <ccan/err/err.h>
*
* static void print_as(const char *fmt, const char *member_name)
* {
* printf("\tprintf(\"%%s:%s\\n\", \"%s\", s->%s);\n",
* fmt, member_name, member_name);
* }
*
* int main(int argc, char *argv[])
* {
* char *code, *problems;
* struct cdump_definitions *defs;
* int i, j;
*
* // Read code from stdin.
* code = grab_file(NULL, NULL);
*
* defs = cdump_extract(NULL, code, &problems);
* if (!defs)
* errx(1, "Parsing stdin: %s", problems);
*
* for (i = 1; i < argc; i++) {
* struct cdump_type *t = strmap_get(&defs->structs, argv[i]);
* if (!t)
* errx(1, "Could not find struct %s", argv[i]);
*
* printf("void print_struct_%s(const struct %s *s)\n"
* "{\n", argv[i], argv[i]);
* for (j = 0; j < tal_count(t->u.members); j++) {
* const struct cdump_member *m = t->u.members + j;
* switch (m->type->kind) {
* case CDUMP_STRUCT:
* case CDUMP_UNION:
* case CDUMP_ARRAY:
* // Too hard for this simple example.
* printf("\tprintf(\"%%s:???\\n\", \"%s\");\n",
* m->name);
* break;
* case CDUMP_ENUM:
* print_as("%i", m->name);
* break;
* case CDUMP_POINTER:
* print_as("%p", m->name);
* break;
* case CDUMP_UNKNOWN:
* if (!strcmp(m->type->name, "int"))
* print_as("%i", m->name);
* else if (!strcmp(m->type->name, "long int"))
* print_as("%li", m->name);
* else if (!strcmp(m->type->name, "unsigned int"))
* print_as("%u", m->name);
* // etc...
* break;
* }
* }
* printf("}\n");
* }
* return 0;
* }
*/
int main(int argc, char *argv[])
{
/* Expect exactly one argument */
if (argc != 2)
return 1;

if (strcmp(argv[1], "depends") == 0) {
printf("ccan/tal\n");
printf("ccan/tal/str\n");
printf("ccan/strmap\n");
return 0;
}

return 1;
}
547 changes: 547 additions & 0 deletions ccan/ccan/cdump/cdump.c

Large diffs are not rendered by default.

96 changes: 96 additions & 0 deletions ccan/ccan/cdump/cdump.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/* MIT (BSD) license - see LICENSE file for details */
#ifndef CCAN_CDUMP_H
#define CCAN_CDUMP_H
#include <ccan/strmap/strmap.h>
#include <ccan/tal/tal.h>

enum cdump_type_kind {
CDUMP_STRUCT,
CDUMP_UNION,
CDUMP_ENUM,
CDUMP_ARRAY,
CDUMP_POINTER,
CDUMP_UNKNOWN
};

struct cdump_member {
const char *name;
/* const, volatile */
const char *qualifiers;
struct cdump_type *type;
};

struct cdump_enum_val {
const char *name;
/* Either NULL, or whatever follows '=' sign */
const char *value;
};

struct cdump_array {
const char *size;
struct cdump_type *type;
};

struct cdump_type {
enum cdump_type_kind kind;
const char *name;
union {
/* CDUMP_STRUCT / CDUMP_UNION: array */
struct cdump_member *members;
/* CDUMP_ENUM: array */
struct cdump_enum_val *enum_vals;
/* CDUMP_ARRAY */
struct cdump_array arr;
/* CDUMP_POINTER */
const struct cdump_type *ptr;
} u;
};

/* The map of typenames to definitions */
struct cdump_map {
STRMAP_MEMBERS(struct cdump_type *);
};

struct cdump_definitions {
struct cdump_map enums;
struct cdump_map structs;
struct cdump_map unions;
};

/**
* cdump_extract - extract definitions from simple C code.
* @ctx: context to tal() the return and @problems from (or NULL)
* @code: a nul-terminated string of C definitions
* @problems: a pointer to a char * to report problems (or NULL)
*
* This function parses @code and extracts enum, struct and union definitions
* into the return. If there is a parse error, it will return NULL and
* allocate a problem string for human consumption.
*
* Example:
* // Returns name of first field of 'struct @name' in @code.
* static const char *first_field_of_struct(const char *code,
* const char *name)
* {
* char *problems;
* struct cdump_definitions *defs;
* struct cdump_type *t;
*
* defs = cdump_extract(NULL, code, &problems);
* if (!defs) {
* fprintf(stderr, "%s", problems);
* tal_free(problems);
* return NULL;
* }
* t = strmap_get(&defs->structs, name);
* if (!t) {
* fprintf(stderr, "Couldn't find struct %s", name);
* return NULL;
* }
* assert(t->kind == CDUMP_STRUCT);
* return t->u.members[0].name;
* }
*/
struct cdump_definitions *cdump_extract(const tal_t *ctx, const char *code,
char **problems);
#endif /* CCAN_CDUMP_H */
34 changes: 34 additions & 0 deletions ccan/ccan/cdump/test/run-enum-comma.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include <ccan/cdump/cdump.h>
/* Include the C files directly. */
#include <ccan/cdump/cdump.c>
#include <ccan/tap/tap.h>

int main(void)
{
struct cdump_definitions *defs;
const struct cdump_type *t;
char *problems;

/* This is how many tests you plan to run */
plan_tests(12);

defs = cdump_extract(NULL, "enum foo { BAR, BAZ, };", &problems);
ok1(defs);
ok1(!problems);

ok1(strmap_empty(&defs->structs));
ok1(strmap_empty(&defs->unions));
t = strmap_get(&defs->enums, "foo");
ok1(t);
ok1(t->kind == CDUMP_ENUM);
ok1(streq(t->name, "foo"));
ok1(tal_count(t->u.enum_vals) == 2);
ok1(streq(t->u.enum_vals[0].name, "BAR"));
ok1(!t->u.enum_vals[0].value);
ok1(streq(t->u.enum_vals[1].name, "BAZ"));
ok1(!t->u.enum_vals[1].value);
tal_free(defs);

/* This exits depending on whether all tests passed */
return exit_status();
}
43 changes: 43 additions & 0 deletions ccan/ccan/cdump/test/run-forward-decl.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#include <ccan/cdump/cdump.h>
/* Include the C files directly. */
#include <ccan/cdump/cdump.c>
#include <ccan/tap/tap.h>

int main(void)
{
struct cdump_definitions *defs;
const struct cdump_type *t, *t2;
char *ctx = tal(NULL, char), *problems;

/* This is how many tests you plan to run */
plan_tests(16);

defs = cdump_extract(ctx, "struct foo { struct bar *bar; };\n"
"struct bar { int x; };", &problems);
ok1(defs);
ok1(tal_parent(defs) == ctx);
ok1(!problems);

t = strmap_get(&defs->structs, "foo");
ok1(t);
t2 = strmap_get(&defs->structs, "bar");
ok1(t2);

ok1(t2->kind == CDUMP_STRUCT);
ok1(streq(t2->name, "bar"));
ok1(tal_count(t2->u.members) == 1);
ok1(t2->u.members[0].type->kind == CDUMP_UNKNOWN);
ok1(streq(t2->u.members[0].type->name, "int"));

ok1(t->kind == CDUMP_STRUCT);
ok1(streq(t->name, "foo"));
ok1(tal_count(t->u.members) == 1);
ok1(streq(t->u.members[0].name, "bar"));
ok1(t->u.members[0].type->kind == CDUMP_POINTER);
ok1(t->u.members[0].type->u.ptr == t2);

tal_free(ctx);

/* This exits depending on whether all tests passed */
return exit_status();
}
130 changes: 130 additions & 0 deletions ccan/ccan/cdump/test/run-qualifiers.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#include <ccan/cdump/cdump.h>
/* Include the C files directly. */
#include <ccan/cdump/cdump.c>
#include <ccan/tap/tap.h>

int main(void)
{
struct cdump_definitions *defs;
const struct cdump_type *t, *p;
char *ctx = tal(NULL, char), *problems;

/* This is how many tests you plan to run */
plan_tests(63);

defs = cdump_extract(ctx,
"struct foo {\n"
" long l;\n"
" long int li;\n"
" unsigned long *ulp;\n"
" unsigned long int *ulip;\n"
"};", &problems);
ok1(defs);
ok1(tal_parent(defs) == ctx);
ok1(!problems);

ok1(strmap_empty(&defs->enums));
ok1(strmap_empty(&defs->unions));
t = strmap_get(&defs->structs, "foo");
ok1(t);
ok1(t->kind == CDUMP_STRUCT);
ok1(streq(t->name, "foo"));
ok1(tal_count(t->u.members) == 4);

ok1(streq(t->u.members[0].name, "l"));
p = t->u.members[0].type;
ok1(p->kind == CDUMP_UNKNOWN);
ok1(streq(p->name, "long"));

ok1(streq(t->u.members[1].name, "li"));
p = t->u.members[1].type;
ok1(p->kind == CDUMP_UNKNOWN);
ok1(streq(p->name, "long int"));

ok1(streq(t->u.members[2].name, "ulp"));
p = t->u.members[2].type;
ok1(p->kind == CDUMP_POINTER);
p = p->u.ptr;
ok1(p->kind == CDUMP_UNKNOWN);
ok1(streq(p->name, "unsigned long"));

ok1(streq(t->u.members[3].name, "ulip"));
p = t->u.members[3].type;
ok1(p->kind == CDUMP_POINTER);
p = p->u.ptr;
ok1(p->kind == CDUMP_UNKNOWN);
ok1(streq(p->name, "unsigned long int"));

defs = cdump_extract(ctx,
"struct foo {\n"
" volatile long vl;\n"
" const long cl;\n"
" volatile const long long int *vclli;\n"
"};", &problems);
ok1(defs);
ok1(tal_parent(defs) == ctx);
ok1(!problems);

ok1(strmap_empty(&defs->enums));
ok1(strmap_empty(&defs->unions));
t = strmap_get(&defs->structs, "foo");
ok1(t);
ok1(t->kind == CDUMP_STRUCT);
ok1(streq(t->name, "foo"));
ok1(tal_count(t->u.members) == 3);

ok1(streq(t->u.members[0].name, "vl"));
ok1(streq(t->u.members[0].qualifiers, "volatile"));
p = t->u.members[0].type;
ok1(p->kind == CDUMP_UNKNOWN);
ok1(streq(p->name, "long"));

ok1(streq(t->u.members[1].name, "cl"));
ok1(streq(t->u.members[1].qualifiers, "const"));
p = t->u.members[1].type;
ok1(p->kind == CDUMP_UNKNOWN);
ok1(streq(p->name, "long"));

ok1(streq(t->u.members[2].name, "vclli"));
ok1(streq(t->u.members[2].qualifiers, "volatile const"));
p = t->u.members[2].type;
ok1(p->kind == CDUMP_POINTER);
p = p->u.ptr;
ok1(p->kind == CDUMP_UNKNOWN);
ok1(streq(p->name, "long long int"));

defs = cdump_extract(ctx,
"struct foo {\n"
" volatile struct bar *a, b;\n"
"};", &problems);
ok1(defs);
ok1(tal_parent(defs) == ctx);
ok1(!problems);

ok1(strmap_empty(&defs->enums));
ok1(strmap_empty(&defs->unions));
t = strmap_get(&defs->structs, "foo");
ok1(t);
ok1(t->kind == CDUMP_STRUCT);
ok1(streq(t->name, "foo"));
ok1(tal_count(t->u.members) == 2);

ok1(streq(t->u.members[0].name, "a"));
ok1(streq(t->u.members[0].qualifiers, "volatile"));
p = t->u.members[0].type;
ok1(p->kind == CDUMP_POINTER);
p = p->u.ptr;
ok1(p->kind == CDUMP_STRUCT);
ok1(streq(p->name, "bar"));

ok1(streq(t->u.members[1].name, "b"));
ok1(streq(t->u.members[1].qualifiers, "volatile"));
p = t->u.members[1].type;
ok1(p->kind == CDUMP_STRUCT);
ok1(streq(p->name, "bar"));

tal_free(ctx);

/* This exits depending on whether all tests passed */
return exit_status();
}
152 changes: 152 additions & 0 deletions ccan/ccan/cdump/test/run.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
#include <ccan/cdump/cdump.h>
/* Include the C files directly. */
#include <ccan/cdump/cdump.c>
#include <ccan/tap/tap.h>

int main(void)
{
struct cdump_definitions *defs;
const struct cdump_type *t, *p;
char *ctx = tal(NULL, char), *problems;

/* This is how many tests you plan to run */
plan_tests(94);

defs = cdump_extract(ctx, "enum foo { BAR };", NULL);
ok1(defs);
ok1(tal_parent(defs) == ctx);

ok1(strmap_empty(&defs->structs));
ok1(strmap_empty(&defs->unions));
t = strmap_get(&defs->enums, "foo");
ok1(t);
ok1(t->kind == CDUMP_ENUM);
ok1(streq(t->name, "foo"));
ok1(tal_count(t->u.enum_vals) == 1);
ok1(streq(t->u.enum_vals[0].name, "BAR"));
ok1(!t->u.enum_vals[0].value);

defs = cdump_extract(ctx, "enum foo { BAR = 7 };", &problems);
ok1(defs);
ok1(tal_parent(defs) == ctx);
ok1(!problems);

ok1(strmap_empty(&defs->structs));
ok1(strmap_empty(&defs->unions));
t = strmap_get(&defs->enums, "foo");
ok1(t);
ok1(t->kind == CDUMP_ENUM);
ok1(streq(t->name, "foo"));
ok1(tal_count(t->u.enum_vals) == 1);
ok1(streq(t->u.enum_vals[0].name, "BAR"));
ok1(streq(t->u.enum_vals[0].value, "7"));

defs = cdump_extract(ctx, "enum foo { BAR = 7, BAZ, FUZZ };", &problems);
ok1(defs);
ok1(tal_parent(defs) == ctx);
ok1(!problems);

ok1(strmap_empty(&defs->structs));
ok1(strmap_empty(&defs->unions));
t = strmap_get(&defs->enums, "foo");
ok1(t);
ok1(t->kind == CDUMP_ENUM);
ok1(streq(t->name, "foo"));
ok1(tal_count(t->u.enum_vals) == 3);
ok1(streq(t->u.enum_vals[0].name, "BAR"));
ok1(streq(t->u.enum_vals[0].value, "7"));
ok1(streq(t->u.enum_vals[1].name, "BAZ"));
ok1(!t->u.enum_vals[1].value);
ok1(streq(t->u.enum_vals[2].name, "FUZZ"));
ok1(!t->u.enum_vals[2].value);

defs = cdump_extract(ctx, "struct foo { int x; };", &problems);
ok1(defs);
ok1(tal_parent(defs) == ctx);
ok1(!problems);

ok1(strmap_empty(&defs->enums));
ok1(strmap_empty(&defs->unions));
t = strmap_get(&defs->structs, "foo");
ok1(t);
ok1(t->kind == CDUMP_STRUCT);
ok1(streq(t->name, "foo"));
ok1(tal_count(t->u.members) == 1);
ok1(streq(t->u.members[0].name, "x"));
ok1(t->u.members[0].type->kind == CDUMP_UNKNOWN);
ok1(streq(t->u.members[0].type->name, "int"));

defs = cdump_extract(ctx, "struct foo { int x[5<< 1]; struct foo *next; struct unknown **ptrs[10]; };", &problems);
ok1(defs);
ok1(tal_parent(defs) == ctx);
ok1(!problems);

ok1(strmap_empty(&defs->enums));
ok1(strmap_empty(&defs->unions));
t = strmap_get(&defs->structs, "foo");
ok1(t);
ok1(t->kind == CDUMP_STRUCT);
ok1(streq(t->name, "foo"));
ok1(tal_count(t->u.members) == 3);

ok1(streq(t->u.members[0].name, "x"));
ok1(t->u.members[0].type->kind == CDUMP_ARRAY);
ok1(streq(t->u.members[0].type->u.arr.size, "5<< 1"));
ok1(t->u.members[0].type->u.arr.type->kind == CDUMP_UNKNOWN);
ok1(streq(t->u.members[0].type->u.arr.type->name, "int"));

ok1(streq(t->u.members[1].name, "next"));
ok1(t->u.members[1].type->kind == CDUMP_POINTER);
ok1(t->u.members[1].type->u.ptr == t);

ok1(streq(t->u.members[2].name, "ptrs"));
p = t->u.members[2].type;
ok1(p->kind == CDUMP_ARRAY);
ok1(streq(p->u.arr.size, "10"));
p = p->u.arr.type;
ok1(p->kind == CDUMP_POINTER);
p = p->u.ptr;
ok1(p->kind == CDUMP_POINTER);
p = p->u.ptr;
ok1(p->kind == CDUMP_STRUCT);
ok1(streq(p->name, "unknown"));
ok1(p->u.members == NULL);

/* We don't put undefined structs into definition maps. */
ok1(!strmap_get(&defs->structs, "unknown"));

/* unions and comments. */
defs = cdump_extract(ctx, "#if 0\n"
"/* Normal comment */\n"
"struct foo { int x[5 * 7/* Comment */]; };\n"
"// One-line comment\n"
"union bar { enum sometype x; union yun// Comment\n"
" y;};\n"
"#endif", &problems);
ok1(defs);
ok1(tal_parent(defs) == ctx);
ok1(!problems);
t = strmap_get(&defs->structs, "foo");
ok1(t);
ok1(tal_count(t->u.members) == 1);
ok1(streq(t->u.members[0].name, "x"));
ok1(t->u.members[0].type->kind == CDUMP_ARRAY);
ok1(streq(t->u.members[0].type->u.arr.size, "5 * 7"));
ok1(t->u.members[0].type->u.arr.type->kind == CDUMP_UNKNOWN);
ok1(streq(t->u.members[0].type->u.arr.type->name, "int"));

t = strmap_get(&defs->unions, "bar");
ok1(t);
ok1(tal_count(t->u.members) == 2);
ok1(streq(t->u.members[0].name, "x"));
ok1(t->u.members[0].type->kind == CDUMP_ENUM);
ok1(streq(t->u.members[0].type->name, "sometype"));
ok1(!t->u.members[0].type->u.enum_vals);
ok1(streq(t->u.members[1].name, "y"));
ok1(t->u.members[1].type->kind == CDUMP_UNION);
ok1(streq(t->u.members[1].type->name, "yun"));
ok1(!t->u.members[1].type->u.members);

/* This exits depending on whether all tests passed */
return exit_status();
}
1 change: 1 addition & 0 deletions ccan/ccan/cdump/tools/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
cdump-enumstr
52 changes: 52 additions & 0 deletions ccan/ccan/cdump/tools/cdump-enumstr.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include <ccan/cdump/cdump.h>
#include <ccan/tal/grab_file/grab_file.h>
#include <ccan/err/err.h>

static bool dump_map(const char *name, struct cdump_type *t, void *unused)
{
size_t i;

printf("struct {\n"
" enum %s v;\n"
" const char *name;\n"
"} enum_%s_names[] = {\n", name, name);

for (i = 0; i < tal_count(t->u.enum_vals); i++)
printf(" { %s, \"%s\" },\n",
t->u.enum_vals[i].name,
t->u.enum_vals[i].name);
printf(" { 0, NULL } };\n");
return true;
}

int main(int argc, char *argv[])
{
char *code, *problems;
struct cdump_definitions *defs;

if (argc < 2)
errx(1, "Usage: cdump-enumstr <filename> [<enums>...]");

code = grab_file(NULL, streq(argv[1], "-") ? NULL : argv[1]);
if (!code)
err(1, "Reading %s", argv[1]);

defs = cdump_extract(code, code, &problems);
if (!defs)
errx(1, "Parsing %s:\n%s", argv[1], problems);

if (argc == 2)
strmap_iterate(&defs->enums, dump_map, NULL);
else {
unsigned int i;
struct cdump_type *t;

for (i = 2; i < argc; i++) {
t = strmap_get(&defs->enums, argv[i]);
if (!t)
errx(1, "Enum %s not found", argv[i]);
dump_map(argv[i], t, NULL);
}
}
return 0;
}
4 changes: 3 additions & 1 deletion tools/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
TOOL_BINS = tools/make-peer-packet tools/spv-blocks
TOOL_BINS = tools/make-peer-packet tools/spv-blocks tools/cdump-enum-names

default-tools:
@echo Run make tools from top dir. >&2 && exit 1
@@ -7,6 +7,8 @@ tools: $(TOOL_BINS)

tools/make-peer-packet: tools/make-peer-packet.o netaddr.o tal_packet.o marshal.o minimal_log.o $(CCAN_OBJS)

tools/cdump-enum-names: tools/cdump-enum-names.o $(CCAN_OBJS)

clean: tools-clean
distclean: tools-distclean

42 changes: 42 additions & 0 deletions tools/cdump-enum-names.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include <ccan/cdump/cdump.h>
#include <ccan/tal/grab_file/grab_file.h>
#include <ccan/err/err.h>

static bool create_file(const char *name, struct cdump_type *t,
const char *prefix)
{
size_t i;

printf("/* Generated from enum %s by tools/cdump-enum-names */\n"
"#include \"%s_names.h\"\n"
"\n"
"struct %s_names %s_names[] = {\n",
name, prefix, prefix, prefix);

for (i = 0; i < tal_count(t->u.enum_vals); i++)
printf(" { %s, \"%s\" },\n",
t->u.enum_vals[i].name, t->u.enum_vals[i].name);
printf(" { 0, NULL }\n"
"};\n");
return true;
}

int main(int argc, char *argv[])
{
struct cdump_definitions *defs;
const char *code;
char *problems;

err_set_progname(argv[0]);
if (argc != 4)
errx(1, "Usage: %s <headerfile> <enum> <prefix>", argv[0]);
code = grab_file(NULL, argv[1]);
if (!code)
err(1, "Reading %s", argv[1]);
defs = cdump_extract(code, code, &problems);
if (!defs)
errx(1, "Parsing %s: %s", argv[1], problems);

create_file(argv[2], strmap_get(&defs->enums, argv[2]), argv[3]);
return 0;
}