summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mem.h4
-rw-r--r--read.c35
2 files changed, 32 insertions, 7 deletions
diff --git a/mem.h b/mem.h
index 84fa4bb..87f817b 100644
--- a/mem.h
+++ b/mem.h
@@ -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);
diff --git a/read.c b/read.c
index 5b3f43e..26dcfd5 100644
--- a/read.c
+++ b/read.c
@@ -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) {