commit 5b66729c016af058c3f50bed846edb24934ea10f
parent 60e982b9e3efeef6c181e206aa0e3a6019495125
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Wed,  9 Mar 2011 17:01:27 -0300
Slightly changed the token buffer interface to allow it to be used as a char stack
Diffstat:
2 files changed, 44 insertions(+), 14 deletions(-)
diff --git a/src/kstate.h b/src/kstate.h
@@ -185,7 +185,13 @@ inline bool ks_sisempty(klisp_State *K)
 */
 
 inline void ks_tbadd(klisp_State *K, char ch);
-inline char *ks_tbget(klisp_State *K);
+#define ks_tbpush(K_, ch_) (ks_tbadd((K_), (ch_)))
+inline char ks_tbget(klisp_State *K);
+inline char ks_tbpop(klisp_State *K);
+/* this is for DISCARDING stack pop (value isn't used, avoid warning) */ 
+#define ks_tbdpop(st_) (UNUSED(ks_tbpop(st_)))
+
+inline char *ks_tbget_buffer(klisp_State *K);
 inline void ks_tbclear(klisp_State *K);
 inline bool ks_tbisempty(klisp_State *K);
 
@@ -208,7 +214,26 @@ inline void ks_tbadd(klisp_State *K, char ch)
     ++ks_tbidx(K);
 }
 
-inline char *ks_tbget(klisp_State *K)
+inline char ks_tbget(klisp_State *K)
+{
+    return ks_tbelem(K, ks_tbidx(K) - 1);
+}
+
+inline char ks_tbpop(klisp_State *K)
+{
+    if (ks_tbsize(K) != KS_ITBSIZE && ks_tbidx(K) < (ks_tbsize(K) / 4)) {
+	/* NOTE: shrink can't fail */
+	size_t old_size = ks_tbsize(K);
+	size_t new_size = old_size / 2;
+	ks_tbuf(K) = klispM_realloc_(K, ks_tbuf(K), old_size, new_size);
+	ks_tbsize(K) = new_size; 
+    }
+    char ch = ks_tbelem(K, ks_tbidx(K) - 1);
+    --ks_tbidx(K);
+    return ch;
+}
+
+inline char *ks_tbget_buffer(klisp_State *K)
 {
     assert(ks_tbelem(K, ks_tbidx(K) - 1) == '\0');
     return ks_tbuf(K);
diff --git a/src/ktoken.c b/src/ktoken.c
@@ -400,7 +400,7 @@ TValue ktok_read_maybe_signed_numeric(klisp_State *K)
     if (ktok_check_delimiter(K)) {
 	ks_tbadd(K, ch);
 	ks_tbadd(K, '\0');
-	TValue new_sym = ksymbol_new(K, ks_tbuf(K));
+	TValue new_sym = ksymbol_new(K, ks_tbget_buffer(K));
 	ks_tbclear(K);
 	return new_sym;
     } else {
@@ -454,7 +454,7 @@ TValue ktok_read_string(klisp_State *K)
 	    i++;
 	}
     }
-    TValue new_str = kstring_new(K, ks_tbuf(K), i);
+    TValue new_str = kstring_new(K, ks_tbget_buffer(K), i);
     ks_tbclear(K);
     return new_str;
 }
@@ -484,9 +484,10 @@ TValue ktok_read_special(klisp_State *K)
 	ktok_read_until_delimiter(K);
 	/* NOTE: can use strcmp even in the presence of '\0's */
 	TValue ret_val;
-	if (strcmp(ks_tbuf(K), "gnore") == 0)
+	char *buf = ks_tbget_buffer(K);
+	if (strcmp(buf, "gnore") == 0)
 	    ret_val = KIGNORE;
-	else if (strcmp(ks_tbuf(K), "nert") == 0)
+	else if (strcmp(buf, "nert") == 0)
 	    ret_val =  KINERT;
 	else {
 	    ktok_error(K, "unexpected char in # constant");
@@ -496,15 +497,16 @@ TValue ktok_read_special(klisp_State *K)
 	ks_tbclear(K);
 	return ret_val;
     }
-    case 'e':
+    case 'e': {
 	/* an exact infinity */
 	/* XXX: could also be an exact number */
 	ktok_read_until_delimiter(K);
 	TValue ret_val;
 	/* NOTE: can use strcmp even in the presence of '\0's */
-	if (strcmp(ks_tbuf(K), "+infinity") == 0) {
+	char *buf = ks_tbget_buffer(K);
+	if (strcmp(buf, "+infinity") == 0) {
 	    ret_val = KEPINF;
-	} else if (strcmp(ks_tbuf(K), "-infinity") == 0) {
+	} else if (strcmp(buf, "-infinity") == 0) {
 	    ret_val =  KEMINF;
 	} else {
 	    ktok_error(K, "unexpected char in # constant");
@@ -513,6 +515,7 @@ TValue ktok_read_special(klisp_State *K)
 	}
 	ks_tbclear(K);
 	return ret_val;
+    }
     case 't':
     case 'f':
 	/* boolean constant */
@@ -523,7 +526,7 @@ TValue ktok_read_special(klisp_State *K)
 	    /* avoid warning */
 	    return KINERT;
 	}
-    case '\\':
+    case '\\': {
 	/* char constant */
 	/* 
 	** RATIONALE: in the scheme spec (R5RS) it says that only alphabetic 
@@ -546,16 +549,17 @@ TValue ktok_read_special(klisp_State *K)
 	    return ch2tv(ch);
 
 	ktok_read_until_delimiter(K);
-	char *p = ks_tbuf(K);
+	char *p = ks_tbget_buffer(K);
 	while (*p) {
 	    *p = tolower(*p);
 	    p++;
 	}
 	ch = tolower(ch);
 	/* NOTE: can use strcmp even in the presence of '\0's */
-	if (ch == 's' && strcmp(ks_tbuf(K), "pace") == 0)
+	char *buf = ks_tbget_buffer(K);
+	if (ch == 's' && strcmp(buf, "pace") == 0)
 	    ch = ' ';
-	else if (ch == 'n' && strcmp(ks_tbuf(K), "ewline") == 0)
+	else if (ch == 'n' && strcmp(buf, "ewline") == 0)
 	    ch = ('\n');
 	else {
 	    ktok_error(K, "Unrecognized character name");
@@ -564,6 +568,7 @@ TValue ktok_read_special(klisp_State *K)
 	}
 	ks_tbclear(K);
 	return ch2tv(ch);
+    }
     case '0': case '1': case '2': case '3': case '4': 
     case '5': case '6': case '7': case '8': case '9': {
 	/* srfi-38 type token (can be either a def or ref) */
@@ -613,7 +618,7 @@ TValue ktok_read_identifier(klisp_State *K)
 	    ktok_error(K, "Invalid char in identifier");	    
     }
     ks_tbadd(K, '\0');
-    TValue new_sym = ksymbol_new(K, ks_tbuf(K));
+    TValue new_sym = ksymbol_new(K, ks_tbget_buffer(K));
     ks_tbclear(K);
     return new_sym;
 }