2012-05-12 22:26:59 +01:00
|
|
|
/* Pretty-printer for Hammer.
|
|
|
|
|
* Copyright (C) 2012 Meredith L. Patterson, Dan "TQ" Hirsch
|
|
|
|
|
*
|
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
|
* as published by the Free Software Foundation, version 2.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
*/
|
|
|
|
|
|
2012-05-11 23:42:17 +01:00
|
|
|
#define _GNU_SOURCE
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <glib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include "hammer.h"
|
2012-05-17 18:27:59 +02:00
|
|
|
#include <malloc.h>
|
2012-05-11 23:42:17 +01:00
|
|
|
|
|
|
|
|
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:
|
2012-05-18 18:43:02 +02:00
|
|
|
if (tok->sint < 0)
|
|
|
|
|
printf("%*ss -%#lx\n", indent, "", -tok->sint);
|
|
|
|
|
else
|
|
|
|
|
printf("%*ss %#lx\n", indent, "", tok->sint);
|
|
|
|
|
|
2012-05-11 23:42:17 +01:00
|
|
|
break;
|
|
|
|
|
case TT_UINT:
|
2012-05-18 18:43:02 +02:00
|
|
|
printf("%*su %#lx\n", indent, "", tok->uint);
|
2012-05-11 23:42:17 +01:00
|
|
|
break;
|
|
|
|
|
case TT_SEQUENCE: {
|
|
|
|
|
printf("%*s[\n", indent, "");
|
2012-05-17 15:51:19 +02:00
|
|
|
for (size_t i = 0; i < tok->seq->used; i++) {
|
|
|
|
|
pprint(tok->seq->elements[i], indent + delta, delta);
|
2012-05-11 23:42:17 +01:00
|
|
|
}
|
|
|
|
|
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;
|
2012-05-22 03:57:27 +02:00
|
|
|
if (!tok) {
|
|
|
|
|
append_buf(buf, "NULL", 4);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2012-05-11 23:42:17 +01:00
|
|
|
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++) {
|
2012-05-13 01:01:26 +01:00
|
|
|
const char *HEX = "0123456789abcdef";
|
2012-05-11 23:42:17 +01:00
|
|
|
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:
|
2012-05-18 18:43:02 +02:00
|
|
|
if (tok->sint < 0)
|
|
|
|
|
len = asprintf(&tmpbuf, "s-%#lx", -tok->sint);
|
|
|
|
|
else
|
|
|
|
|
len = asprintf(&tmpbuf, "s%#lx", tok->sint);
|
2012-05-11 23:42:17 +01:00
|
|
|
append_buf(buf, tmpbuf, len);
|
2012-05-17 18:27:59 +02:00
|
|
|
free(tmpbuf);
|
2012-05-11 23:42:17 +01:00
|
|
|
break;
|
|
|
|
|
case TT_UINT:
|
2012-05-18 18:43:02 +02:00
|
|
|
len = asprintf(&tmpbuf, "u%#lx", tok->uint);
|
2012-05-11 23:42:17 +01:00
|
|
|
append_buf(buf, tmpbuf, len);
|
2012-05-17 18:27:59 +02:00
|
|
|
free(tmpbuf);
|
2012-05-11 23:42:17 +01:00
|
|
|
break;
|
2012-05-12 21:53:54 +01:00
|
|
|
case TT_ERR:
|
|
|
|
|
append_buf(buf, "ERR", 3);
|
|
|
|
|
break;
|
2012-05-11 23:42:17 +01:00
|
|
|
case TT_SEQUENCE: {
|
|
|
|
|
append_buf_c(buf, '(');
|
2012-05-17 15:51:19 +02:00
|
|
|
for (size_t i = 0; i < tok->seq->used; i++) {
|
|
|
|
|
if (i > 0)
|
2012-05-11 23:42:17 +01:00
|
|
|
append_buf_c(buf, ' ');
|
2012-05-17 15:51:19 +02:00
|
|
|
unamb_sub(tok->seq->elements[i], buf);
|
2012-05-11 23:42:17 +01:00
|
|
|
}
|
|
|
|
|
append_buf_c(buf, ')');
|
2012-05-12 01:28:52 +01:00
|
|
|
}
|
|
|
|
|
break;
|
2012-05-11 23:42:17 +01:00
|
|
|
default:
|
2012-05-12 01:28:52 +01:00
|
|
|
fprintf(stderr, "Unexpected token type %d\n", tok->token_type);
|
2012-05-11 23:42:17 +01:00
|
|
|
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);
|
2012-05-17 15:51:19 +02:00
|
|
|
append_buf_c(&buf, 0);
|
2012-05-11 23:42:17 +01:00
|
|
|
return buf.output;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|