1) size_t bundling an unbundling.
2) CDUMP_IGNORE to avoid saving struct members.
3) const handling (ie. ignore the keyword).
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);
{
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);
+}
* };
*/
#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;
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);
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 */
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]);
typelen = i - 1;
}
}
+ if (streq(tok[i], "CDUMP_IGNORE"))
+ goto skip;
}
i = typelen;
i++;
} while (tok[i] && !streq(tok[i], ";") && !strstarts(tok[i], "CDUMP_"));
+skip:
while (tok[i] && !streq(tok[i], ";"))
i++;
--- /dev/null
+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[];
--- /dev/null
+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);
+}
+
--- /dev/null
+#include <ccan/cdump/cdump_parse.c>
+#include <ccan/tap/tap.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+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();
+}
--- /dev/null
+/* 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;
+};