shithub: kwa

Download patch

ref: ba4a1c07f1bc7622f8a3dcd4f2d383f4ec70fc1c
parent: 7e6d7d36f83f05f372cfbce43534a2747bfc39c3
author: qwx <qwx@sciops.net>
date: Thu Sep 25 18:50:35 EDT 2025

toupper/tolower: handle unicode

--- a/run.c
+++ b/run.c
@@ -1516,13 +1516,15 @@
 {
 	Cell *x, *y;
 	Awkfloat u, tmp;
-	int t;
+	int n, t;
 	Rune wc;
-	char *p, *buf;
+	char *p, *s, *buf, *rbuf;
 	char mbc[50];
 	Node *nextarg;
 	Biobuf *fp;
 	void flush_all(void);
+	int (*test)(Rune);
+	Rune (*conv)(Rune);
 
 	t = ptoi(a[0]);
 	x = execute(a[1]);
@@ -1578,21 +1580,29 @@
 		break;
 	case FTOUPPER:
 	case FTOLOWER:
-		buf = tostring(getsval(x));
+		buf = getsval(x);
+		n = utflen(buf) * UTFmax + 1;	/* just in case size differs... */
+		if ((rbuf = malloc(n)) == nil)
+			FATAL("out of space in %s", t == FTOUPPER ? "toupper" : "tolower");
 		if (t == FTOUPPER) {
-			for (p = buf; *p; p++)
-				if (islower(*p))
-					*p = toupper(*p);
+			test = islowerrune;
+			conv = toupperrune;
 		} else {
-			for (p = buf; *p; p++)
-				if (isupper(*p))
-					*p = tolower(*p);
+			test = isupperrune;
+			conv = tolowerrune;
 		}
+		for (p = rbuf, s = buf; *s; s += n) {
+			n = chartorune(&wc, s);
+			if (test(wc))
+				wc = conv(wc);
+			p += runetochar(p, &wc);
+		}
+		*p = 0;
 		if (istemp(x))
 			tfree(x);
 		x = gettemp();
-		setsval(x, buf);
-		free(buf);
+		setsval(x, rbuf);
+		free(rbuf);
 		return x;
 	case FFLUSH:
 		if (isrec(x) || strlen(getsval(x)) == 0) {
--