klisp

an open source interpreter for the Kernel Programming Language.
git clone http://git.hanabi.in/repos/klisp.git
Log | Files | Refs | README

commit 4f00aa5516a9d1e59771438fd76ad28cbbc12ec9
parent 2dc55373360d82776f2732e47548ee6391c8ac98
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Tue, 22 Feb 2011 19:59:26 -0300

Bugfix: escaped " and \ in strings (kwrite). Added support for printing embedded '\0's in strings.

Diffstat:
Msrc/kstring.h | 1+
Msrc/kwrite.c | 58+++++++++++++++++++++++++++++++++++++++++++++-------------
2 files changed, 46 insertions(+), 13 deletions(-)

diff --git a/src/kstring.h b/src/kstring.h @@ -12,6 +12,7 @@ /* TEMP: for now all strings are mutable */ TValue kstring_new(const char *, uint32_t); #define kstring_buf(tv_) (((Symbol *) ((tv_).tv.v.gc))->b) +#define kstring_size(tv_) (((Symbol *) ((tv_).tv.v.gc))->size) /* The only empty string */ /* TEMP: for now initialized in ktoken.c */ diff --git a/src/kwrite.c b/src/kwrite.c @@ -18,14 +18,6 @@ #include "kstring.h" #include "ksymbol.h" -/* -** TODO: -** -** - Write a print function for strings that works on strings -** with embedded '\0's -** -*/ - /* TODO: move to the global state */ FILE *kwrite_file = NULL; /* TEMP: for now use fixints for shared refs */ @@ -56,6 +48,48 @@ int kw_dstack_i; #define kw_flush() fflush(kwrite_file) /* +** Helper for printing strings (correcly escapes backslashes and +** double quotes & prints embedded '\0's). It includes the surrounding +** double quotes. +*/ +void kw_print_string(TValue str) +{ + int size = kstring_size(str); + char *buf = kstring_buf(str); + char *ptr = buf; + int i = 0; + + kw_printf("\""); + + while (i < size) { + /* find the longest printf-able substring to avoid calling printf + for every char */ + for (ptr = buf; i < size && *ptr != '\0' + && *ptr != '\\' && *ptr != '"'; i++, ptr++) + ; + + /* NOTE: this work even if ptr == buf (which can only happen the + first or last time) */ + char ch = *ptr; + *ptr = '\0'; + printf("%s", buf); + *ptr = ch; + + while(i < size && (*ptr == '\0' || *ptr == '\\' || *ptr == '"')) { + if (*ptr == '\0') + printf("%c", '\0'); /* this may not show in the terminal */ + else + printf("\\%c", *ptr); + i++; + ptr++; + } + buf = ptr; + } + + kw_printf("\""); +} + +/* ** Writer initialization */ void kwrite_init() @@ -243,16 +277,14 @@ void kwrite_fsm() } else { TValue mark = kget_mark(obj); if (ttisboolean(mark)) { /* simple string (only once) */ - /* XXX: this doesn't correctly print strings with '\0's */ - kw_printf("\"%s\"", kstring_buf(obj)); + kw_print_string(obj); } else if (ivalue(mark) < 0) { /* string with no assigned # */ /* TEMP: for now only fixints in shared refs */ assert(kw_shared_count >= 0); kset_mark(obj, i2tv(kw_shared_count)); - /* XXX: this doesn't correctly print strings with '\0's */ - kw_printf("#%" PRId32 "=\"%s\"", kw_shared_count, - kstring_buf(obj)); + kw_printf("#%" PRId32 "=", kw_shared_count); kw_shared_count++; + kw_print_string(obj); } else { /* string with an assigned number */ kw_printf("#%" PRId32 "#", ivalue(mark)); }