From a44c7e09d9b3504fdc26253840728e517fa9f598 Mon Sep 17 00:00:00 2001
From: Thomas Voss <mail@thomasvoss.com>
Date: Thu, 9 May 2024 16:34:09 +0200
Subject: Fix bug where pointer to local was returned

---
 lib/unicode/prop/uprop_get_cf.c       | 16 +++++----
 lib/unicode/prop/uprop_get_lc.c       | 64 ++++++++++++++++++++++-------------
 lib/unicode/prop/uprop_get_nfkc_cf.c  |  8 +++--
 lib/unicode/prop/uprop_get_nfkc_scf.c |  8 +++--
 lib/unicode/prop/uprop_get_tc.c       | 15 ++++----
 lib/unicode/prop/uprop_get_uc.c       | 26 +++++++++-----
 6 files changed, 86 insertions(+), 51 deletions(-)

(limited to 'lib/unicode/prop')

diff --git a/lib/unicode/prop/uprop_get_cf.c b/lib/unicode/prop/uprop_get_cf.c
index 6297f73..351cf2f 100644
--- a/lib/unicode/prop/uprop_get_cf.c
+++ b/lib/unicode/prop/uprop_get_cf.c
@@ -3,7 +3,6 @@
 #include "macros.h"
 #include "unicode/prop.h"
 
-#define M(...) ((struct rview)_(__VA_ARGS__))
 #define _(...) \
 	{(const rune []){__VA_ARGS__}, lengthof(((const rune []){__VA_ARGS__}))}
 
@@ -1456,12 +1455,17 @@ static const struct rview stage2[][64] = {
 struct rview
 uprop_get_cf(rune ch, bool az_or_tr)
 {
-	if (ch == U'İ')
-		return az_or_tr ? M('i') : M('i', 0x307);
+	constexpr rune COMB_DOT_ABOVE = 0x307;
+	static thread_local rune hack[2];
+
+	if (ch == U'İ') {
+		hack[0] = 'i';
+		hack[1] = COMB_DOT_ABOVE;
+		return (struct rview){hack, az_or_tr ? 1 : 2};
+	}
 	struct rview rv = stage2[stage1[ch / 64]][ch % 64];
 	if (rv.p != nullptr)
 		return rv;
-	/* TODO: This returns a pointer to a stack-allocated array; fix this! */
-	ch = uprop_get_scf(ch, az_or_tr);
-	return M(ch);
+	hack[0] = uprop_get_scf(ch, az_or_tr);
+	return (struct rview){hack, 1};
 }
diff --git a/lib/unicode/prop/uprop_get_lc.c b/lib/unicode/prop/uprop_get_lc.c
index faf26c3..84d8240 100644
--- a/lib/unicode/prop/uprop_get_lc.c
+++ b/lib/unicode/prop/uprop_get_lc.c
@@ -1,53 +1,71 @@
 #include "macros.h"
 #include "unicode/prop.h"
 
-#define M(...) ((struct rview)_(__VA_ARGS__))
-#define _(...) \
-	{(const rune[]){__VA_ARGS__}, lengthof(((const rune[]){__VA_ARGS__}))}
-
 struct rview
 uprop_get_lc(rune ch, struct lcctx ctx)
 {
-	constexpr rune COMB_GRAVE     = 0x300;
-	constexpr rune COMB_ACUTE     = 0x301;
-	constexpr rune COMB_TILDE     = 0x303;
+	constexpr rune COMB_GRAVE = 0x300;
+	constexpr rune COMB_ACUTE = 0x301;
+	constexpr rune COMB_TILDE = 0x303;
 	constexpr rune COMB_DOT_ABOVE = 0x307;
+	static thread_local rune hack[3];
 
-	if (ch == U'Σ')
-		return ctx.final_sigma ? M(U'ς') : M(U'σ');
-	if (ch == U'İ')
-		return ctx.az_or_tr ? M('i') : M('i', COMB_DOT_ABOVE);
+	if (ch == U'Σ') {
+		hack[0] = ctx.final_sigma ? U'ς' : U'σ';
+		return (struct rview){hack, 1};
+	}
+	if (ch == U'İ') {
+		hack[0] = 'i';
+		hack[1] = COMB_DOT_ABOVE;
+		return (struct rview){hack, ctx.az_or_tr ? 1 : 2};
+	}
 
 	if (ctx.lt) {
 		if (ctx.more_above) {
 			switch (ch) {
 			case 'I':
-				return M('i', COMB_DOT_ABOVE);
+				hack[0] = 'i';
+				hack[1] = COMB_DOT_ABOVE;
+				return (struct rview){hack, 2};
 			case 'J':
-				return M('j', COMB_DOT_ABOVE);
+				hack[0] = 'j';
+				hack[1] = COMB_DOT_ABOVE;
+				return (struct rview){hack, 2};
 			case U'Į':
-				return M(U'į', COMB_DOT_ABOVE);
+				hack[0] = U'į';
+				hack[1] = COMB_DOT_ABOVE;
+				return (struct rview){hack, 2};
 			}
 		}
 
 		switch (ch) {
 		case U'Ì':
-			return M('i', COMB_DOT_ABOVE, COMB_GRAVE);
 		case U'Í':
-			return M('i', COMB_DOT_ABOVE, COMB_ACUTE);
 		case U'Ĩ':
-			return M('i', COMB_DOT_ABOVE, COMB_TILDE);
+			hack[0] = 'i';
+			hack[1] = COMB_DOT_ABOVE;
+
+			/* TODO: Use ternary when GCC stops being bad */
+			if (ch == U'Ì')
+				hack[2] = COMB_GRAVE;
+			else if (ch == U'Í')
+				hack[2] = COMB_ACUTE;
+			else
+				hack[2] = COMB_TILDE;
+
+			return (struct rview){hack, 3};
 		}
 	}
 
 	if (ctx.az_or_tr) {
 		if (ch == COMB_DOT_ABOVE && ctx.after_I)
-			return M();
-		if (ch == 'I' && !ctx.before_dot)
-			return M(U'ı');
+			return (struct rview){};
+		if (ch == 'I' && !ctx.before_dot) {
+			hack[0] = U'ı';
+			return (struct rview){hack, 1};
+		}
 	}
 
-	/* TODO: This returns a pointer to a stack-allocated array; fix this! */
-	ch = uprop_get_slc(ch);
-	return M(ch);
+	hack[0] = uprop_get_slc(ch);
+	return (struct rview){hack, 1};
 }
diff --git a/lib/unicode/prop/uprop_get_nfkc_cf.c b/lib/unicode/prop/uprop_get_nfkc_cf.c
index 1fe282e..39c4ef9 100644
--- a/lib/unicode/prop/uprop_get_nfkc_cf.c
+++ b/lib/unicode/prop/uprop_get_nfkc_cf.c
@@ -3,7 +3,6 @@
 #include "macros.h"
 #include "unicode/prop.h"
 
-#define M(...) ((struct rview)_(__VA_ARGS__))
 #define _(...) \
 	{(const rune []){__VA_ARGS__}, lengthof(((const rune []){__VA_ARGS__}))}
 
@@ -17698,7 +17697,10 @@ static const struct rview stage2[][256] = {
 struct rview
 uprop_get_nfkc_cf(rune ch)
 {
+	static thread_local rune hack;
 	struct rview rv = stage2[stage1[ch / 256]][ch % 256];
-	/* TODO: This returns a pointer to a stack-allocated array; fix this! */
-	return rv.len == 1 && rv.p[0] == SENTINAL ? M(ch) : rv;
+	if (rv.len != 1 || rv.p[0] != SENTINAL)
+		return rv;
+	hack = ch;
+	return (struct rview){&hack, 1};
 }
diff --git a/lib/unicode/prop/uprop_get_nfkc_scf.c b/lib/unicode/prop/uprop_get_nfkc_scf.c
index 1738874..3c870d8 100644
--- a/lib/unicode/prop/uprop_get_nfkc_scf.c
+++ b/lib/unicode/prop/uprop_get_nfkc_scf.c
@@ -3,7 +3,6 @@
 #include "macros.h"
 #include "unicode/prop.h"
 
-#define M(...) ((struct rview)_(__VA_ARGS__))
 #define _(...) \
 	{(const rune []){__VA_ARGS__}, lengthof(((const rune []){__VA_ARGS__}))}
 
@@ -17698,7 +17697,10 @@ static const struct rview stage2[][256] = {
 struct rview
 uprop_get_nfkc_scf(rune ch)
 {
+	static thread_local rune hack;
 	struct rview rv = stage2[stage1[ch / 256]][ch % 256];
-	/* TODO: This returns a pointer to a stack-allocated array; fix this! */
-	return rv.len == 1 && rv.p[0] == SENTINAL ? M(ch) : rv;
+	if (rv.len != 1 || rv.p[0] != SENTINAL)
+		return rv;
+	hack = ch;
+	return (struct rview){&hack, 1};
 }
diff --git a/lib/unicode/prop/uprop_get_tc.c b/lib/unicode/prop/uprop_get_tc.c
index cececd8..e08096e 100644
--- a/lib/unicode/prop/uprop_get_tc.c
+++ b/lib/unicode/prop/uprop_get_tc.c
@@ -3,7 +3,6 @@
 #include "macros.h"
 #include "unicode/prop.h"
 
-#define M(...) ((struct rview)_(__VA_ARGS__))
 #define _(...) \
 	{(const rune []){__VA_ARGS__}, lengthof(((const rune []){__VA_ARGS__}))}
 
@@ -1457,16 +1456,18 @@ struct rview
 uprop_get_tc(rune ch, struct tcctx ctx)
 {
 	constexpr rune COMB_DOT_ABOVE = 0x307;
+	static thread_local rune hack;
 
-	if (ch == 'i' && ctx.az_or_tr)
-		return M(U'İ');
+	if (ch == 'i' && ctx.az_or_tr) {
+		hack = U'İ';
+		return (struct rview){&hack, 1};
+	}
 	if (ch == COMB_DOT_ABOVE && ctx.lt && ctx.after_soft_dotted)
-		return M();
+		return (struct rview){nullptr, 0};
 
 	struct rview rv = stage2[stage1[ch / 64]][ch % 64];
 	if (rv.p != nullptr)
 		return rv;
-	/* TODO: This returns a pointer to a stack-allocated array; fix this! */
-	ch = uprop_get_stc(ch);
-	return M(ch);
+	hack = uprop_get_stc(ch);
+	return (struct rview){&hack, 1};
 }
diff --git a/lib/unicode/prop/uprop_get_uc.c b/lib/unicode/prop/uprop_get_uc.c
index 698c61c..4eaafa1 100644
--- a/lib/unicode/prop/uprop_get_uc.c
+++ b/lib/unicode/prop/uprop_get_uc.c
@@ -2,7 +2,6 @@
 #include "rune.h"
 #include "unicode/prop.h"
 
-#define M(...) ((struct rview)_(__VA_ARGS__))
 #define _(...) \
 	{(const rune []){__VA_ARGS__}, lengthof(((const rune []){__VA_ARGS__}))}
 
@@ -1136,18 +1135,27 @@ struct rview
 uprop_get_uc(rune ch, struct ucctx ctx)
 {
 	constexpr rune COMB_DOT_ABOVE = 0x307;
+	static thread_local rune hack[2];
 
-	if (ch == U'ß')
-		return ctx.ẞ ? M(U'ẞ') : M('S', 'S');
-	if (ch == 'i' && ctx.az_or_tr)
-		return M(U'İ');
+	if (ch == U'ß') {
+		if (ctx.ẞ) {
+			hack[0] = U'ẞ';
+			return (struct rview){hack, 1};
+		}
+		hack[0] = 'S';
+		hack[1] = 'S';
+		return (struct rview){hack, 2};
+	}
+	if (ch == 'i' && ctx.az_or_tr) {
+		hack[0] = U'İ';
+		return (struct rview){hack, 1};
+	}
 	if (ch == COMB_DOT_ABOVE && ctx.lt && ctx.after_soft_dotted)
-		return M();
+		return (struct rview){nullptr, 0};
 
 	struct rview rv = stage2[stage1[ch / 128]][ch % 128];
 	if (rv.p != nullptr)
 		return rv;
-	/* TODO: This returns a pointer to a stack-allocated array; fix this! */
-	ch = uprop_get_suc(ch);
-	return M(ch);
+	hack[0] = uprop_get_suc(ch);
+	return (struct rview){hack, 1};
 }
-- 
cgit v1.2.3