nvda happened to be speaking 3647 because strtoi was actually overflowing. Better make sure to have proper ascii to number translation before continuing. Fixes #1385master
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <wctype.h> | #include <wctype.h> | ||||
#include <errno.h> | |||||
#include <limits.h> | |||||
#include <espeak-ng/espeak_ng.h> | #include <espeak-ng/espeak_ng.h> | ||||
#include <espeak-ng/speak_lib.h> | #include <espeak-ng/speak_lib.h> | ||||
// "words" of 3 digits may be preceded by another number "word" for thousands or millions | // "words" of 3 digits may be preceded by another number "word" for thousands or millions | ||||
int n_digits; | int n_digits; | ||||
int value; | |||||
long value; | |||||
int ix; | int ix; | ||||
int digix; | int digix; | ||||
unsigned char c; | unsigned char c; | ||||
int thousands_inc = 0; | int thousands_inc = 0; | ||||
int prev_thousands = 0; | int prev_thousands = 0; | ||||
int ordinal = 0; | int ordinal = 0; | ||||
int this_value; | |||||
long this_value; | |||||
int decimal_count; | int decimal_count; | ||||
int max_decimal_count; | int max_decimal_count; | ||||
int decimal_mode; | int decimal_mode; | ||||
static const char str_pause[2] = { phonPAUSE_NOLINK, 0 }; | static const char str_pause[2] = { phonPAUSE_NOLINK, 0 }; | ||||
char *end; | |||||
*flags = 0; | *flags = 0; | ||||
n_digit_lookup = 0; | n_digit_lookup = 0; | ||||
buf_digit_lookup[0] = 0; | buf_digit_lookup[0] = 0; | ||||
for (ix = 0; IsDigit09(word[ix]); ix++) ; | for (ix = 0; IsDigit09(word[ix]); ix++) ; | ||||
n_digits = ix; | n_digits = ix; | ||||
value = this_value = atoi(word); | |||||
errno = 0; | |||||
this_value = strtol(word, &end, 10); | |||||
if (errno || end == word || this_value > INT_MAX) | |||||
return 0; // long number, speak as individual digits | |||||
value = this_value; | |||||
group_len = 3; | group_len = 3; | ||||
if (tr->langopts.numbers2 & NUM2_MYRIADS) | if (tr->langopts.numbers2 & NUM2_MYRIADS) |
test_phon en "t'En tw'Enti T'3:ti f'o@ti f'Ifti s'Iksti s'Ev@nti; 'eIti n'aInti" "10 20 30 40 50 60 70 80 90" "tens" | test_phon en "t'En tw'Enti T'3:ti f'o@ti f'Ifti s'Iksti s'Ev@nti; 'eIti n'aInti" "10 20 30 40 50 60 70 80 90" "tens" | ||||
test_phon en-GB "Tr'i:h'VndrI2d@n s'Iksti f'aIv" "365" "hundreds" | test_phon en-GB "Tr'i:h'VndrI2d@n s'Iksti f'aIv" "365" "hundreds" | ||||
test_phon en-US "Tr'i:h'VndrI2d s'Iksti f'aIv" "365" "hundreds" | test_phon en-US "Tr'i:h'VndrI2d s'Iksti f'aIv" "365" "hundreds" | ||||
test_phon en "w'0nh'VndrI2d w'0n T'aUz@nd w'0n m'Ili@n w'0n b'Ili@n w'0n tr'Ili@n w'0n kw0dr'Ili@n w'0n kwInt'Ili@n w'0n sExt'Ili@n w'0n sEpt'Ili@n w'0n 0kt'Ili@n w'0n n0n'Ili@n" "100 1000 1000000 1000000000 1000000000000 1000000000000000 1000000000000000000 1000000000000000000000 1000000000000000000000000 1000000000000000000000000000 1000000000000000000000000000000" "large" # 10^2 10^3 10^6 10^9 10^12 10^15 10^18 10^21 10^24 10^27 10^30 | |||||
test_phon en "w'0nh'VndrI2d w'0n T'aUz@nd w'0n m'Ili@n w'0n b'Ili@n w'0n tr'Ili@n w'0n kw0dr'Ili@n w'0n kwInt'Ili@n w'0n sExt'Ili@n w'0n sEpt'Ili@n w'0n 0kt'Ili@n w'0n n0n'Ili@n t'En n0n'Ili@n w'0nz'i@roU_!z'i@roUz'i@roU_!z'i@roUz'i@roU_!z'i@roUz'i@roU_!z'i@roUz'i@roU_!z'i@roUz'i@roU_!z'i@roUz'i@roU_!z'i@roUz'i@roU_!z'i@roUz'i@roU_!z'i@roUz'i@roU_!z'i@roUz'i@roU_!z'i@roUz'i@roU_!z'i@roUz'i@roU_!z'i@roUz'i@roU_!z'i@roUz'i@roU_!z'i@r" "100 1000 1000000 1000000000 1000000000000 1000000000000000 1000000000000000000 1000000000000000000000 1000000000000000000000000 1000000000000000000000000000 1000000000000000000000000000000 10000000000000000000000000000000 100000000000000000000000000000000" "large" # 10^2 10^3 10^6 10^9 10^12 10^15 10^18 10^21 10^24 10^27 10^30 10^31 10^32 | |||||
test_phon en "f'aIv s'Iksti f'o@ w'0nh'VndrI2d@n tw'Enti Tr'i: f'o@ T'aUz@nd Tr'i:h'VndrI2d@n f'Ifti s'Ev@n f'o@ti:n T'aUz@nd_! s'Iksh'VndrI2d@n 'eIti Tr'i: s'Ev@nh'VndrI2d@n f'o@ti t'u: T'aUz@nd_! Tr'i:h'VndrI2d@n f'Ifti n'aIn s'Iks m'Ili@n_! f'o@h'VndrI2d@n s'Ev@nti f'aIv T'aUz@nd_! Tr'i:h'VndrI2d@n tw'Enti; 'eIt" "5 64 123 4357 14683 742359 6475328" "mixed" | test_phon en "f'aIv s'Iksti f'o@ w'0nh'VndrI2d@n tw'Enti Tr'i: f'o@ T'aUz@nd Tr'i:h'VndrI2d@n f'Ifti s'Ev@n f'o@ti:n T'aUz@nd_! s'Iksh'VndrI2d@n 'eIti Tr'i: s'Ev@nh'VndrI2d@n f'o@ti t'u: T'aUz@nd_! Tr'i:h'VndrI2d@n f'Ifti n'aIn s'Iks m'Ili@n_! f'o@h'VndrI2d@n s'Ev@nti f'aIv T'aUz@nd_! Tr'i:h'VndrI2d@n tw'Enti; 'eIt" "5 64 123 4357 14683 742359 6475328" "mixed" | ||||
echo "... lv (Latvian)" # short scale | echo "... lv (Latvian)" # short scale |