diff options
-rw-r--r-- | mem.h | 4 | ||||
-rw-r--r-- | read.c | 35 |
2 files changed, 32 insertions, 7 deletions
@@ -15,12 +15,12 @@ void *M(State *S, void *ptr, size_t old, size_t new); // needs len,cap,d fields #define ENSURE_CAP(S, darr, type, needed) \ - if (darr.cap < needed) { \ + do { if (darr.cap < needed) { \ size_t __newsz = next_pwrof2(needed); \ if (__newsz < 8) __newsz = 8; \ darr.d = RENEW_ARR(S, darr.d, type, darr.cap, __newsz); \ darr.cap = __newsz; \ - } + } } while (0) size_t next_pwrof2(size_t x); @@ -1,4 +1,5 @@ #include "val.h" +#include "mem.h" #include "util.h" #include <string.h> @@ -87,12 +88,36 @@ static Val symbol(Reader *R) { } } static Val string(Reader *R) { - char *start = R->c; - int len = 0; - // todo, escape sequences - while (*R->c != '"') { len += 1; next(R); } + struct { + size_t len; + size_t cap; + char *d; + } str; + str.len = 0; + str.cap = 0; + str.d = NULL; + + #define append(c) do { ENSURE_CAP(R->S, str, char, str.cap+1); str.d[str.len++] = c; } while (0) + + while (*R->c != '"') { + if (*R->c == '\\') { + next(R); + switch (*R->c) { + case '\\': append('\\'); break; + case 't': append('\t'); break; + case 'n': append('\n'); break; + case '"': append('"'); break; + } + next(R); + } else { + append(*R->c); + next(R); + } + } + append('\0'); + #undef append next(R); - ObjString *s = objstring_copy(R->S, start, len); + ObjString *s = objstring_take(R->S, str.d, str.len-1); return en(R, "quote", VAL_OBJ(s)); } static Val list(Reader *R, char closer) { |