Valdis Vitolins 5 years ago
parent
commit
826e96642b

+ 12
- 12
src/libespeak-ng/numbers.c View File

/* /*
* Copyright (C) 2005 to 2015 by Jonathan Duddington * Copyright (C) 2005 to 2015 by Jonathan Duddington
* email: [email protected] * email: [email protected]
* Copyright (C) 2015-2016 Reece H. Dunn
* Copyright (C) 2015-2016, 2020 Reece H. Dunn
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
if (((value % 100) > 10) && ((value % 100) < 20)) if (((value % 100) > 10) && ((value % 100) < 20))
teens = true; teens = true;


switch ((translator->langopts.numbers2 >> 6) & 0x7)
switch (translator->langopts.numbers2 & NUM2_THOUSANDS_VAR_BITS)
{ {
case 1: // lang=ru use singular for xx1 except for x11
case NUM2_THOUSANDS_VAR1: // lang=ru use singular for xx1 except for x11
if ((teens == false) && ((value % 10) == 1)) if ((teens == false) && ((value % 10) == 1))
return "1M"; return "1M";
break; break;
case 2: // lang=cs,sk
case NUM2_THOUSANDS_VAR2: // lang=cs,sk
if ((value >= 2) && (value <= 4)) if ((value >= 2) && (value <= 4))
return "0MA"; return "0MA";
break; break;
case 3: // lang=pl
case NUM2_THOUSANDS_VAR3: // lang=pl
if ((teens == false) && (((value % 10) >= 2) && ((value % 10) <= 4))) if ((teens == false) && (((value % 10) >= 2) && ((value % 10) <= 4)))
return "0MA"; return "0MA";
break; break;
case 4: // lang=lt
case NUM2_THOUSANDS_VAR4: // lang=lt
if ((teens == true) || ((value % 10) == 0)) if ((teens == true) || ((value % 10) == 0))
return "0MB"; return "0MB";
if ((value % 10) == 1) if ((value % 10) == 1)
return "0MA"; return "0MA";
break; break;
case 5: // lang=bs,hr,sr
case NUM2_THOUSANDS_VAR5: // lang=bs,hr,sr
if (teens == false) { if (teens == false) {
if ((value % 10) == 1) if ((value % 10) == 1)
return "1M"; return "1M";
LookupNum2(tr, hundreds/10, thousandplex, x, ph_digits); LookupNum2(tr, hundreds/10, thousandplex, x, ph_digits);
} }


if (tr->langopts.numbers2 & 0x200)
sprintf(ph_thousands, "%s%c%s%c", ph_10T, phonEND_WORD, ph_digits, phonEND_WORD); // say "thousands" before its number, not after
if (tr->langopts.numbers2 & NUM2_SWAP_THOUSANDS)
sprintf(ph_thousands, "%s%c%s%c", ph_10T, phonEND_WORD, ph_digits, phonEND_WORD);
else else
sprintf(ph_thousands, "%s%c%s%c", ph_digits, phonEND_WORD, ph_10T, phonEND_WORD); sprintf(ph_thousands, "%s%c%s%c", ph_digits, phonEND_WORD, ph_10T, phonEND_WORD);


} }


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 & 0x200))
sprintf(ph_out, "%s%s%c%s%s", ph_zeros, ph_append, phonEND_WORD, ph_buf2, ph_buf); // say "thousands" before its number
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);
else else
sprintf(ph_out, "%s%s%s%c%s", ph_zeros, ph_buf2, ph_buf, phonEND_WORD, ph_append); sprintf(ph_out, "%s%s%s%c%s", ph_zeros, ph_buf2, ph_buf, phonEND_WORD, ph_append);


decimal_count++; decimal_count++;


max_decimal_count = 2; max_decimal_count = 2;
switch (decimal_mode = (tr->langopts.numbers & 0xe000))
switch (decimal_mode = (tr->langopts.numbers & NUM_DFRACTION_BITS))
{ {
case NUM_DFRACTION_4: case NUM_DFRACTION_4:
max_decimal_count = 5; max_decimal_count = 5;

+ 20
- 20
src/libespeak-ng/tr_languages.c View File

/* /*
* Copyright (C) 2005 to 2015 by Jonathan Duddington * Copyright (C) 2005 to 2015 by Jonathan Duddington
* email: [email protected] * email: [email protected]
* Copyright (C) 2015-2016 Reece H. Dunn
* Copyright (C) 2015-2016, 2020 Reece H. Dunn
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
tr->langopts.break_numbers = BREAK_LAKH_BN; tr->langopts.break_numbers = BREAK_LAKH_BN;


if (name2 == L3('b', 'p', 'y')) { if (name2 == L3('b', 'p', 'y')) {
tr->langopts.numbers = 1;
tr->langopts.numbers = NUM_DEFAULT;
tr->langopts.numbers2 = NUM2_SWAP_THOUSANDS; tr->langopts.numbers2 = NUM2_SWAP_THOUSANDS;
} }


SetLetterBitsRange(tr, LETTERGP_B, 0x90, 0xbc); SetLetterBitsRange(tr, LETTERGP_B, 0x90, 0xbc);
SetLetterBitsRange(tr, LETTERGP_C, 0x40, 0x6c); // consonant letters (not subjoined) SetLetterBitsRange(tr, LETTERGP_C, 0x40, 0x6c); // consonant letters (not subjoined)
tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words
tr->langopts.numbers = 1;
tr->langopts.numbers = NUM_DEFAULT;
} }
break; break;
case L('c', 'y'): // Welsh case L('c', 'y'): // Welsh
tr->langopts.stress_flags = S_MID_DIM | S_FINAL_DIM; // use 'diminished' for unstressed final syllable tr->langopts.stress_flags = S_MID_DIM | S_FINAL_DIM; // use 'diminished' for unstressed final syllable
SetLetterBitsRange(tr, LETTERGP_B, 0x26, 0x30); // vowel signs, and virama SetLetterBitsRange(tr, LETTERGP_B, 0x26, 0x30); // vowel signs, and virama
tr->langopts.break_numbers = BREAK_LAKH_DV; tr->langopts.break_numbers = BREAK_LAKH_DV;
tr->langopts.numbers = 1;
tr->langopts.numbers = NUM_DEFAULT;
} }
break; break;
case L('e', 'n'): case L('e', 'n'):
tr->langopts.param[LOPT_SONORANT_MIN] = 130; // limit the shortening of sonorants before short vowels tr->langopts.param[LOPT_SONORANT_MIN] = 130; // limit the shortening of sonorants before short vowels


tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_DECIMAL_COMMA; tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_DECIMAL_COMMA;
tr->langopts.numbers2 = 0x2 | NUM2_MULTIPLE_ORDINAL | NUM2_ORDINAL_NO_AND; // variant form of numbers before thousands
tr->langopts.numbers2 = NUM2_THOUSANDPLEX_VAR_THOUSANDS | NUM2_MULTIPLE_ORDINAL | NUM2_ORDINAL_NO_AND;


if (name2 == L3('g', 'r', 'c')) { if (name2 == L3('g', 'r', 'c')) {
// ancient greek // ancient greek
tr->langopts.accents = 1; tr->langopts.accents = 1;


tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_HUNDRED_AND | NUM_OMIT_1_HUNDRED | NUM_DECIMAL_COMMA | NUM_THOUS_SPACE | NUM_DFRACTION_2 | NUM_ROMAN_CAPITALS; tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_HUNDRED_AND | NUM_OMIT_1_HUNDRED | NUM_DECIMAL_COMMA | NUM_THOUS_SPACE | NUM_DFRACTION_2 | NUM_ROMAN_CAPITALS;
tr->langopts.numbers2 = 0xa + NUM2_THOUSANDS_VAR5; // variant numbers before thousands,milliards
tr->langopts.numbers2 = NUM2_THOUSANDPLEX_VAR_THOUSANDS | NUM2_THOUSANDPLEX_VAR_MILLIARDS | NUM2_THOUSANDS_VAR5;
tr->langopts.our_alphabet = OFFSET_CYRILLIC; // don't say "cyrillic" before letter names tr->langopts.our_alphabet = OFFSET_CYRILLIC; // don't say "cyrillic" before letter names


SetLetterVowel(tr, 'y'); SetLetterVowel(tr, 'y');
tr->letter_groups[1] = is_lettergroup_B; tr->letter_groups[1] = is_lettergroup_B;
SetLetterVowel(tr, 'y'); SetLetterVowel(tr, 'y');
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_SINGLE_AND | NUM_HUNDRED_AND | NUM_AND_UNITS | NUM_1900; tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_SINGLE_AND | NUM_HUNDRED_AND | NUM_AND_UNITS | NUM_1900;
tr->langopts.numbers2 = 0x2;
tr->langopts.numbers2 = NUM2_THOUSANDPLEX_VAR_THOUSANDS;
} }
break; break;
case L('i', 't'): // Italian case L('i', 't'): // Italian
} }
break; break;
case L('k', 'y'): // Kyrgyx case L('k', 'y'): // Kyrgyx
tr->langopts.numbers = 1;
tr->langopts.numbers = NUM_DEFAULT;
break; break;
case L('l', 'a'): // Latin case L('l', 'a'): // Latin
{ {


tr->langopts.stress_rule = STRESSPOSN_3R; // antipenultimate tr->langopts.stress_rule = STRESSPOSN_3R; // antipenultimate
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_AND_UNITS | NUM_OMIT_1_HUNDRED | NUM_OMIT_1_THOUSAND | NUM_DFRACTION_2; tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_AND_UNITS | NUM_OMIT_1_HUNDRED | NUM_OMIT_1_THOUSAND | NUM_DFRACTION_2;
tr->langopts.numbers2 = 0x8a; // variant numbers before thousands,milliards
tr->langopts.numbers2 = NUM2_THOUSANDPLEX_VAR_THOUSANDS | NUM2_THOUSANDPLEX_VAR_MILLIARDS | NUM2_THOUSANDS_VAR2;
} }
break; break;
case L('m', 't'): // Maltese case L('m', 't'): // Maltese
tr->encoding = ESPEAKNG_ENCODING_ISO_8859_3; tr->encoding = ESPEAKNG_ENCODING_ISO_8859_3;
tr->langopts.param[LOPT_REGRESSIVE_VOICING] = 0x100; // devoice at end of word tr->langopts.param[LOPT_REGRESSIVE_VOICING] = 0x100; // devoice at end of word
tr->langopts.stress_rule = STRESSPOSN_2R; // penultimate tr->langopts.stress_rule = STRESSPOSN_2R; // penultimate
tr->langopts.numbers = 1;
tr->langopts.numbers = NUM_DEFAULT;
} }
break; break;
case L('n', 'l'): // Dutch case L('n', 'l'): // Dutch
tr->langopts.stress_rule = STRESSPOSN_2R; tr->langopts.stress_rule = STRESSPOSN_2R;
tr->langopts.stress_flags = S_FINAL_DIM_ONLY | S_FINAL_NO_2 | 0x80000; tr->langopts.stress_flags = S_FINAL_DIM_ONLY | S_FINAL_NO_2 | 0x80000;
tr->langopts.numbers = NUM_OMIT_1_HUNDRED | NUM_HUNDRED_AND; tr->langopts.numbers = NUM_OMIT_1_HUNDRED | NUM_HUNDRED_AND;
tr->langopts.numbers2 = 0x200; // say "thousands" before its number
tr->langopts.numbers2 = NUM2_SWAP_THOUSANDS;
} }
break; break;
case L('p', 'l'): // Polish case L('p', 'l'): // Polish


tr->encoding = ESPEAKNG_ENCODING_ISO_8859_2; tr->encoding = ESPEAKNG_ENCODING_ISO_8859_2;
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_ALLOW_SPACE | NUM_DFRACTION_3 | NUM_AND_UNITS | NUM_ROMAN; tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_ALLOW_SPACE | NUM_DFRACTION_3 | NUM_AND_UNITS | NUM_ROMAN;
tr->langopts.numbers2 = 0x1e; // variant numbers before all thousandplex
tr->langopts.numbers2 = NUM2_THOUSANDPLEX_VAR_ALL;
} }
break; break;
case L('r', 'u'): // Russian case L('r', 'u'): // Russian
tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable
tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words. Need to allow "bw'" prefix tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words. Need to allow "bw'" prefix
tr->langopts.numbers = NUM_HUNDRED_AND | NUM_AND_UNITS | NUM_DFRACTION_2 | NUM_AND_HUNDRED; tr->langopts.numbers = NUM_HUNDRED_AND | NUM_AND_UNITS | NUM_DFRACTION_2 | NUM_AND_HUNDRED;
tr->langopts.numbers2 = 0x200; // say "thousands" before its number
tr->langopts.numbers2 = NUM2_SWAP_THOUSANDS;
} }
break; break;
case L('s', 'k'): // Slovak case L('s', 'k'): // Slovak
tr->langopts.decimal_sep = ','; tr->langopts.decimal_sep = ',';


if (name2 == L('c', 's')) if (name2 == L('c', 's'))
tr->langopts.numbers2 = 0x108; // variant numbers before milliards
tr->langopts.numbers2 = NUM2_THOUSANDPLEX_VAR_MILLIARDS | NUM2_THOUSANDS_VAR4;


SetLetterVowel(tr, 'y'); SetLetterVowel(tr, 'y');
SetLetterVowel(tr, 'r'); SetLetterVowel(tr, 'r');
tr->langopts.param[LOPT_IT_LENGTHEN] = 1; // remove lengthen indicator from unstressed syllables tr->langopts.param[LOPT_IT_LENGTHEN] = 1; // remove lengthen indicator from unstressed syllables
tr->letter_bits[(int)'r'] |= 0x80; // add 'r' to letter group 7, vowels for Unpronouncable test tr->letter_bits[(int)'r'] |= 0x80; // add 'r' to letter group 7, vowels for Unpronouncable test
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_ALLOW_SPACE | NUM_SWAP_TENS | NUM_OMIT_1_HUNDRED | NUM_DFRACTION_2 | NUM_ORDINAL_DOT | NUM_ROMAN; tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_ALLOW_SPACE | NUM_SWAP_TENS | NUM_OMIT_1_HUNDRED | NUM_DFRACTION_2 | NUM_ORDINAL_DOT | NUM_ROMAN;
tr->langopts.numbers2 = 0x100; // plural forms of millions etc
tr->langopts.numbers2 = NUM2_THOUSANDS_VAR4;
tr->langopts.thousands_sep = ' '; // don't allow dot as thousands separator tr->langopts.thousands_sep = ' '; // don't allow dot as thousands separator
break; break;
case L('s', 'q'): // Albanian case L('s', 'q'): // Albanian
tr->langopts.stress_rule = 13; // 1st syllable, unless 1st vowel is short and 2nd is long tr->langopts.stress_rule = 13; // 1st syllable, unless 1st vowel is short and 2nd is long
} else if (name2 == L('k', 'n')) { } else if (name2 == L('k', 'n')) {
tr->letter_bits_offset = OFFSET_KANNADA; tr->letter_bits_offset = OFFSET_KANNADA;
tr->langopts.numbers = 0x1;
tr->langopts.numbers = NUM_DEFAULT;
} else if (name2 == L('t', 'e')) { } else if (name2 == L('t', 'e')) {
tr->letter_bits_offset = OFFSET_TELUGU; tr->letter_bits_offset = OFFSET_TELUGU;
tr->langopts.numbers = 0x1;
tr->langopts.numbers = NUM_DEFAULT;
tr->langopts.numbers2 = NUM2_ORDINAL_DROP_VOWEL; tr->langopts.numbers2 = NUM2_ORDINAL_DROP_VOWEL;
} }
SetIndicLetters(tr); // call this after setting OFFSET_ SetIndicLetters(tr); // call this after setting OFFSET_
case L3('s', 'h', 'n'): case L3('s', 'h', 'n'):
tr->langopts.tone_language = 1; // Tone language, use CalcPitches_Tone() rather than CalcPitches() tr->langopts.tone_language = 1; // Tone language, use CalcPitches_Tone() rather than CalcPitches()
tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable
tr->langopts.numbers = 1;
tr->langopts.numbers = NUM_DEFAULT;
tr->langopts.break_numbers = BREAK_INDIVIDUAL; tr->langopts.break_numbers = BREAK_INDIVIDUAL;
break; break;
case L3('c', 'm', 'n'): // no break, just go to 'zh' case case L3('c', 'm', 'n'): // no break, just go to 'zh' case
if (name2 == L3('z', 'h', 'y')) { if (name2 == L3('z', 'h', 'y')) {
tr->langopts.textmode = true; tr->langopts.textmode = true;
tr->langopts.listx = 1; // compile zh_listx after zh_list tr->langopts.listx = 1; // compile zh_listx after zh_list
tr->langopts.numbers = 1;
tr->langopts.numbers = NUM_DEFAULT;
tr->langopts.numbers2 = NUM2_ZERO_TENS; tr->langopts.numbers2 = NUM2_ZERO_TENS;
tr->langopts.break_numbers = BREAK_INDIVIDUAL; tr->langopts.break_numbers = BREAK_INDIVIDUAL;
} }
tr->langopts.stress_flags = S_NO_AUTO_2; tr->langopts.stress_flags = S_NO_AUTO_2;


tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_OMIT_1_HUNDRED; tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_OMIT_1_HUNDRED;
tr->langopts.numbers2 = 0x2 + NUM2_THOUSANDS_VAR1; // variant numbers before thousands
tr->langopts.numbers2 = NUM2_THOUSANDPLEX_VAR_THOUSANDS | NUM2_THOUSANDS_VAR1; // variant numbers before thousands
} }

+ 3
- 3
src/libespeak-ng/translate.c View File

} }


// append plural suffixes depending on preceding letter // append plural suffixes depending on preceding letter
void addPluralSuffixes(int flags, Translator *tr, char last_char, char *word_phonemes)
static void addPluralSuffixes(int flags, Translator *tr, char last_char, char *word_phonemes)
{ {
char word_zz[4] = { 0, 'z', 'z', 0 }; char word_zz[4] = { 0, 'z', 'z', 0 };
char word_iz[4] = { 0, 'i', 'z', 0 }; char word_iz[4] = { 0, 'i', 'z', 0 };
if (wflags & FLAG_TRANSLATOR2) if (wflags & FLAG_TRANSLATOR2)
return 0; return 0;


addPluralSuffixes(wflags, tr, last_char, &word_phonemes);
addPluralSuffixes(wflags, tr, last_char, word_phonemes);
return dictionary_flags[0] & FLAG_SKIPWORDS; // for "b.c.d" return dictionary_flags[0] & FLAG_SKIPWORDS; // for "b.c.d"
} else if (found == false) { } else if (found == false) {
// word's pronunciation is not given in the dictionary list, although // word's pronunciation is not given in the dictionary list, although
} }
} }


addPluralSuffixes(wflags, tr, last_char, &word_phonemes);
addPluralSuffixes(wflags, tr, last_char, word_phonemes);
wflags |= emphasize_allcaps; wflags |= emphasize_allcaps;


// determine stress pattern for this word // determine stress pattern for this word

+ 60
- 91
src/libespeak-ng/translate.h View File

/* /*
* Copyright (C) 2005 to 2014 by Jonathan Duddington * Copyright (C) 2005 to 2014 by Jonathan Duddington
* email: [email protected] * email: [email protected]
* Copyright (C) 2015-2017 Reece H. Dunn
* Copyright (C) 2015-2017, 2020 Reece H. Dunn
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
unsigned char *length_mods; unsigned char *length_mods;
unsigned char *length_mods0; unsigned char *length_mods0;


#define NUM_THOUS_SPACE 0x4
#define NUM_DECIMAL_COMMA 0x8
#define NUM_SWAP_TENS 0x10
#define NUM_AND_UNITS 0x20
#define NUM_HUNDRED_AND 0x40
#define NUM_SINGLE_AND 0x80
#define NUM_SINGLE_STRESS 0x100
#define NUM_SINGLE_VOWEL 0x200
#define NUM_OMIT_1_HUNDRED 0x400
#define NUM_1900 0x800
#define NUM_ALLOW_SPACE 0x1000
#define NUM_DFRACTION_1 0x2000
#define NUM_DFRACTION_2 0x4000
#define NUM_DFRACTION_3 0x6000
#define NUM_DFRACTION_4 0x8000
#define NUM_DFRACTION_5 0xa000
#define NUM_DFRACTION_6 0xc000
#define NUM_DFRACTION_7 0xe000 // lang=si, alternative form of number for decimal fraction digits (except the last)
#define NUM_ORDINAL_DOT 0x10000
#define NUM_NOPAUSE 0x20000
#define NUM_AND_HUNDRED 0x40000
#define NUM_THOUSAND_AND 0x80000
#define NUM_VIGESIMAL 0x100000
#define NUM_OMIT_1_THOUSAND 0x200000
#define NUM_ZERO_HUNDRED 0x400000
#define NUM_HUNDRED_AND_DIGIT 0x800000
#define NUM_ROMAN 0x1000000
#define NUM_ROMAN_CAPITALS 0x2000000
#define NUM_ROMAN_AFTER 0x4000000
#define NUM_ROMAN_ORDINAL 0x8000000
#define NUM_SINGLE_STRESS_L 0x10000000

// bits0-1=which numbers routine to use.
// bit2= thousands separator must be space
// bit3= , decimal separator, not .
// bit4=use three-and-twenty rather than twenty-three
// bit5='and' between tens and units
// bit6=add "and" after hundred or thousand
// bit7=don't have "and" both after hundreds and also between tens and units
// bit8=only one primary stress in tens+units
// bit9=only one vowel betwen tens and units
// bit10=omit "one" before "hundred"
// bit11=say 19** as nineteen hundred
// bit12=allow space as thousands separator (in addition to langopts.thousands_sep)
// bits13-15 post-decimal-digits 0=single digits, 1=(LANG=it) 2=(LANG=pl) 3=(LANG=ro)

// bit16= dot after number indicates ordinal
// bit17= don't add pause after a number
// bit18= 'and' before hundreds
// bit19= 'and' after thousands if there are no hundreds
// bit20= vigesimal number, if tens are not found
// bit21= omit "one" before "thousand"
// bit22= say "zero" before hundred
// bit23= add "and" after hundreds and thousands, only if there are digits and no tens

// bit24= recognize roman numbers
// bit25= Roman numbers only if upper case
// bit26= say "roman" after the number, not before
// bit27= Roman numbers are ordinal numbers
// bit28= only one primary stress in tens+units (on the tens)
#define NUM_DEFAULT 0x00000001 // enable number processing; use if no other NUM_ option is specified
#define NUM_THOUS_SPACE 0x00000004 // thousands separator must be space
#define NUM_DECIMAL_COMMA 0x00000008 // , decimal separator, not .
#define NUM_SWAP_TENS 0x00000010 // use three-and-twenty rather than twenty-three
#define NUM_AND_UNITS 0x00000020 // 'and' between tens and units
#define NUM_HUNDRED_AND 0x00000040 // add "and" after hundred or thousand
#define NUM_SINGLE_AND 0x00000080 // don't have "and" both after hundreds and also between tens and units
#define NUM_SINGLE_STRESS 0x00000100 // only one primary stress in tens+units
#define NUM_SINGLE_VOWEL 0x00000200 // only one vowel betwen tens and units
#define NUM_OMIT_1_HUNDRED 0x00000400 // omit "one" before "hundred"
#define NUM_1900 0x00000800 // say 19** as nineteen hundred
#define NUM_ALLOW_SPACE 0x00001000 // allow space as thousands separator (in addition to langopts.thousands_sep)
#define NUM_DFRACTION_BITS 0x0000e000 // post-decimal-digits 0=single digits, 1=(LANG=it) 2=(LANG=pl) 3=(LANG=ro)
#define NUM_ORDINAL_DOT 0x00010000 // dot after number indicates ordinal
#define NUM_NOPAUSE 0x00020000 // don't add pause after a number
#define NUM_AND_HUNDRED 0x00040000 // 'and' before hundreds
#define NUM_THOUSAND_AND 0x00080000 // 'and' after thousands if there are no hundreds
#define NUM_VIGESIMAL 0x00100000 // vigesimal number, if tens are not found
#define NUM_OMIT_1_THOUSAND 0x00200000 // omit "one" before "thousand"
#define NUM_ZERO_HUNDRED 0x00400000 // say "zero" before hundred
#define NUM_HUNDRED_AND_DIGIT 0x00800000 // add "and" after hundreds and thousands, only if there are digits and no tens
#define NUM_ROMAN 0x01000000 // recognize roman numbers
#define NUM_ROMAN_CAPITALS 0x02000000 // Roman numbers only if upper case
#define NUM_ROMAN_AFTER 0x04000000 // say "roman" after the number, not before
#define NUM_ROMAN_ORDINAL 0x08000000 // Roman numbers are ordinal numbers
#define NUM_SINGLE_STRESS_L 0x10000000 // only one primary stress in tens+units (on the tens)

#define NUM_DFRACTION_1 0x00002000
#define NUM_DFRACTION_2 0x00004000
#define NUM_DFRACTION_3 0x00006000
#define NUM_DFRACTION_4 0x00008000
#define NUM_DFRACTION_5 0x0000a000
#define NUM_DFRACTION_6 0x0000c000
#define NUM_DFRACTION_7 0x0000e000 // lang=si, alternative form of number for decimal fraction digits (except the last)

int numbers; int numbers;


#define NUM2_THOUSANDS_VAR1 0x40
#define NUM2_THOUSANDS_VAR2 0x80
#define NUM2_THOUSANDS_VAR3 0xc0
#define NUM2_THOUSANDS_VAR4 0x100
#define NUM2_THOUSANDS_VAR5 0x140

#define NUM2_SWAP_THOUSANDS 0x200
#define NUM2_ORDINAL_NO_AND 0x800
#define NUM2_MULTIPLE_ORDINAL 0x1000
#define NUM2_NO_TEEN_ORDINALS 0x2000
#define NUM2_MYRIADS 0x4000
#define NUM2_ENGLISH_NUMERALS 0x8000
#define NUM2_PERCENT_BEFORE 0x10000
#define NUM2_OMIT_1_HUNDRED_ONLY 0x20000
#define NUM2_ORDINAL_AND_THOUSANDS 0x40000
#define NUM2_ORDINAL_DROP_VOWEL 0x80000 // currently only for tens and units
#define NUM2_ZERO_TENS 0x100000
// bits 1-4 use variant form of numbers before thousands,millions,etc.
// bits 6-8 use different forms of thousand, million, etc (M MA MB)
// bit9=(LANG=rw) say "thousand" and "million" before its number, not after
// bit11=(LANG=es,an) don't say 'and' between tens and units for ordinal numbers
// bit12=(LANG=el,es) use ordinal form of hundreds and tens as well as units
// bit13=(LANG=pt) don't use 11-19 numbers to make ordinals
// bit14=(LANG=ko) use myriads (groups of 4 digits) not thousands (groups of 3)
// bit15=(LANG=ne) speak (non-replaced) English numerals in English
// bit16=(LANG=si) say "%" before the number
// bit17=(LANG=ml) omit "one" before hundred only if there are no previous digits
// bit18=(LANG=ta) same variant for ordinals and thousands (#o = #a)
// bit19=(LANG=te) drop final vowel from cardial number before adding ordinal suffix
// bit20=(LANG=zh) say zero tens
#define NUM2_THOUSANDPLEX_VAR_BITS 0x0000001e // use variant form of numbers before thousands, millions, etc.
#define NUM2_THOUSANDS_VAR_BITS 0x000001c0 // use different forms of thousand, million, etc (M MA MB)
#define NUM2_SWAP_THOUSANDS 0x00000200 // say "thousand" and "million" before its number, not after
#define NUM2_ORDINAL_NO_AND 0x00000800 // don't say 'and' between tens and units for ordinal numbers
#define NUM2_MULTIPLE_ORDINAL 0x00001000 // use ordinal form of hundreds and tens as well as units
#define NUM2_NO_TEEN_ORDINALS 0x00002000 // don't use 11-19 numbers to make ordinals
#define NUM2_MYRIADS 0x00004000 // use myriads (groups of 4 digits) not thousands (groups of 3)
#define NUM2_ENGLISH_NUMERALS 0x00008000 // speak (non-replaced) English numerals in English
#define NUM2_PERCENT_BEFORE 0x00010000 // say "%" before the number
#define NUM2_OMIT_1_HUNDRED_ONLY 0x00020000 // omit "one" before hundred only if there are no previous digits
#define NUM2_ORDINAL_AND_THOUSANDS 0x00040000 // same variant for ordinals and thousands (#o = #a)
#define NUM2_ORDINAL_DROP_VOWEL 0x00080000 // drop final vowel from cardial number before adding ordinal suffix (currently only tens and units)
#define NUM2_ZERO_TENS 0x00100000 // say zero tens

#define NUM2_THOUSANDPLEX_VAR_THOUSANDS 0x00000002
#define NUM2_THOUSANDPLEX_VAR_MILLIARDS 0x00000008
#define NUM2_THOUSANDPLEX_VAR_ALL 0x0000001e

#define NUM2_THOUSANDS_VAR1 0x00000040
#define NUM2_THOUSANDS_VAR2 0x00000080
#define NUM2_THOUSANDS_VAR3 0x000000c0
#define NUM2_THOUSANDS_VAR4 0x00000100 // plural forms for millions, etc.
#define NUM2_THOUSANDS_VAR5 0x00000140

int numbers2; int numbers2;


// Bit 2^n is set if 10^n separates a number grouping (max n=31). // Bit 2^n is set if 10^n separates a number grouping (max n=31).

Loading…
Cancel
Save