shithub: femtolisp

Download patch

ref: 996c021140362c19d87dd0ab8f9e6280b0bc37e8
parent: 7c72a3b4dd1ca191c8799069306e2d94233c1a23
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Tue Dec 31 23:25:30 EST 2024

print_string: fix mixed ascii+non-ascii runes clobbered printout

Fixes: https://todo.sr.ht/~ft/femtolisp/34

--- a/print.c
+++ b/print.c
@@ -506,14 +506,14 @@
 static void
 print_string(ios_t *f, const char *str, size_t sz)
 {
-	char buf[512];
-	size_t i = 0;
+	char buf[64];
 	uint8_t c;
-	static char hexdig[] = "0123456789abcdef";
+	static const char hexdig[] = "0123456789abcdef";
 
+	size_t i = 0;
 	if(!u8_isvalid(str, sz)){
 		// alternate print algorithm that preserves data if it's not UTF-8
-		for(i = 0; i < sz; i++){
+		for(; i < sz; i++){
 			c = str[i];
 			if(c == '\\')
 				outsn(f, "\\\\", 2);
@@ -529,7 +529,7 @@
 		}
 	}else{
 		while(i < sz){
-			size_t n = u8_escape(buf, sizeof(buf), str, &i, sz, 1, 0);
+			size_t n = u8_escape(buf, sizeof(buf), str, &i, sz, true, false);
 			outsn(f, buf, n-1);
 		}
 	}
@@ -759,11 +759,12 @@
 				}
 				return;
 			}else if(eltype == FL_runesym){
-				char buf[UTFmax];
+				char buf[UTFmax+1];
 				if(!FL(print_princ))
 					outc(f, '"');
 				for(i = 0; i < cnt; i++, data = (char*)data + elsize){
 					int n = runetochar(buf, (Rune*)data);
+					buf[n] = 0;
 					if(FL(print_princ))
 						ios_write(f, buf, n);
 					else
--- a/utf8.c
+++ b/utf8.c
@@ -16,8 +16,8 @@
 #include "flisp.h"
 
 static const uint32_t offsetsFromUTF8[6] = {
-	0x00000000UL, 0x00003080UL, 0x000E2080UL,
-	0x03C82080UL, 0xFA082080UL, 0x82082080UL
+	0x00000000U, 0x00003080U, 0x000E2080U,
+	0x03C82080U, 0xFA082080U, 0x82082080U
 };
 
 static const char trailingBytesForUTF8[256] = {
@@ -46,7 +46,7 @@
 size_t
 u8_seqlen(const char *s)
 {
-	return trailingBytesForUTF8[(unsigned int)(uint8_t)s[0]] + 1;
+	return trailingBytesForUTF8[(uint8_t)s[0]] + 1;
 }
 
 /* byte offset => charnum */
@@ -80,14 +80,12 @@
 Rune
 u8_nextmemchar(const char *s, size_t *i)
 {
+	size_t sz = u8_seqlen(&s[*i]);
 	Rune ch = 0;
-	size_t sz = 0;
-
-	do{
+	for(size_t j = 0; j < sz; j++){
 		ch <<= 6;
 		ch += (uint8_t)s[(*i)++];
-		sz++;
-	}while(!isutf(s[*i]));
+	};
 	return ch - offsetsFromUTF8[sz-1];
 }
 
@@ -94,7 +92,7 @@
 int
 octal_digit(char c)
 {
-	return (c >= '0' && c <= '7');
+	return c >= '0' && c <= '7';
 }
 
 int
@@ -156,7 +154,7 @@
 }
 
 size_t
-u8_escape(char *buf, size_t sz, const char *src, size_t *pi, size_t end, int escape_quotes, int ascii)
+u8_escape(char *buf, size_t sz, const char *src, size_t *pi, size_t end, bool escape_quotes, bool ascii)
 {
 	size_t i = *pi, i0;
 	Rune ch;
@@ -187,7 +185,7 @@
 	}
 	*buf++ = '\0';
 	*pi = i;
-	return (buf-start);
+	return buf - start;
 }
 
 char *
--- a/utf8.h
+++ b/utf8.h
@@ -37,7 +37,7 @@
    returns number of bytes placed in buf, including a NUL terminator.
 */
 size_t u8_escape(char *buf, size_t sz, const char *src, size_t *pi, size_t end,
-                 int escape_quotes, int ascii);
+                 bool escape_quotes, bool ascii);
 
 /* utility predicates used by the above */
 int octal_digit(char c);