Skip to content

Commit 6d2da5a

Browse files
authored
Merge pull request #136 from jayrm/bugfix-897
bugfix: sf.net 897 length of literal wstring is miscalculated at compile time. bugfix: sf.net 794 literal tabs in string literals miscompiled if followed by 0-9 numeric chars
2 parents f35c501 + 20ef868 commit 6d2da5a

File tree

5 files changed

+108
-22
lines changed

5 files changed

+108
-22
lines changed

changelog.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ Version 1.07.0
66
- CVA_LIST type, CVA_START(), CVA_COPY() CVA_END(), CVA_ARG() macros will map to gcc's __builtin_va_list and __builtin_va_* macros in gcc backend
77

88
[fixed]
9-
- #881: C backend: support for varadic function parameters in gcc using __builtin_va_list type and related macros
9+
- sf.net #881: C backend: support for varadic function parameters in gcc using __builtin_va_list type and related macros
1010
- push/pop correct GL_PROJECTION matrix and GL_MODELVIEW matrix when setting up graphics screen (gothon)
1111
- fix char & wchar concatentation. For char double byte characters (such as Chinese characters), the "wstr = char & wchar" would become "wstr = char & chrw(0) & wchar" (SkyFish)
12+
- sf.net #794: literal tabs in string literals miscompiled if followed by 0-9 numeric chars
13+
- sf.net #897: length of literal wstring is miscalculated at compile time. Compile time evaluation of len(!"\u1234") was using the internal escaped string length instead of the actual codepoint length
1214

1315

1416
Version 1.06.0

src/compiler/hlp-str.bas

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -812,11 +812,15 @@ function hEscape _
812812
dst += 1
813813

814814
if( c < 8 ) then
815+
dst[0] = CHAR_0
816+
dst[1] = CHAR_0
817+
dst += 2
815818
c += CHAR_0
816819

817820
elseif( c < 64 ) then
818-
*dst = CHAR_0 + (c shr 3)
819-
dst += 1
821+
dst[0] = CHAR_0
822+
dst[1] = CHAR_0 + (c shr 3)
823+
dst += 2
820824
c = CHAR_0 + (c and 7)
821825

822826
else

src/compiler/parser-quirk-math.bas

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,10 @@ private function hLen _
7474
end if
7575

7676
'' String literal, evaluate at compile-time
77-
lgt = symbGetWstrLen( litsym ) - 1
77+
'' symbGetStrLen( litsym ) will return the number of codepoints
78+
'' that are used to store the escaped WSTRING literal, when what
79+
'' we really want is the number od codepoints unescaped.
80+
lgt = len( *hUnescapeW( symbGetVarLitTextW( litsym ) ) )
7881

7982
case FB_DATATYPE_FIXSTR
8083
'' len( fixstr ) returns the N from STRING * N, i.e. it works

tests/string/literal-tab.bas

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#include "fbcunit.bi"
2+
3+
SUITE( fbc_tests.string_.literal_tab )
4+
5+
TEST( default)
6+
7+
'' test that literal tabs in the source file
8+
'' are correctly escaped and emitted.
9+
10+
'' careful - string is 'x' chr(9) '0' 'x' chr(9) '0' '9'
11+
dim as string a = "x 0x 1x"
12+
dim as string b = "x" & chr(9) & "0x" & chr(9) & "1x"
13+
dim as string c = !"x\t0x\t1x"
14+
dim as ubyte d(0 to 6) = { asc("x"), 9, asc("0"), asc("x"), _
15+
9, asc("1"), asc("x") }
16+
17+
CU_ASSERT( len("x 0x 1x") = 7 )
18+
CU_ASSERT( len( a ) = 7 )
19+
CU_ASSERT( len( b ) = 7 )
20+
CU_ASSERT( len( c ) = 7 )
21+
22+
CU_ASSERT( a = "x 0x 1x" )
23+
CU_ASSERT( b = a )
24+
CU_ASSERT( c = a )
25+
26+
for i as integer = 0 to 6
27+
CU_ASSERT( a[i] = d(i) )
28+
CU_ASSERT( b[i] = d(i) )
29+
CU_ASSERT( c[i] = d(i) )
30+
next
31+
32+
END_TEST
33+
34+
END_SUITE

tests/wstring/len.bas

Lines changed: 61 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,70 @@
22

33
SUITE( fbc_tests.wstring_.len_ )
44

5-
const TEST_LIT = "abcdef"
5+
'' len( [w]str( literal ) ) is evaluated at compile time
6+
'' check that the compile time calculation matches the
7+
'' run time library calculation
8+
9+
const LIT_A1 = "abcdef"
10+
const LIT_W1 = wstr( "abcdef" )
11+
const LIT_W2 = !"bcd\u0065\u0066\u0067"
12+
const LIT_W3 = !"\u0063\u0064\u0065\u0065\u0067\u0068"
13+
14+
const CODE_LEN = 6
15+
616
const TEST_LEN = 32
717
const TEST_SIZ = TEST_LEN * len( wstring )
818

9-
TEST( default )
10-
11-
dim s as wstring * TEST_LEN
12-
dim ps as wstring ptr
13-
14-
s = TEST_LIT
15-
ps = @s
16-
17-
CU_ASSERT( len( s ) = len( TEST_LIT ) )
18-
19-
CU_ASSERT( sizeof( s ) = TEST_SIZ )
20-
21-
CU_ASSERT( len( *ps ) = len( TEST_LIT ) )
22-
23-
CU_ASSERT( len( ps ) = len( any ptr ) )
24-
25-
CU_ASSERT( sizeof( ps ) = sizeof( any ptr ) )
19+
#macro do_test( init_string )
20+
21+
scope
22+
dim s as wstring * TEST_LEN
23+
dim ps as wstring ptr
24+
25+
s = init_string
26+
ps = @s
27+
28+
CU_ASSERT( len( s ) = CODE_LEN )
29+
CU_ASSERT( len( *ps ) = CODE_LEN )
30+
31+
CU_ASSERT( len( s ) = len( init_string ) )
32+
33+
CU_ASSERT( sizeof( s ) = TEST_SIZ )
34+
35+
CU_ASSERT( len( *ps ) = len( init_string ) )
36+
37+
CU_ASSERT( len( ps ) = len( any ptr ) )
38+
39+
CU_ASSERT( sizeof( ps ) = sizeof( any ptr ) )
40+
end scope
41+
42+
#endmacro
43+
44+
TEST( literal )
45+
46+
do_test( "abcdef" )
47+
do_test( wstr( "abcdef" ) )
48+
do_test( !"bcd\u0065\u0066\u0067" )
49+
do_test( !"\u0063\u0064\u0065\u0065\u0067\u0068" )
50+
51+
do_test( LIT_A1 )
52+
do_test( LIT_W1 )
53+
do_test( LIT_W2 )
54+
do_test( LIT_W3 )
55+
56+
END_TEST
57+
58+
TEST( literal_const )
59+
60+
do_test( "abcdef" )
61+
do_test( wstr( "abcdef" ) )
62+
do_test( !"bcd\u0065\u0066\u0067" )
63+
do_test( !"\u0063\u0064\u0065\u0065\u0067\u0068" )
64+
65+
do_test( LIT_A1 )
66+
do_test( LIT_W1 )
67+
do_test( LIT_W2 )
68+
do_test( LIT_W3 )
2669

2770
END_TEST
2871

0 commit comments

Comments
 (0)