{"thread":{"id":"23443","subject":"[EXPERIMENTAL PATCH] S-expression structured output backend","startedAt":"2010-04-13T10:23:25Z","lastAt":"2010-04-13T10:29:38Z","messageCount":2,"participants":["Ilari Liusvaara","Ping Yin"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"139410","messageId":"1271154205-5919-1-git-send-email-ilari.liusvaara@elisanet.fi","threadId":"23443","inReplyTo":null,"subject":"[EXPERIMENTAL PATCH] S-expression structured output backend","fromName":"Ilari Liusvaara","fromEmail":"ilari.liusvaara@elisanet.fi","sentAt":"2010-04-13T10:23:25Z","receivedAt":"2010-04-13T10:23:25Z","isPatch":true,"sender":{"key":"ilari.liusvaara@elisanet.fi","avatar":null},"body":"Add structured output mode 'sexp' that prints out canonical form\nS-expressions.\n\nSigned-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>\n---\n Makefile      |    1 +\n output-sexp.c |   76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n output.c      |    9 ++++++-\n output.h      |    3 +-\n 4 files changed, 87 insertions(+), 2 deletions(-)\n create mode 100644 output-sexp.c\n\ndiff --git a/Makefile b/Makefile\nindex d32a334..8b0fc21 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -582,6 +582,7 @@ LIB_OBJS += notes-cache.o\n LIB_OBJS += object.o\n LIB_OBJS += output.o\n LIB_OBJS += output-json.o\n+LIB_OBJS += output-sexp.o\n LIB_OBJS += output-normal.o\n LIB_OBJS += output-xml.o\n LIB_OBJS += output-zero.o\ndiff --git a/output-sexp.c b/output-sexp.c\nnew file mode 100644\nindex 0000000..df8d56b\n--- /dev/null\n+++ b/output-sexp.c\n@@ -0,0 +1,76 @@\n+#include \"git-compat-util.h\"\n+#include \"output.h\"\n+\n+static void sexp_str(FILE *file, const char *value)\n+{\n+\tfprintf(file, \"%llu:%s\", (uint64_t)strlen(value), value);\n+}\n+\n+static void sexp_container_start(FILE *file, const char *name)\n+{\n+\tfprintf(file, \"(\");\n+}\n+\n+static void sexp_container_end(FILE *file, const char *name)\n+{\n+\tfprintf(file, \")\");\n+}\n+\n+static void sexp_objitem_end(FILE *file, const char *name, int first)\n+{\n+\tfprintf(file, \")\");\n+}\n+\n+static void sexp_obj_item_start(FILE *file, const char *name, int first)\n+{\n+\tfprintf(file, \"(\");\n+\tsexp_str(file,name);\n+}\n+\n+static void sexp_bool(FILE *file, int value)\n+{\n+\tif (value)\n+\t\tsexp_str(file, \"true\");\n+\telse\n+\t\tsexp_str(file, \"false\");\n+}\n+\n+static void sexp_int_(FILE *file, int64_t value)\n+{\n+\tchar buffer[256];\n+\tsprintf(buffer, \"%lli\", value);\n+\tsexp_str(file, buffer);\n+}\n+\n+static void sexp_uint(FILE *file, uint64_t value)\n+{\n+\tchar buffer[256];\n+\tsprintf(buffer, \"%llu\", value);\n+\tsexp_str(file, buffer);\n+}\n+\n+static void sexp_double_(FILE *file, double value, int precision)\n+{\n+\tchar buffer[256];\n+\tsprintf(buffer, \"%.*f\", precision, value);\n+\tsexp_str(file, buffer);\n+}\n+\n+\n+struct output_ops output_sexp_ops = {\n+\tsexp_container_start,\n+\tsexp_container_end,\n+\tsexp_obj_item_start,\n+\tsexp_objitem_end,\n+\n+\tsexp_container_start,\n+\tsexp_container_end,\n+\tNULL,\n+\tNULL,\n+\n+\tsexp_bool,\n+\tsexp_str,\n+\tsexp_int_,\n+\tsexp_uint,\n+\tsexp_double_,\n+};\ndiff --git a/output.c b/output.c\nindex 3be1560..9d04cc4 100644\n--- a/output.c\n+++ b/output.c\n@@ -8,12 +8,14 @@ extern struct output_ops output_normal_ops;\n extern struct output_ops output_zero_ops;\n extern struct output_ops output_json_ops;\n extern struct output_ops output_xml_ops;\n+extern struct output_ops output_sexp_ops;\n \n struct output_ops *output_ops[] = {\n \t&output_normal_ops,\n \t&output_zero_ops,\n \t&output_json_ops,\n \t&output_xml_ops,\n+\t&output_sexp_ops,\n };\n \n enum output_style handle_output_arg(char *s)\n@@ -28,6 +30,8 @@ enum output_style handle_output_arg(char *s)\n \t\treturn OUTPUT_JSON;\n \telse if (!strcmp(s, \"xml\"))\n \t\treturn OUTPUT_XML;\n+\telse if (!strcmp(s, \"sexp\"))\n+\t\treturn OUTPUT_SEXP;\n \telse\n \t\tdie(\"Invalid output style '%s'\", s);\n }\n@@ -54,8 +58,11 @@ void output_end(struct output_context *context)\n \t * OUTPUT_NORMAL and OUTPUT_ZERO are special cases - the output format\n \t * is _already_ defined so we have to stick to the rules, we can't add\n \t * _anything_\n+\t *\n+\t * As for S-Expression output, no, canonical mode does not allow trailing\n+\t * newline, so suppress it.\n \t */\n-\tif (context->style > OUTPUT_ZERO)\n+\tif (context->style > OUTPUT_ZERO && context->style != OUTPUT_SEXP)\n \t\tfprintf(context->file, \"\\n\");\n \n \tfree(context);\ndiff --git a/output.h b/output.h\nindex cc0b921..7ee2cd7 100644\n--- a/output.h\n+++ b/output.h\n@@ -6,6 +6,7 @@ enum output_style {\n \tOUTPUT_ZERO,\n \tOUTPUT_JSON,\n \tOUTPUT_XML,\n+\tOUTPUT_SEXP,\n };\n \n struct output_ops {\n@@ -59,7 +60,7 @@ extern struct option OUTPUT_OPTION;\n \n #define OPT_OUTPUT(s, l, v) { OPTION_STRING, (s), (l), (v), \"style\",     \\\n \t\t\t      \"Use a structured output style, options: \" \\\n-\t\t\t      \"no, zero, json, xml (Default: zero)\",     \\\n+\t\t\t      \"no, zero, json, xml, sexp (Default: zero)\",     \\\n \t\t\t      PARSE_OPT_OPTARG, NULL, (intptr_t)\"zero\" }\n \n enum output_style handle_output_arg(char *s);\n-- \n1.7.0.2.282.g5b1c2\n"},{"id":"139412","messageId":"p2x46dff0321004130329gb21cefecn147b4f1b30152e25@mail.gmail.com","threadId":"23443","inReplyTo":"1271154205-5919-1-git-send-email-ilari.liusvaara@elisanet.fi","subject":"Re: [EXPERIMENTAL PATCH] S-expression structured output backend","fromName":"Ping Yin","fromEmail":"pkufranky@gmail.com","sentAt":"2010-04-13T10:29:38Z","receivedAt":"2010-04-13T10:29:38Z","isPatch":true,"sender":{"key":"pkufranky@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5346?v=4"},"body":"On Tue, Apr 13, 2010 at 6:23 PM, Ilari Liusvaara\n<ilari.liusvaara@elisanet.fi> wrote:\n> Add structured output mode 'sexp' that prints out canonical form\n> S-expressions.\n>\n> Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>\n> ---\n>  Makefile      |    1 +\n>  output-sexp.c |   76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\nI think it's better to put all output-* files in a separate directory.\n"}]}