From ba78a00d5ca07198747ee30f9b8a75f8653cc0e2 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Mon, 21 Oct 2013 11:12:34 +0900 Subject: [PATCH] take care of escaped characters in string --- include/picrin.h | 1 + src/port.c | 19 ++++++++++++++++++- src/scan.l | 19 ++++++++++++------- src/string.c | 16 ++++++++++++---- 4 files changed, 43 insertions(+), 12 deletions(-) diff --git a/include/picrin.h b/include/picrin.h index 3cf3fb36..b7cd063e 100644 --- a/include/picrin.h +++ b/include/picrin.h @@ -66,6 +66,7 @@ bool pic_eq_p(pic_state *, pic_value, pic_value); pic_value pic_intern_cstr(pic_state *, const char *); +pic_value pic_str_new(pic_state *, const char *, size_t); pic_value pic_str_new_cstr(pic_state *, const char *); bool pic_parse(pic_state *, const char *, pic_value *); diff --git a/src/port.c b/src/port.c index 32dfd8fc..894b2f2a 100644 --- a/src/port.c +++ b/src/port.c @@ -7,6 +7,7 @@ #include "picrin/string.h" static void write_pair(pic_state *pic, struct pic_pair *pair); +static void write_str(pic_state *pic, struct pic_string *str); static void write(pic_state *pic, pic_value obj) @@ -42,7 +43,9 @@ write(pic_state *pic, pic_value obj) printf("#", pic_port_ptr(obj)); break; case PIC_TT_STRING: - printf("\"%s\"", pic_str_ptr(obj)->str); + printf("\""); + write_str(pic, pic_str_ptr(obj)); + printf("\""); break; } } @@ -64,6 +67,20 @@ write_pair(pic_state *pic, struct pic_pair *pair) write(pic, pair->cdr); } +static void +write_str(pic_state *pic, struct pic_string *str) +{ + int i; + const char *cstr = str->str; + + for (i = 0; i < str->len; ++i) { + if (cstr[i] == '"' || cstr[i] == '\\') { + putchar('\\'); + } + putchar(cstr[i]); + } +} + void pic_debug(pic_state *pic, pic_value obj) { diff --git a/src/scan.l b/src/scan.l index f23ebdc3..c9b55f74 100644 --- a/src/scan.l +++ b/src/scan.l @@ -11,7 +11,7 @@ struct parser_control { bool incomp; }; -static pic_value escape_string(pic_state *, const char *); +static pic_value new_escaped_string(pic_state *, const char *); #define YY_DECL int yylex (struct parser_control *p) %} @@ -47,7 +47,7 @@ string_elem [^\"\\]|"\\\""|"\\\\" {real} { yylval.datum = pic_float_value(atof(yytext)); return tNUMBER; } {identifier} { yylval.datum = pic_intern_cstr(p->pic, yytext); return tSYMBOL; } {string} { - yylval.datum = escape_string(p->pic, yytext); + yylval.datum = new_escaped_string(p->pic, yytext); return tSTRING; } @@ -60,19 +60,24 @@ yywrap() } static pic_value -escape_string(pic_state *pic, const char *str) +new_escaped_string(pic_state *pic, const char *str) { size_t len; char *new_str; - int i; + int i,j; pic_value v; len = strlen(str); new_str = (char *)pic_alloc(pic, len + 1); - for (i = 1; i < len - 1; ++i) { - new_str[i-1] = str[i]; + for (j = 0, i = 1; i < len - 1; ++i, ++j) { + if (str[i] == '\\') { + ++i; + new_str[j] = str[i]; + continue; + } + new_str[j] = str[i]; } - new_str[i] = '\0'; + new_str[j] = '\0'; v = pic_str_new_cstr(pic, new_str); pic_free(pic, new_str); diff --git a/src/string.c b/src/string.c index 14b6850c..896ebf12 100644 --- a/src/string.c +++ b/src/string.c @@ -4,15 +4,14 @@ #include "picrin/string.h" pic_value -pic_str_new_cstr(pic_state *pic, const char *cstr) +pic_str_new(pic_state *pic, const char *cstr, size_t len) { struct pic_string *str; - size_t len; char *new_str; - len = strlen(cstr); new_str = (char *)pic_alloc(pic, len + 1); - strncpy(new_str, cstr, len + 1); + strncpy(new_str, cstr, len); + new_str[len] = '\0'; str = (struct pic_string *)pic_obj_alloc(pic, sizeof(struct pic_string), PIC_TT_STRING); str->len = len; @@ -20,3 +19,12 @@ pic_str_new_cstr(pic_state *pic, const char *cstr) return pic_obj_value(str); } + +pic_value +pic_str_new_cstr(pic_state *pic, const char *cstr) +{ + size_t len; + + len = strlen(cstr); + return pic_str_new(pic, cstr, len); +}