Browse Source

TranslateNumber: Take care of ph_out end (#2101)

master
Samuel Thibault 5 months ago
parent
commit
2c0f19cab7
No account linked to committer's email address
3 changed files with 75 additions and 25 deletions
  1. 71
    21
      src/libespeak-ng/numbers.c
  2. 2
    2
      src/libespeak-ng/numbers.h
  3. 2
    2
      src/libespeak-ng/translateword.c

+ 71
- 21
src/libespeak-ng/numbers.c View File

return 0; return 0;
} }


int TranslateRoman(Translator *tr, char *word, char *ph_out, WORD_TAB *wtab)
int TranslateRoman(Translator *tr, char *word, char *ph_out, char *ph_out_end, WORD_TAB *wtab)
{ {
int c; int c;
char *p; char *p;
if ((tr->langopts.numbers & NUM_ROMAN_AFTER) == 0) { if ((tr->langopts.numbers & NUM_ROMAN_AFTER) == 0) {
strcpy(ph_out, ph_roman); strcpy(ph_out, ph_roman);
p = &ph_out[strlen(ph_roman)]; p = &ph_out[strlen(ph_roman)];
} else {
ph_out_end -= strlen(ph_roman);
} }


sprintf(number_chars, " %d %s ", acc, tr->langopts.roman_suffix); sprintf(number_chars, " %d %s ", acc, tr->langopts.roman_suffix);


tr->prev_dict_flags[0] = 0; tr->prev_dict_flags[0] = 0;
tr->prev_dict_flags[1] = 0; tr->prev_dict_flags[1] = 0;
TranslateNumber(tr, &number_chars[2], p, flags, wtab, num_control);
TranslateNumber(tr, &number_chars[2], p, ph_out_end, flags, wtab, num_control);


if (tr->langopts.numbers & NUM_ROMAN_AFTER) if (tr->langopts.numbers & NUM_ROMAN_AFTER)
strcat(ph_out, ph_roman); strcat(ph_out, ph_roman);
return true; return true;
} }


static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned int *flags, WORD_TAB *wtab, int control)
static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, char *ph_out_end, unsigned int *flags, WORD_TAB *wtab, int control)
{ {
// Number translation with various options // Number translation with various options
// the "word" may be up to 4 digits // the "word" may be up to 4 digits
char ph_zeros[50]; char ph_zeros[50];
char suffix[30]; // string[] must be long enough for sizeof(suffix)+2 char suffix[30]; // string[] must be long enough for sizeof(suffix)+2
char buf_digit_lookup[50]; char buf_digit_lookup[50];
char *ph_cur;


static const char str_pause[2] = { phonPAUSE_NOLINK, 0 }; static const char str_pause[2] = { phonPAUSE_NOLINK, 0 };




LookupNum3(tr, value, ph_buf, suppress_null, thousandplex, prev_thousands | ordinal | decimal_point); LookupNum3(tr, value, ph_buf, suppress_null, thousandplex, prev_thousands | ordinal | decimal_point);
if ((thousandplex > 0) && (tr->langopts.numbers2 & NUM2_SWAP_THOUSANDS)) if ((thousandplex > 0) && (tr->langopts.numbers2 & NUM2_SWAP_THOUSANDS))
sprintf(ph_out, "%s%s%c%s%s", ph_zeros, ph_append, phonEND_WORD, ph_buf2, ph_buf);
len = sprintf(ph_out, "%s%s%c%s%s", ph_zeros, ph_append, phonEND_WORD, ph_buf2, ph_buf);
else else
sprintf(ph_out, "%s%s%s%c%s", ph_zeros, ph_buf2, ph_buf, phonEND_WORD, ph_append);
len = sprintf(ph_out, "%s%s%s%c%s", ph_zeros, ph_buf2, ph_buf, phonEND_WORD, ph_append);


ph_cur = ph_out + len;


while (decimal_point) { while (decimal_point) {
n_digits++; n_digits++;
// French/Polish decimal fraction // French/Polish decimal fraction
while (word[n_digits] == '0') { while (word[n_digits] == '0') {
Lookup(tr, "_0", buf1); Lookup(tr, "_0", buf1);
strcat(ph_out, buf1);
len = strlen(buf1);
if (ph_cur + len + 1 > ph_out_end)
goto stop;
strcpy(ph_cur, buf1);
ph_cur += len;
decimal_count--; decimal_count--;
n_digits++; n_digits++;
} }
if ((decimal_count <= max_decimal_count) && IsDigit09(word[n_digits])) { if ((decimal_count <= max_decimal_count) && IsDigit09(word[n_digits])) {
LookupNum3(tr, atoi(&word[n_digits]), buf1, false, 0, 0); LookupNum3(tr, atoi(&word[n_digits]), buf1, false, 0, 0);
strcat(ph_out, buf1);
len = strlen(buf1);
if (ph_cur + len + 1 > ph_out_end)
goto stop;
strcpy(ph_cur, buf1);
ph_cur += len;
n_digits += decimal_count; n_digits += decimal_count;
} }
break; break;
if (Lookup(tr, string, buf1) == 0) if (Lookup(tr, string, buf1) == 0)
break; // revert to speaking single digits break; // revert to speaking single digits


if (decimal_mode == NUM_DFRACTION_6)
strcat(ph_out, buf1);
else
if (decimal_mode == NUM_DFRACTION_6) {
len = strlen(buf1);
if (ph_cur + len + 1 > ph_out_end)
goto stop;
strcpy(ph_cur, buf1);
ph_cur += len;
} else
strcat(ph_buf, buf1); strcat(ph_buf, buf1);
} }
strcat(ph_out, ph_buf);

len = strlen(ph_buf);
if (ph_cur + len + 1 > ph_out_end)
goto stop;
strcpy(ph_cur, ph_buf);
ph_cur += len;

n_digits += decimal_count; n_digits += decimal_count;
break; break;
case NUM_DFRACTION_3: case NUM_DFRACTION_3:
// Romanian decimal fractions // Romanian decimal fractions
if ((decimal_count <= 4) && (word[n_digits] != '0')) { if ((decimal_count <= 4) && (word[n_digits] != '0')) {
LookupNum3(tr, atoi(&word[n_digits]), buf1, false, 0, 0); LookupNum3(tr, atoi(&word[n_digits]), buf1, false, 0, 0);
strcat(ph_out, buf1);
len = strlen(buf1);
if (ph_cur + len + 1 > ph_out_end)
goto stop;
strcpy(ph_cur, buf1);
ph_cur += len;
n_digits += decimal_count; n_digits += decimal_count;
} }
break; break;
if (Lookup(tr, string, buf1) == 0) if (Lookup(tr, string, buf1) == 0)
break; break;
n_digits++; n_digits++;
strcat(ph_out, buf1);
len = strlen(buf1);
if (ph_cur + len + 1 > ph_out_end)
goto stop;
strcpy(ph_cur, buf1);
ph_cur += len;
} }
} }


// speak any remaining decimal fraction digits individually // speak any remaining decimal fraction digits individually
value = word[n_digits++] - '0'; value = word[n_digits++] - '0';
LookupNum2(tr, value, 0, 2, buf1); LookupNum2(tr, value, 0, 2, buf1);
len = strlen(ph_out);
sprintf(&ph_out[len], "%c%s", phonEND_WORD, buf1);

len = strlen(buf1);
if (ph_cur + 1 + len + 1 > ph_out_end)
goto stop;
*ph_cur = phonEND_WORD;
strcpy(ph_cur + 1, buf1);
ph_cur += 1 + len;
} }


// something after the decimal part ? // something after the decimal part ?
if (Lookup(tr, "_dpt2", buf1))
strcat(ph_out, buf1);
if (Lookup(tr, "_dpt2", buf1)) {
len = strlen(buf1);
if (ph_cur + len + 1 > ph_out_end)
goto stop;
strcpy(ph_cur, buf1);
ph_cur += len;
}


if ((c == tr->langopts.decimal_sep) && IsDigit09(word[n_digits+1])) { if ((c == tr->langopts.decimal_sep) && IsDigit09(word[n_digits+1])) {
Lookup(tr, "_dpt", buf1); Lookup(tr, "_dpt", buf1);
strcat(ph_out, buf1);
len = strlen(buf1);
if (ph_cur + len + 1 > ph_out_end)
goto stop;
strcpy(ph_cur, buf1);
ph_cur += len;
} else } else
decimal_point = 0; decimal_point = 0;
} }

stop:
if ((ph_out[0] != 0) && (ph_out[0] != phonSWITCH)) { if ((ph_out[0] != 0) && (ph_out[0] != phonSWITCH)) {
int next_char; int next_char;
char *p; char *p;
utf8_in(&next_char, p); utf8_in(&next_char, p);


if (!iswalpha(next_char) && (thousands_exact == 0)) if (!iswalpha(next_char) && (thousands_exact == 0))
strcat(ph_out, str_pause); // don't add pause for 100s, 6th, etc.
{
if (ph_cur + strlen(str_pause) + 1 > ph_out_end)
ph_cur = ph_out_end - (strlen(str_pause) + 1);
strcpy(ph_cur, str_pause); // don't add pause for 100s, 6th, etc.
}
} }


*flags |= FLAG_FOUND; *flags |= FLAG_FOUND;
return 1; return 1;
} }


int TranslateNumber(Translator *tr, char *word1, char *ph_out, unsigned int *flags, WORD_TAB *wtab, int control)
int TranslateNumber(Translator *tr, char *word1, char *ph_out, char *ph_out_end, unsigned int *flags, WORD_TAB *wtab, int control)
{ {
if ((option_sayas == SAYAS_DIGITS1) || (wtab[0].flags & FLAG_INDIVIDUAL_DIGITS)) if ((option_sayas == SAYAS_DIGITS1) || (wtab[0].flags & FLAG_INDIVIDUAL_DIGITS))
return 0; // speak digits individually return 0; // speak digits individually


if (tr->langopts.numbers != 0) if (tr->langopts.numbers != 0)
return TranslateNumber_1(tr, word1, ph_out, flags, wtab, control);
return TranslateNumber_1(tr, word1, ph_out, ph_out_end, flags, wtab, control);
return 0; return 0;
} }

+ 2
- 2
src/libespeak-ng/numbers.h View File

void LookupLetter(Translator *tr, unsigned int letter, int next_byte, char *ph_buf1, int control); void LookupLetter(Translator *tr, unsigned int letter, int next_byte, char *ph_buf1, int control);
int IsSuperscript(int letter); int IsSuperscript(int letter);
void SetSpellingStress(Translator *tr, char *phonemes, int control, int n_chars); void SetSpellingStress(Translator *tr, char *phonemes, int control, int n_chars);
int TranslateRoman(Translator *tr, char *word, char *ph_out, WORD_TAB *wtab);
int TranslateNumber(Translator *tr, char *word1, char *ph_out, unsigned int *flags, WORD_TAB *wtab, int control);
int TranslateRoman(Translator *tr, char *word, char *ph_out, char *ph_out_end, WORD_TAB *wtab);
int TranslateNumber(Translator *tr, char *word1, char *ph_out, char *ph_out_end, unsigned int *flags, WORD_TAB *wtab, int control);




#ifdef __cplusplus #ifdef __cplusplus

+ 2
- 2
src/libespeak-ng/translateword.c View File

return 0; return 0;
} }


found = TranslateNumber(tr, word1, phonemes, dictionary_flags, wtab, 0);
found = TranslateNumber(tr, word1, phonemes, phonemes + sizeof(phonemes), dictionary_flags, wtab, 0);
} }


if (!found && ((wflags & FLAG_UPPERS) != FLAG_FIRST_UPPER)) { if (!found && ((wflags & FLAG_UPPERS) != FLAG_FIRST_UPPER)) {
if ((tr->langopts.numbers & NUM_ROMAN) || ((tr->langopts.numbers & NUM_ROMAN_CAPITALS) && (wflags & FLAG_ALL_UPPER))) { if ((tr->langopts.numbers & NUM_ROMAN) || ((tr->langopts.numbers & NUM_ROMAN_CAPITALS) && (wflags & FLAG_ALL_UPPER))) {
if ((wflags & FLAG_LAST_WORD) || !(wtab[1].flags & FLAG_NOSPACE)) { if ((wflags & FLAG_LAST_WORD) || !(wtab[1].flags & FLAG_NOSPACE)) {
// don't use Roman number if this word is not separated from the next word (eg. "XLTest") // don't use Roman number if this word is not separated from the next word (eg. "XLTest")
if ((found = TranslateRoman(tr, word1, phonemes, wtab)) != 0)
if ((found = TranslateRoman(tr, word1, phonemes, phonemes + sizeof(phonemes), wtab)) != 0)
dictionary_flags[0] |= FLAG_ABBREV; // prevent emphasis if capitals dictionary_flags[0] |= FLAG_ABBREV; // prevent emphasis if capitals
} }
} }

Loading…
Cancel
Save