diff --git a/src/read.c b/src/read.c index f8836e44..dfcc63d4 100644 --- a/src/read.c +++ b/src/read.c @@ -4,6 +4,7 @@ #include #include +#include #include "picrin.h" #include "picrin/error.h" #include "picrin/pair.h" @@ -354,6 +355,50 @@ read_string(pic_state *pic, struct pic_port *port, char c) return pic_obj_value(str); } +static pic_value +read_pipe(pic_state *pic, struct pic_port *port, char c) +{ + char *buf; + size_t size, cnt; + pic_sym sym; + /* Currently supports only ascii chars */ + char HEX_BUF[3]; + size_t i = 0; + + size = 256; + buf = pic_alloc(pic, size); + cnt = 0; + while ((c = next(port)) != '|') { + if (c == '\\') { + switch (c = next(port)) { + case 'a': c = '\a'; break; + case 'b': c = '\b'; break; + case 't': c = '\t'; break; + case 'n': c = '\n'; break; + case 'r': c = '\r'; break; + case 'x': + i = 0; + while ((HEX_BUF[i++] = next(port)) != ';') { + if (i >= sizeof HEX_BUF) + read_error(pic, "expected ';'"); + } + c = (char)strtol(HEX_BUF, NULL, 16); + break; + } + } + buf[cnt++] = c; + if (cnt >= size) { + buf = pic_realloc(pic, buf, size *= 2); + } + } + buf[cnt] = '\0'; + + sym = pic_intern_cstr(pic, buf); + pic_free(pic, buf); + + return pic_sym_value(sym); +} + static pic_value read_unsigned_blob(pic_state *pic, struct pic_port *port, char c) { @@ -584,6 +629,8 @@ read_nullable(pic_state *pic, struct pic_port *port, char c) return read_comma(pic, port, c); case '"': return read_string(pic, port, c); + case '|': + return read_pipe(pic, port, c); case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return read_number(pic, port, c);