cgen: fix a sporadic segfault when giving -width in a string interpolation
parent
5f435fa1cc
commit
809676a856
|
@ -9,6 +9,10 @@ fn (mut g Gen) write_str_fn_definitions() {
|
||||||
void _STR_PRINT_ARG(const char *fmt, char** refbufp, int *nbytes, int *memsize, int guess, ...) {
|
void _STR_PRINT_ARG(const char *fmt, char** refbufp, int *nbytes, int *memsize, int guess, ...) {
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, guess);
|
va_start(args, guess);
|
||||||
|
// NB: (*memsize - *nbytes) === how much free space is left at the end of the current buffer refbufp
|
||||||
|
// *memsize === total length of the buffer refbufp
|
||||||
|
// *nbytes === already occupied bytes of buffer refbufp
|
||||||
|
// guess === how many bytes were taken during the current vsnprintf run
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if (guess < *memsize - *nbytes) {
|
if (guess < *memsize - *nbytes) {
|
||||||
guess = vsnprintf(*refbufp + *nbytes, *memsize - *nbytes, fmt, args);
|
guess = vsnprintf(*refbufp + *nbytes, *memsize - *nbytes, fmt, args);
|
||||||
|
@ -62,7 +66,7 @@ string _STR(const char *fmt, int nfmts, ...) {
|
||||||
fwidth -= (s.len - utf8_str_visible_length(s));
|
fwidth -= (s.len - utf8_str_visible_length(s));
|
||||||
else
|
else
|
||||||
fwidth += (s.len - utf8_str_visible_length(s));
|
fwidth += (s.len - utf8_str_visible_length(s));
|
||||||
_STR_PRINT_ARG(fmt, &buf, &nbytes, &memsize, k+fwidth-4, fwidth, s.len, s.str);
|
_STR_PRINT_ARG(fmt, &buf, &nbytes, &memsize, k+s.len-4, fwidth, s.len, s.str);
|
||||||
} else { // %.*s
|
} else { // %.*s
|
||||||
_STR_PRINT_ARG(fmt, &buf, &nbytes, &memsize, k+s.len-4, s.len, s.str);
|
_STR_PRINT_ARG(fmt, &buf, &nbytes, &memsize, k+s.len-4, s.len, s.str);
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ fn test_implicit_str() {
|
||||||
assert text == '4242'
|
assert text == '4242'
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_string_interpolation_percent_escaping(){
|
fn test_string_interpolation_percent_escaping() {
|
||||||
test := 'hello'
|
test := 'hello'
|
||||||
hello := 'world'
|
hello := 'world'
|
||||||
x := '%.*s$hello$test |${hello:-30s}|'
|
x := '%.*s$hello$test |${hello:-30s}|'
|
||||||
|
@ -111,7 +111,11 @@ fn test_utf8_string_interpolation() {
|
||||||
st := 'Sträßle'
|
st := 'Sträßle'
|
||||||
m := '10€'
|
m := '10€'
|
||||||
assert '$a $st $m' == 'à-côté Sträßle 10€'
|
assert '$a $st $m' == 'à-côté Sträßle 10€'
|
||||||
assert '>${a:10}< >${st:-8}< >${m:5}<-' == '> à-côté< >Sträßle < > 10€<-'
|
zz := '>${a:10}< >${st:-8}< >${m:5}<-'
|
||||||
|
zz_expected := '> à-côté< >Sträßle < > 10€<-'
|
||||||
|
eprintln(' zz: $zz')
|
||||||
|
eprintln('zz_expected: $zz_expected')
|
||||||
|
assert zz == zz_expected
|
||||||
// e := '\u20AC' // Eurosign doesn' work with MSVC and tcc
|
// e := '\u20AC' // Eurosign doesn' work with MSVC and tcc
|
||||||
e := '€'
|
e := '€'
|
||||||
assert '100.00 $e' == '100.00 €'
|
assert '100.00 $e' == '100.00 €'
|
||||||
|
@ -135,3 +139,15 @@ fn test_string_interpolation_str_evaluation() {
|
||||||
mut x := S{17, 13.455893}
|
mut x := S{17, 13.455893}
|
||||||
assert '$x' == '[17, 13.456]'
|
assert '$x' == '[17, 13.456]'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn test_string_interpolation_with_negative_format_width_should_compile_and_run_without_segfaulting() {
|
||||||
|
// discovered during debugging VLS
|
||||||
|
i := 3
|
||||||
|
input := '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}'
|
||||||
|
eprintln('---------------------------------------------------------------------------------------------')
|
||||||
|
eprintln('+60 ${i:10} | input.len: ${input.len:10} | ${input.bytes().hex():60} | $input')
|
||||||
|
eprintln('-60 ${i:10} | input.len: ${input.len:10} | ${input.bytes().hex():-60} | $input')
|
||||||
|
eprintln('---------------------------------------------------------------------------------------------')
|
||||||
|
assert true
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue