From a44c7e09d9b3504fdc26253840728e517fa9f598 Mon Sep 17 00:00:00 2001 From: Thomas Voss 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 +++++++++----- test/_case-test.h | 1 + 7 files changed, 87 insertions(+), 51 deletions(-) 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}; } diff --git a/test/_case-test.h b/test/_case-test.h index ea05a86..701d884 100644 --- a/test/_case-test.h +++ b/test/_case-test.h @@ -72,6 +72,7 @@ test(const char8_t *line, int id) if (!u8eq(mapped, after)) { warn("case %d: expected ‘%.*s’ but got ‘%.*s’", id, SV_PRI_ARGS(after), SV_PRI_ARGS(mapped)); + arena_free(&a); return false; } -- cgit v1.2.3