From c7beb6054603bcbabfd781abeaf8de01d3a60e56 Mon Sep 17 00:00:00 2001
From: Dan Hirsch <thequux@thequux.com>
Date: Fri, 11 May 2012 23:42:17 +0100
Subject: [PATCH] Actually added pretty printer this time

---
 src/pprint.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 138 insertions(+)
 create mode 100644 src/pprint.c

diff --git a/src/pprint.c b/src/pprint.c
new file mode 100644
index 00000000..6aad7b3c
--- /dev/null
+++ b/src/pprint.c
@@ -0,0 +1,138 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <glib.h>
+#include <string.h>
+#include "hammer.h"
+
+typedef struct pp_state {
+  int delta;
+  int indent_amt;
+  int at_bol;
+} pp_state_t;
+
+void pprint(const parsed_token_t* tok, int indent, int delta) {
+  switch (tok->token_type) {
+  case TT_NONE:
+    printf("%*snull\n", indent, "");
+    break;
+  case TT_BYTES:
+    if (tok->bytes.len == 0)
+      printf("%*s<>\n", indent, "");
+    else {
+      printf("%*s", indent, "");
+      for (size_t i = 0; i < tok->bytes.len; i++) {
+	printf("%c%02hhx",
+	       (i == 0) ? '<' : '.',
+	       tok->bytes.token[i]);
+      }
+      printf(">\n");
+    }
+    break;
+  case TT_SINT:
+    printf("%*su %#lx\n", indent, "", tok->sint);
+    break;
+  case TT_UINT:
+     printf("%*ss %#lx\n", indent, "", tok->uint);
+    break;
+  case TT_SEQUENCE: {
+    GSequenceIter *it;
+    printf("%*s[\n", indent, "");
+    for (it = g_sequence_get_begin_iter(tok->seq);
+	 !g_sequence_iter_is_end(it);
+	 it = g_sequence_iter_next(it)) {
+      parsed_token_t* subtok = g_sequence_get(it);
+      pprint(subtok, indent + delta, delta);
+    }
+    printf("%*s]\n", indent, "");
+  } // TODO: implement this
+  default:
+    g_assert_not_reached();
+  }
+}
+
+
+struct result_buf {
+  char* output;
+  size_t len;
+  size_t capacity;
+};
+
+static inline void ensure_capacity(struct result_buf *buf, int amt) {
+  while (buf->len + amt >= buf->capacity)
+    buf->output = g_realloc(buf->output, buf->capacity *= 2);
+}
+
+static inline void append_buf(struct result_buf *buf, const char* input, int len) {
+  ensure_capacity(buf, len);
+  memcpy(buf->output + buf->len, input, len);
+  buf->len += len;
+}
+
+static inline void append_buf_c(struct result_buf *buf, char v) {
+  ensure_capacity(buf, 1);
+  buf->output[buf->len++] = v;
+}
+
+static void unamb_sub(const parsed_token_t* tok, struct result_buf *buf) {
+  char* tmpbuf;
+  int len;
+  switch (tok->token_type) {
+  case TT_NONE:
+    append_buf(buf, "null", 4);
+    break;
+  case TT_BYTES:
+    if (tok->bytes.len == 0)
+      append_buf(buf, "<>", 2);
+    else {
+      for (size_t i = 0; i < tok->bytes.len; i++) {
+	const char *HEX = "0123456789ABCDEF";
+	append_buf_c(buf, (i == 0) ? '<': '.');
+	char c = tok->bytes.token[i];
+	append_buf_c(buf, HEX[(c >> 4) & 0xf]);
+	append_buf_c(buf, HEX[(c >> 0) & 0xf]);
+      }
+      append_buf_c(buf, '>');
+    }
+    break;
+  case TT_SINT:
+    len = asprintf(&tmpbuf, "u%#lx", tok->sint);
+    append_buf(buf, tmpbuf, len);
+    break;
+  case TT_UINT:
+    len = asprintf(&tmpbuf, "s%#lx\n", tok->uint);
+    append_buf(buf, tmpbuf, len);
+    break;
+  case TT_SEQUENCE: {
+    GSequenceIter *it;
+    int at_begin = 1;
+    append_buf_c(buf, '(');
+    for (it = g_sequence_get_begin_iter(tok->seq);
+	 !g_sequence_iter_is_end(it);
+	 it = g_sequence_iter_next(it)) {
+      parsed_token_t* subtok = g_sequence_get(it);
+      if (at_begin)
+	at_begin = 0;
+      else
+	append_buf_c(buf, ' ');
+      unamb_sub(subtok, buf);
+    }
+    append_buf_c(buf, ')');
+  } // TODO: implement this
+  default:
+    g_assert_not_reached();
+  }
+}
+  
+
+char* write_result_unamb(const parsed_token_t* tok) {
+  struct result_buf buf = {
+    .output = g_malloc0(16),
+    .len = 0,
+    .capacity = 16
+  };
+  unamb_sub(tok, &buf);
+  return buf.output;
+}
+  
+
+
-- 
GitLab