From: Rusty Russell Date: Fri, 21 Jan 2011 03:36:26 +0000 (+1030) Subject: cdump: features which weren't in genparser X-Git-Url: http://git.ozlabs.org/?p=ccan-lca-2011.git;a=commitdiff_plain;h=d5713111bd392c112c689171e727ab1a4d90ad9e cdump: features which weren't in genparser 1) size_t bundling an unbundling. 2) CDUMP_IGNORE to avoid saving struct members. 3) const handling (ie. ignore the keyword). --- diff --git a/ccan/cdump/cdump.c b/ccan/cdump/cdump.c index f151cbf..a1b5519 100644 --- a/ccan/cdump/cdump.c +++ b/ccan/cdump/cdump.c @@ -725,6 +725,12 @@ bool cdump_unbundle_float(const void *ctx, void *ptr, const char *str) return true; } +bool cdump_unbundle_size_t(const void *ctx, void *ptr, const char *str) +{ + *(size_t *)ptr = strtoul(str, NULL, 10); + return true; +} + bool cdump_bundle_char(struct cdump_string *p, const void *ptr, unsigned indent) { return addshort(p, "%u", *(unsigned char *)ptr); @@ -754,3 +760,8 @@ bool cdump_bundle_float(struct cdump_string *p, const void *ptr, unsigned indent { return addshort(p, "%g", *(float *)ptr); } + +bool cdump_bundle_size_t(struct cdump_string *p, const void *ptr, unsigned indent) +{ + return addshort(p, "%zu", *(size_t *)ptr); +} diff --git a/ccan/cdump/cdump.h b/ccan/cdump/cdump.h index 70def69..05d5321 100644 --- a/ccan/cdump/cdump.h +++ b/ccan/cdump/cdump.h @@ -44,7 +44,20 @@ * }; */ #define CDUMP_ZEROTERM -#endif + +/** + * CDUMP_IGNORE - annotation for telling cdump_parse to ignore a member. + * + * This means it won't be bundled (and thus doesn't need to be understood) so + * on unbundling it will be all zero. + * + * Example: + * CDUMP_SAVED struct baz { + * char *p CDUMP_IGNORE; + * }; + */ +#define CDUMP_IGNORE +#endif /* CDUMP_PARSING */ struct cdump_desc; diff --git a/ccan/cdump/cdump_internal.h b/ccan/cdump/cdump_internal.h index 7e85f5f..eb50ff4 100644 --- a/ccan/cdump/cdump_internal.h +++ b/ccan/cdump/cdump_internal.h @@ -67,6 +67,7 @@ bool cdump_bundle_unsigned(struct cdump_string *p, const void *ptr, unsigned); bool cdump_bundle_time_t(struct cdump_string *p, const void *ptr, unsigned ind); bool cdump_bundle_double(struct cdump_string *p, const void *ptr, unsigned ind); bool cdump_bundle_float(struct cdump_string *p, const void *ptr, unsigned ind); +bool cdump_bundle_size_t(struct cdump_string *p, const void *ptr, unsigned ind); bool cdump_unbundle_char(const void *ctx, void *ptr, const char *str); bool cdump_unbundle_int(const void *ctx, void *ptr, const char *str); @@ -74,8 +75,11 @@ bool cdump_unbundle_unsigned(const void *ctx, void *ptr, const char *str); bool cdump_unbundle_time_t(const void *ctx, void *ptr, const char *str); bool cdump_unbundle_double(const void *ctx, void *ptr, const char *str); bool cdump_unbundle_float(const void *ctx, void *ptr, const char *str); +bool cdump_unbundle_size_t(const void *ctx, void *ptr, const char *str); #define cdump_bundle_unsigned_char cdump_bundle_char #define cdump_unbundle_unsigned_char cdump_unbundle_char +#define cdump_bundle_unsigned_int cdump_bundle_int +#define cdump_unbundle_unsigned_int cdump_unbundle_int #endif /* CCAN_CDUMP_INTERNAL */ diff --git a/ccan/cdump/cdump_parse.c b/ccan/cdump/cdump_parse.c index fea7df1..41fd5c5 100644 --- a/ccan/cdump/cdump_parse.c +++ b/ccan/cdump/cdump_parse.c @@ -127,6 +127,9 @@ static size_t parse_one(const void *ctx, const char *outer_struct_name, unbundle = talloc_strdup(ctx, "cdump_unbundle"); size = talloc_strdup(ctx, "sizeof("); for (i = 0; i < typelen; i++) { + /* Const is irrelevant for bundling. */ + if (streq(type[i], "const")) + continue; bundle = talloc_asprintf_append(bundle, "_%s", type[i]); unbundle = talloc_asprintf_append(unbundle, "_%s", type[i]); size = talloc_asprintf_append(size, "%s ", type[i]); @@ -177,6 +180,8 @@ static size_t parse_element(const void *ctx, const char *outer_struct_name, typelen = i - 1; } } + if (streq(tok[i], "CDUMP_IGNORE")) + goto skip; } i = typelen; @@ -188,6 +193,7 @@ static size_t parse_element(const void *ctx, const char *outer_struct_name, i++; } while (tok[i] && !streq(tok[i], ";") && !strstarts(tok[i], "CDUMP_")); +skip: while (tok[i] && !streq(tok[i], ";")) i++; diff --git a/ccan/cdump/test/example_generated-advanced-decls.h b/ccan/cdump/test/example_generated-advanced-decls.h new file mode 100644 index 0000000..7ec57f9 --- /dev/null +++ b/ccan/cdump/test/example_generated-advanced-decls.h @@ -0,0 +1,6 @@ +bool cdump_bundle_enum_state(struct cdump_string *, const void *, unsigned); +bool cdump_unbundle_enum_state(const void *, void *, const char *); +extern const struct cdump_enum cdump_enum_state[]; +bool cdump_bundle_struct_client(struct cdump_string *, const void *, unsigned); +bool cdump_unbundle_struct_client(const void *, void *, const char *); +extern const struct cdump_desc cdump_struct_client[]; diff --git a/ccan/cdump/test/example_generated-advanced-defs.h b/ccan/cdump/test/example_generated-advanced-defs.h new file mode 100644 index 0000000..7a704af --- /dev/null +++ b/ccan/cdump/test/example_generated-advanced-defs.h @@ -0,0 +1,38 @@ +const struct cdump_enum cdump_enum_state[] = { + { "SENDING_GREETING", SENDING_GREETING }, + { "RECEIVING_USER_QUESTION", RECEIVING_USER_QUESTION }, + { "SENDING_OTHER_QUESTION_PREFIX", SENDING_OTHER_QUESTION_PREFIX }, + { "SENDING_OTHER_QUESTION", SENDING_OTHER_QUESTION }, + { "RECEIVING_OTHER_ANSWER", RECEIVING_OTHER_ANSWER }, + { "SENDING_ANSWER_PREFIX", SENDING_ANSWER_PREFIX }, + { "SENDING_ANSWER", SENDING_ANSWER }, + { "FINISHED", FINISHED }, + { NULL, 0 } }; +bool cdump_bundle_enum_state(struct cdump_string *p, const void *ptr, unsigned indent) +{ + return cdump_bundle_enum(cdump_enum_state, p, ptr, indent); +} +bool cdump_unbundle_enum_state(const void *ctx, void *ptr, const char *str) +{ + return cdump_unbundle_enum(cdump_enum_state, ptr, str); +} + +const struct cdump_desc cdump_struct_client[] = { + { "node", 0, sizeof(struct list_node), offsetof(struct client, node), 0, NULL, 0, cdump_bundle_struct_list_node, cdump_unbundle_struct_list_node }, + { "state", 0, sizeof(enum state), offsetof(struct client, state), 0, NULL, CDUMP_FLAG_ALWAYS, cdump_bundle_enum_state, cdump_unbundle_enum_state }, + { "bytes_sent", 0, sizeof(size_t), offsetof(struct client, bytes_sent), 0, NULL, 0, cdump_bundle_size_t, cdump_unbundle_size_t }, + { "fd", 0, sizeof(int), offsetof(struct client, fd), 0, NULL, 0, cdump_bundle_int, cdump_unbundle_int }, + { "question", 1, sizeof(char), offsetof(struct client, question), 0, NULL, 0, cdump_bundle_char, cdump_unbundle_char }, + { "subclient", 1, sizeof(struct client), offsetof(struct client, subclient), 0, NULL, 0, cdump_bundle_struct_client, cdump_unbundle_struct_client }, + { "oracle", 1, sizeof(struct client), offsetof(struct client, oracle), 0, NULL, 0, cdump_bundle_struct_client, cdump_unbundle_struct_client }, + { "answer", 1, sizeof(char), offsetof(struct client, answer), 0, NULL, 0, cdump_bundle_char, cdump_unbundle_char }, + { NULL, 0, 0, 0, 0, NULL, 0, NULL, NULL } }; +bool cdump_bundle_struct_client(struct cdump_string *p, const void *ptr, unsigned indent) +{ + return cdump_bundle_struct(cdump_struct_client, p, ptr, indent); +} +bool cdump_unbundle_struct_client(const void *ctx, void *ptr, const char *str) +{ + return cdump_unbundle_struct(ctx, cdump_struct_client, ptr, str); +} + diff --git a/ccan/cdump/test/run-03-advanced-parse.c b/ccan/cdump/test/run-03-advanced-parse.c new file mode 100644 index 0000000..7471d7d --- /dev/null +++ b/ccan/cdump/test/run-03-advanced-parse.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include +#include + +static size_t diffoff(const char *a, const char *b) +{ + size_t i; + + for (i = 0; a[i]; i++) + if (b[i] != a[i]) + break; + return i; +} + +static char *read_file(const void *ctx, const char *fname) +{ + int fd = open(fname, O_RDONLY); + off_t len = lseek(fd, 0, SEEK_END); + char *ret = talloc_array(ctx, char, len + 1); + lseek(fd, 0, SEEK_SET); + read(fd, ret, len); + ret[len] = '\0'; + close(fd); + return ret; +} + +int main(int argc, char *argv[]) +{ + char *ret, *decls, *defs; + char *toplevel = talloc_strdup(NULL, "toplevel"); + char *header, *definitions, *declarations; + + plan_tests(5); + header = read_file(toplevel, "test/test_header_advanced.h"); + declarations = read_file(toplevel, "test/example_generated-advanced-decls.h"); + definitions = read_file(toplevel, "test/example_generated-advanced-defs.h"); + + ret = cdump_parse(toplevel, header, &decls, &defs); + ok1(ret == NULL); + ok(streq(decls, declarations), + "Declarations differ at %zu: ...'%.*s' vs ...'%.*s'", + diffoff(decls, declarations), + 30, decls + diffoff(decls, declarations), + 30, declarations + diffoff(decls, declarations)); + ok(streq(defs, definitions), + "Definitions differ at %zu: ...'%.*s' vs ...'%.*s'", + diffoff(defs, definitions), + 30, defs + diffoff(defs, definitions), + 30, definitions + diffoff(defs, definitions)); + + ok1(talloc_find_parent_byname(decls, "toplevel") == toplevel); + ok1(talloc_find_parent_byname(defs, "toplevel") == toplevel); + + talloc_free(toplevel); + return exit_status(); +} diff --git a/ccan/cdump/test/test_header_advanced.h b/ccan/cdump/test/test_header_advanced.h new file mode 100644 index 0000000..7cd47f5 --- /dev/null +++ b/ccan/cdump/test/test_header_advanced.h @@ -0,0 +1,31 @@ +/* This tests new features in cdump which weren't in genparser.pl */ +CDUMP_SAVED enum state { + SENDING_GREETING, + RECEIVING_USER_QUESTION, + SENDING_OTHER_QUESTION_PREFIX, + SENDING_OTHER_QUESTION, + RECEIVING_OTHER_ANSWER, + SENDING_ANSWER_PREFIX, + SENDING_ANSWER, + FINISHED +}; + +CDUMP_SAVED struct client { + /* In linked list clients */ + struct list_node node; + /* What are we doing today, brain? */ + enum state state; + /* How many bytes of the current string we sent so far. */ + size_t bytes_sent; + /* Our event info, and the file descriptor. */ + struct tevent_fd *fde CDUMP_IGNORE; + int fd; + /* The question we read from client. */ + const char *question; + /* Whose question this client is answering. */ + struct client *subclient; + /* Who is answering our question. */ + struct client *oracle; + /* The answer we send. */ + char *answer; +};