From 3fe500aebb31a71f4e9b75bbc63d09def99c3c8b Mon Sep 17 00:00:00 2001 From: Ryan Schmidt Date: Tue, 17 Aug 2021 20:07:33 -0500 Subject: [PATCH 01/50] Check more accurately if gradle exists Previously, the configure script would only successfully determine that gradle exists if the user specified an absolute path to the executable. It would fail if the user specified only an executable name or if the default value of "gradle" were used. Now it should succeed in either situation. --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 31cd1281..0c1460ef 100644 --- a/configure.ac +++ b/configure.ac @@ -81,7 +81,7 @@ dnl gradle checks. dnl ================================================================ AC_MSG_CHECKING([for gradle]) -if test -e ${GRADLE} ; then +if command -v "$GRADLE" >/dev/null; then AC_MSG_RESULT([${GRADLE}]) AM_CONDITIONAL(HAVE_GRADLE, [test 1 = 1]) else From c8902dff5c37b4070cadf21825eebce2379245ce Mon Sep 17 00:00:00 2001 From: Ryan Schmidt Date: Tue, 17 Aug 2021 20:08:33 -0500 Subject: [PATCH 02/50] Remove unnecessary curly braces around var name --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 0c1460ef..fb40c6ed 100644 --- a/configure.ac +++ b/configure.ac @@ -82,7 +82,7 @@ dnl ================================================================ AC_MSG_CHECKING([for gradle]) if command -v "$GRADLE" >/dev/null; then - AC_MSG_RESULT([${GRADLE}]) + AC_MSG_RESULT([$GRADLE]) AM_CONDITIONAL(HAVE_GRADLE, [test 1 = 1]) else AC_MSG_RESULT([no]) From f02ef622e49ea564b4db513c8d5f06d5220470b8 Mon Sep 17 00:00:00 2001 From: Ryan Schmidt Date: Tue, 17 Aug 2021 20:10:47 -0500 Subject: [PATCH 03/50] Show in configure summary when gradle is not found Previously, if configure determined that gradle could not be found, the summary at the end of the configure output would nevertheless print the name or path of the nonexistent gradle executable that it tried to find. Now it clears that variable. --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index fb40c6ed..1267f6f8 100644 --- a/configure.ac +++ b/configure.ac @@ -85,6 +85,7 @@ if command -v "$GRADLE" >/dev/null; then AC_MSG_RESULT([$GRADLE]) AM_CONDITIONAL(HAVE_GRADLE, [test 1 = 1]) else + GRADLE= AC_MSG_RESULT([no]) AM_CONDITIONAL(HAVE_GRADLE, [test 1 = 0]) fi From 51ed8cadb50cbde2a98a40ac0587929950e0aa4c Mon Sep 17 00:00:00 2001 From: Ryan Schmidt Date: Tue, 17 Aug 2021 20:16:46 -0500 Subject: [PATCH 04/50] Set HAVE_GRADLE in a more autoconfy way It is perhaps more autoconfy to have AM_CONDITIONAL evaluate a variable rather than call it with what are essentially constants representing either true or false. It might be even more autoconfy to use AC_CHECK_PROG here instead; I don't know if there's a good reason why that wasn't already done here. --- configure.ac | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 1267f6f8..c881ed6a 100644 --- a/configure.ac +++ b/configure.ac @@ -83,12 +83,11 @@ dnl ================================================================ AC_MSG_CHECKING([for gradle]) if command -v "$GRADLE" >/dev/null; then AC_MSG_RESULT([$GRADLE]) - AM_CONDITIONAL(HAVE_GRADLE, [test 1 = 1]) else GRADLE= AC_MSG_RESULT([no]) - AM_CONDITIONAL(HAVE_GRADLE, [test 1 = 0]) fi +AM_CONDITIONAL(HAVE_GRADLE, [test x"$GRADLE" != x]) AC_SUBST(GRADLE) From 216a4ded0bfcc92e521e2d0d8b7edb24b41b04cc Mon Sep 17 00:00:00 2001 From: Bill Dengler Date: Sat, 23 Apr 2022 01:25:30 -0400 Subject: [PATCH 05/50] Fix pronunciation of Issaquah --- dictsource/en_list | 1 + 1 file changed, 1 insertion(+) diff --git a/dictsource/en_list b/dictsource/en_list index e253fa4a..4c80980e 100644 --- a/dictsource/en_list +++ b/dictsource/en_list @@ -2295,6 +2295,7 @@ irises aIrIsI#z iron aI3n isochronous aIs'0kr@n@s isosceles aIs'0s@li:z +issaquah 'Is@kwA: ?3 issuance ISu:@ns invalidity I2nv@lIdI#ti From 7391e314939ef0db853ff9bb572aa80252122c15 Mon Sep 17 00:00:00 2001 From: Andiv06 <94701422+Andiv06@users.noreply.github.com> Date: Sun, 24 Apr 2022 20:41:00 +0300 Subject: [PATCH 06/50] Update Belarusian --- dictsource/be_list | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dictsource/be_list b/dictsource/be_list index 23b57e1e..2f4eae30 100644 --- a/dictsource/be_list +++ b/dictsource/be_list @@ -45,10 +45,10 @@ _4 ts.ati"ri" _5 p;at; _6 s.Es;t; _7 s;Em -_8 vOs;jEm -_9 dz;Ev;at; -_10 dz;Es;at; -_11 adz;inats:at; +_8 vOs;E2m +_9 d;Ev;at; +_10 d;Es;at; +_11 ad;inats:at; _12 dvanats:at; _13 tri"nats:at; _14 ts.ati"rnats:at; @@ -56,7 +56,7 @@ _15 p;atnats:at; _16 s.asnats:at; _17 s;amnats:at; _18 vas;amnats:at; -_19 dz;Ev;atnats:at; +_19 d;Ev;atnats:at; _2X dvats:at; _3X tri"ts:at; _4X sorak From bc0ceab7b9a6b5c7f811bbf4c487cfe51d8398e5 Mon Sep 17 00:00:00 2001 From: Dekedro Date: Mon, 25 Apr 2022 12:44:08 +0000 Subject: [PATCH 07/50] Fix grep regex in tests --- tests/non-executable-files-with-executable-bit.test | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/non-executable-files-with-executable-bit.test b/tests/non-executable-files-with-executable-bit.test index d1edfc99..443067c5 100755 --- a/tests/non-executable-files-with-executable-bit.test +++ b/tests/non-executable-files-with-executable-bit.test @@ -4,8 +4,8 @@ echo -n "testing files for executable bits that shouldn't be executable ... " find * -executable -type f | \ grep -vE "compile|config\.(guess|status|sub)|configure|depcomp|install-sh|libtool|missing" | # Ignore autotools output \ - grep -vE "*\.test|tests/common|src(/\.libs)?/(e?speak-ng|.*\.so\..*)|src/\.libs/lt-espeak-ng|android" | # Ignore built programs and libraries \ - grep -vE "*.\.sh|tools/emoji" | # Ignore helper scripts \ + grep -vE ".*\.test|tests/common|src(/\.libs)?/(e?speak-ng|.*\.so\..*)|src/\.libs/lt-espeak-ng|android" | # Ignore built programs and libraries \ + grep -vE ".*\.sh|tools/emoji" | # Ignore helper scripts \ grep -vE "src/ucd-tools/tools/(.*\.py|mkencodingtable)" | # Ignore ucd-tools helper scripts \ grep -vE "tests/.libs|src/ucd-tools/tests/print(ucd|c)data(_cpp)?" | # Ignore ucd-tools test programs \ tee tests/non-executable-files-with-executable-bit.check > /dev/null From 601c451e8adb288b644afb8919c5e1d58092d7d6 Mon Sep 17 00:00:00 2001 From: Sukil Etxenike Date: Mon, 25 Apr 2022 23:02:53 +0200 Subject: [PATCH 08/50] Fix #1166: Fix "deprimente", hopefully correctly --- dictsource/es_list | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dictsource/es_list b/dictsource/es_list index b4850644..b8c11bdc 100644 --- a/dictsource/es_list +++ b/dictsource/es_list @@ -335,7 +335,7 @@ Uds ustedes $text $capital $dot // pronunciation exceptions ser s'e@-* $only // it's not a abbrev vilmente $1 -deprimente $3 +depri $u $stem // Proper Names and countries amsterdam $3 bardem $2 From fcc1c41e70c6854a9a5b1bf961ec3583528d00ce Mon Sep 17 00:00:00 2001 From: Andiv06 <94701422+Andiv06@users.noreply.github.com> Date: Sat, 30 Apr 2022 12:35:29 +0300 Subject: [PATCH 09/50] Update Bashkir --- dictsource/ba_list | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/dictsource/ba_list b/dictsource/ba_list index 6e3e60e9..aa7a5033 100644 --- a/dictsource/ba_list +++ b/dictsource/ba_list @@ -49,32 +49,23 @@ _0 n'ul? _1 b'er _2 ik'e -_3 'WS; +_3 'Ws _4 d'yrt _5 b'iS _6 Alt'V -_7 Z;id'e -_8 sig'ez -_9 tug'Vz -_10 'un -_11 unb'er -_12 unik'e -_13 un'WS; -_14 und'yrt -_15 unb'iS -_16 unAlt'V -_17 unZ;id'e -_18 unsig'ez -_19 untug'Vz +_7 et'e +_8 hig'eD +_9 tug'VD +_1X 'un _2X egerm'e -_3X ut'Vz -_4X kVr'Vk +_3X ut'VD +_4X qVr'q _5X ill'e _6X Altm'VS -_7X Z;itm'eS -_8X siks'&n -_9X tuks'An -_0C j'Wz +_7X etm'eS +_8X hikh'&n +_9X tukh'An +_0C j'WD _0M1 m'eN _0M2 milli'on _1M2 milli'on From 64af32fca02c4679a5e6821571da8bd00959c8f0 Mon Sep 17 00:00:00 2001 From: Christianlm Date: Sat, 30 Apr 2022 12:06:17 +0200 Subject: [PATCH 10/50] Add/fix some exceptions for italian language. --- dictsource/it_list | 19 ++++++++++++++----- dictsource/it_listx | 2 ++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/dictsource/it_list b/dictsource/it_list index 65e51b6b..50767a5f 100644 --- a/dictsource/it_list +++ b/dictsource/it_list @@ -1,6 +1,6 @@ // This file is UTF-8 encoded -// Updated 2021 December 22 by Christian Leo M, +// Updated 2022 april 30 by Christian Leo Mameli, // $alt change [e] or [o] in the stressed syllable to [E] or [O] // $alt2 change [E] or [O] in the stressed syllable to [e] or [o] @@ -740,7 +740,7 @@ abbiamo $u+ $verbf abbiate $u+ abbiano $1 $verbf avessi av'es:i $verbf -avesse av'es:i $verbf +avesse av'es:e $verbf avessimo $u+ $verbf aveste av'este $verbf avessero $u+ $verbf @@ -2343,6 +2343,7 @@ beatle b'i:tol beccaria $3 beethoven be:t'o:ven benetton $3 +benjamin $1 bergomi $1 behringer b'e:RiNg,E@-* bertold $alt @@ -2367,6 +2368,7 @@ carey _^_en carmel $2 cassano $2 casula $2 +catherine _^_EN catia k'a:tia celentano $3 cesare $1 @@ -2696,6 +2698,7 @@ vainer v'aIne@-* $only valeria $2 $alt2 valter $1 $onlys van $u $capital $only +vanzetti vandz'Et:i vazquez vask'Ets vedder $1 $onlys vermouth v'E@-*mut @@ -3022,6 +3025,7 @@ avvalere $3 avvantaggiano $3 avvantaggino $3 avvelenino $3 +avventurano $3 avver $2 avverano $2 avverino $2 @@ -3068,7 +3072,7 @@ boccino $1 boicottino $3 bombardano $2 bombardino $2 -brahmano $1 +bramano $1 bramino $1 brancolano $1 brancolino $1 @@ -4111,6 +4115,7 @@ preoccupano $2 preoccupino $2 preordin $2 preparano $2 +prescegliere $2 presentino $2 presenziano $2 pressino $1 @@ -4132,9 +4137,10 @@ producano $2 profilano $2 programmano $2 proiettino $3 +prolunghino $2 pronuncino $2 propinino $2 - proponere $3 $alt +proponere $3 $alt propugnano $2 prorogano $1 prosciughino $2 @@ -4194,7 +4200,7 @@ ravvedere $3 ravvisano $2 ravvisino $2 razziano $1 -razziavano $3 +razziavano $2 reagii @-*eadZ'i:j realizzino $3 recano $1 @@ -4442,6 +4448,8 @@ scannino $1 scantono $2 scappano $1 scappino $1 +scarcer $1 +scarcerano $1 scardin $1 scaricano $1 scarichino $1 @@ -5041,6 +5049,7 @@ dirigiti $2 disabilital $3 disconnettiti $3 disegnaci $2 +dissolversi $2 distintasi $2 distintosi $2 domandatel $3 diff --git a/dictsource/it_listx b/dictsource/it_listx index 311796ee..21e839b9 100644 --- a/dictsource/it_listx +++ b/dictsource/it_listx @@ -3783,6 +3783,7 @@ stereotip $3 stesicor $2 stigmate $1 stilobate $2 +stipiti $1 stom $alt stomaci $1 stop $alt @@ -4045,6 +4046,7 @@ travesi $alt tre t@-*'e trenta $alt2 trebaseleghe $3 $alt2 +treccine $2 tredicesim $alt tredici $alt2 tremil $2 From 6d05b492dff8aa800f7d5c9818d0fcb5ce0445e7 Mon Sep 17 00:00:00 2001 From: Andiv06 <94701422+Andiv06@users.noreply.github.com> Date: Fri, 6 May 2022 20:49:01 +0300 Subject: [PATCH 11/50] Update Romanian --- phsource/ph_romanian | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/phsource/ph_romanian b/phsource/ph_romanian index e3598f8e..697005f0 100644 --- a/phsource/ph_romanian +++ b/phsource/ph_romanian @@ -150,7 +150,8 @@ endphoneme phoneme r liquid trl - lengthmod 7 + lengthmod 6 + IF nextPh(isNotVowel) THEN ChangePhoneme(r/) ENDIF @@ -172,6 +173,9 @@ phoneme r FMT(r/trr) ENDIF FMT(r/rr) + Vowelin f1=0 f2=1600 -300 300 f3=-200 80 + Vowelout f1=2 f2=1600 -300 300 f3=-200 80 brk + FMT(r3/r_trill2) addWav(r3/r_trill2.wav, 65) endphoneme From f4b0f408324ee9a014aee8431333740391e2e15b Mon Sep 17 00:00:00 2001 From: Andiv06 <94701422+Andiv06@users.noreply.github.com> Date: Mon, 9 May 2022 09:39:40 +0300 Subject: [PATCH 12/50] Update Greenlandic --- dictsource/kl_list | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/dictsource/kl_list b/dictsource/kl_list index 8db1c6a8..fbe27836 100644 --- a/dictsource/kl_list +++ b/dictsource/kl_list @@ -28,10 +28,10 @@ z zE // ø // å -// Native numbers 0-10 +// Native numbers 0-20 _0n n'u:lu -_1n at'a:sEq -_2n m'arluk +_1n at'a:s@q +_2n m'arl#uk _3n p'iNasut _4n s'isamat _5n t'al#imat @@ -40,6 +40,16 @@ _7n arfinEqm'arluk _8n arfinEqp'iNasut _9n quliNil'uat _10n q'ulit +_11n aqqanEq +_12n aqqanEqm'arl#uk +_13n aqqanEqp'iNasut +_14n aqqanEqs'isamat +_15n aqqanEqt'al#imat +_16n arfErs'anil#it +_17n arfErsanEqm'arl#uk +_18n arfErsanEqp'iNasut +_19n arfErsanEqs'isamat +_20n inukn'a:l#uQu // Danish numbers _0 'nOl From 254b64939df663275535262d37c5b62e444e69a4 Mon Sep 17 00:00:00 2001 From: Bill Dengler Date: Sun, 8 May 2022 20:48:55 -0400 Subject: [PATCH 13/50] Add support for Totontepec Mixe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit implements support for [Totontepec Mixe](https://en.wikipedia.org/wiki/Totontepec_Mixe). The Espeak rules are based on the phonological inventory, orthographic mappings, and phonetic processes described in the "Esbozo fonológico" (phonological outline/sketch) chapter of Verónica Guzmán Guzmán's 2012 master's thesis in Indo American Linguistics awarded by the [Centro de Investigaciones y Estudios Superiores en Antropología Social](https://ciesas.edu.mx/) and *Vocabulario Mixe de Totontepec* (Totontepec Mixe vocabulary), compiled by Alvin Schoenhals and Louise C. Schoenhals and published by the Summer Institute of Linguistics in 1965. This commit was developed as part of a project for [Computational Linguistics](https://jnw.domains.swarthmore.edu/ling073/syllabus.php) at [Swarthmore College](https://swarthmore.edu). We feel that this language is suitable for merge with "testing" status, but further verification/improvements by native speakers would be very helpful. co-authored-by: Elizabeth Resendiz --- Makefile.am | 4 + dictsource/mto_list | 214 ++++++++++++++++++++++++++++++++++ dictsource/mto_rules | 107 +++++++++++++++++ espeak-ng-data/lang/miz/mto | 8 ++ phsource/ph_mixe_mto | 216 +++++++++++++++++++++++++++++++++++ phsource/phonemes | 3 + tests/language-phonemes.test | 1 + 7 files changed, 553 insertions(+) create mode 100644 dictsource/mto_list create mode 100644 dictsource/mto_rules create mode 100644 espeak-ng-data/lang/miz/mto create mode 100644 phsource/ph_mixe_mto diff --git a/Makefile.am b/Makefile.am index f8f1f910..0efbb6d2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -488,6 +488,7 @@ dictionaries: \ espeak-ng-data/mr_dict \ espeak-ng-data/ms_dict \ espeak-ng-data/mt_dict \ + espeak-ng-data/mto_dict \ espeak-ng-data/my_dict \ espeak-ng-data/nci_dict \ espeak-ng-data/ne_dict \ @@ -750,6 +751,9 @@ espeak-ng-data/ms_dict: dictsource/ms_list dictsource/ms_rules dictsource/ms_ext mt: espeak-ng-data/mt_dict espeak-ng-data/mt_dict: dictsource/mt_list dictsource/mt_rules dictsource/mt_extra +mto: espeak-ng-data/mto_dict +espeak-ng-data/mto_dict: dictsource/mto_list dictsource/mto_rules + my: espeak-ng-data/my_dict espeak-ng-data/my_dict: dictsource/my_list dictsource/my_rules dictsource/my_extra dictsource/my_emoji diff --git a/dictsource/mto_list b/dictsource/mto_list new file mode 100644 index 00000000..969d17bc --- /dev/null +++ b/dictsource/mto_list @@ -0,0 +1,214 @@ +// This file is UTF8 encoded + +// letters + +_cap m'aJ^us +_?? s'imbolo +_#32 Esp'aTjo + +// accent names +_lig liQaD'ura +_acu aQ'uDo +_ac2 d'oble||aQ'uDo +_brv br'eBe +_ced seD'iJ^a +_cir sirkumfl'exo +_dia dj'Eresis +_dac d'oble||aQ'uDo +_dot p'unto +_grv gr'aBe +_hac kar'on +_mcn makr'on +_ogo kol'ita +_rng an'iJ^o +_stk b'aRR2a +_tld t'ilde +_sup supE**'indiTe +_sub suB'indiTe + + +// names of symbols +° grados +_. punto +_, koma +_; p,untoik'oma +_: d,osp'untos +_! TERR2'araDmiraTj'on +_? TERR2'arintERR2,oQaTj'on +_¡ aBr'iraDmiraTj'on +_¿ aBr'irintERR2,oQaTj'on +_< men'orke +_> maJ^'orke +_' apostr'ofo +ꞌ salt'il^o $only +_" kom'iJ^as +_- gJ^on +__ suBraJ^'aDo +_/ baRR2a +_\ b'aRR2aimbErt'iDa +_` aT'Ento||gr'aBe +_´ aT'Ento||aQ'uDo +_( ,aBrepar'Entesis +_) Tj,ERR2apar'Entesis +_[ ,aBrekortS'ete +_] Tj,ERR2akortS'ete +_{ ,aBreJ^'aBe +_} Tj,ERR2aJ^'aBe +_« kom'iJ^as||iTkJ^'ErDas +_» kom'iJ^as||dEr'EtSas += iQw'al ++ m'as +# almoaD'iJ^a +* astEr'isko +. punto +^ Tirkumfl'exo +₠ 'eU*o +€ eUro +% porTj'Ento +& ampErs'ant +@ aRR2'oBa +/ baRR2a +© kopiRR2'aIt +£ liBras +¶ p'aRR2afo +§ sEkTj'on +¬ n'ot +· p'unto||m'edjo + +// Language names + +_cyr Ti*'iliko_ +_hy arm'enjo +_he eB@-*'Eo +_ar 'a*aBe +_hi 'i:ndi +_bn beNg,al'i_ +_ta t'amil +_te tel'ugu +_si TiNgal'es +_th t'a:i +_my birm'ano +_ja x,apon'Es +_zh tS'ino + +// numbers +_0 nitija +_1 toU?k# +_2 mahtsk# +_3 toUoUhk# +_4 mAktAAz.k# +_5 mugooz.k# +_6 toUht8k# +_7 vuz.toUht8k# +_8 toUtoUht8k# +_9 tAz.toUht8k# +_1X mAhk# +_2x ii?p +_3X mAhk#ii?p +_4X v8htkup +_5X v8htkupmAhk# +_6X toUoUhk#ii?p +_7X toUoUhk#ii?pmAhk# +_8X mAktAAz.k#ii?p +_9X mAktAAz.k#ii?pmAhk# +_0C mugooz.k#ii?p +_dpt koma +_roman Rom'ano + +// ordinal numbers +_#º o +_#ª a +_ord mu +ºc gr'ados||T'e +ºf gr'ados||'Efe +ºk gr'ados||k'a + +// Letters (names taken from Spanish) +// If a letter has a "word" pronunciation which is different from its +// "letter" name, then include the letter name here, with the letter +// prefixed by a _ character. + +_b be +_c Te +_d de +_f Efe +_g xe +_h atSe +_j xota +_k ka +_l Ele +_m Eme +_n Ene +_ñ En^e +_p pe +_q ku +_r Ere +_s Ese +_t te +_v uBe +_w uBe||d'oBle +_x Ekis +_z TEta + +_a a +_e e +_o o +_y igri'eQa +_á 'a||aTEntw'aDa +_é 'e||aTEntw'aDa +_í 'i||aTEntw'aDa +_ó 'o||aTEntw'aDa +_ú 'u||aTEntw'aDa +_ü 'u||kon||dj'ErEsis +_ç $accent + +// Proper Names and countries +amsterdam $3 +bardem $2 +jerusalem $4 +méxico m'Exiko +vietnam $2 + +// foreign words + +android 'androId +apple 'ap@l +copyright k'opiRR2,aIt +chrome kr'owm +curriculum $2 +diem d'i:em $only +eloquence 'elokwens +english ínglish $text +espeak 'isp'ik +eyes 'aIs +facebook f'eIsbuk +firefox f'aIrfoks +free fr'i +google g'ug@l +hardware h'ardwer +iphone 'aIfon +ipod 'aIpod +jaws dZ'os +jazz dZ'as +linux $1 +live l'aIB +messenger m'esendZer +microsoft m'aIkrosoft +mozilla moT'ila +office 'ofis +platform pl'atfom +power p'awer +service s'erBis +skype sk'aIp +snapshot sn'apS,ot // _^_en +software s'oftwer +spanish sp'aniS +speech sp'itS +thunderbird t'anderbird +twit tw'it +twitter tw'iter +window w'indow + +(e speak) 'isp'ik +(i phone) 'aIfon +(i pod) 'aIpod diff --git a/dictsource/mto_rules b/dictsource/mto_rules new file mode 100644 index 00000000..d75ee175 --- /dev/null +++ b/dictsource/mto_rules @@ -0,0 +1,107 @@ +// Translation rules for mto +// This file is UTF-8 encoded + +.L01 a e i o u ä ë ï ö ü +.L02 m n + +.group a + a a + +.group ä + ä A + +.group e + e e + +.group ë + ë @ + +.group i + i i + +.group ï + ï 8 + +.group o + o o + +.group ö + ö oU + +.group u + u u + +.group v + v(_ f + _)v(o b + j)v vj + v(j vj + v v + +.group s + s s + +.group x + L01)x z. + L02)x z. + j)x s.j + x(j s.j + x s. + +.group j + j h + +.group ts + %L01)ts dz + L02)ts dz + j)ts tsj + ts(j tsj + ts ts + +.group p + L01)p(L01 b + L02)p(L01 b + p(_ p# + j)p pj + p(j pj + p p + +.group t + L01)t(L01 d + L02)t(L01 d + j)t tj + t(j tj + t(_ t# + t t + +.group k + L01)k(L01 g + L02)k(L01 g + k(_ k# + j)k kj + k(j kj + k k + +.group ꞌ + ꞌ ? + +.group m + j)m mj + m(j mj + m m + +.group n + n(p m + n(k N + j)n nj + n(j nj + n n + +.group r + r r + +.group l + l l + +.group y + y j diff --git a/espeak-ng-data/lang/miz/mto b/espeak-ng-data/lang/miz/mto new file mode 100644 index 00000000..eb0f75ff --- /dev/null +++ b/espeak-ng-data/lang/miz/mto @@ -0,0 +1,8 @@ +name Totontepec Mixe +language mto + +maintainer Bill Dengler and Elizabeth Resendiz +status testing + +lowercaseSentence +tunes s6 c6 q6 e6 diff --git a/phsource/ph_mixe_mto b/phsource/ph_mixe_mto new file mode 100644 index 00000000..f7c8c490 --- /dev/null +++ b/phsource/ph_mixe_mto @@ -0,0 +1,216 @@ + +//==================================================== +// Totontepec Mixe +//==================================================== + + +phoneme a + ipa a + vwl starttype #a endtype #a + length 190 + FMT(vowel/a_4) +endphoneme + +phoneme A + ipa ɑ + vwl starttype #a endtype #a + length 220 + unr bck low + FMT(vowel/aa_8) +endphoneme + +phoneme e + ipa e + vwl starttype #e endtype #e + length 190 + FMT(vowel/e_mid2) +endphoneme + +phoneme @ + ipa ə + vwl starttype #@ endtype #@ + unstressed + length 140 + unr cnt mid + IF thisPh(isWordEnd) THEN + FMT(vowel/@_6, 90) + ENDIF + FMT(vowel/@) +endphoneme + +phoneme i + ipa i + vwl starttype #i endtype #i + length 190 + IfNextVowelAppend(;) + FMT(vowel/i) +endphoneme + +phoneme 8 + ipa ɘ + vwl starttype #@ endtype #@ + length 165 + FMT(vowel/8_7) +endphoneme + +phoneme o + ipa o + vwl starttype #o endtype #o + length 195 + FMT(vowel/oo) +endphoneme + +phoneme oU + ipa əʊ + vwl starttype #@ endtype #u + length 220 + FMT(vdiph/@u_en) +endphoneme + +phoneme u + vwl starttype #u endtype #u + length 200 + FMT(vowel/u_bck2) +endphoneme + +phoneme k + import_phoneme consonants/k- +endphoneme + +phoneme k# + import_phoneme consonants/k# +endphoneme + +phoneme g + ipa g + vcd vel stp + lengthmod 5 + voicingswitch k + Vowelin f1=2 f2=2300 200 300 f3=-300 80 + Vowelout f1=2 f2=2300 250 300 f3=-300 80 brk + + FMT(g/g) addWav(x/g2) // weaker [g] +endphoneme + +phoneme t + import_phoneme base1/t[ +endphoneme + +phoneme T // Used in Spanish words + import_phoneme base1/T +endphoneme + +phoneme t# + ipa tʰ + vls dnt stp + lengthmod 2 + voicingswitch d + Vowelin f1=0 f2=1500 -300 300 f3=-100 80 amp=16 + Vowelout f1=0 f2=1500 -300 250 f3=-100 80 rms=20 + IF nextPh(isPause2) THEN + WAV(ustop/t_dnt, 35) + ENDIF + WAV(ustop/t_dnt, 50) +endphoneme + +phoneme d + import_phoneme base2/d +endphoneme + +phoneme p + import_phoneme consonants/p- +endphoneme + +phoneme p# + import_phoneme consonants/ph +endphoneme + +phoneme b + import_phoneme base1/b +endphoneme + +phoneme v + ipa v + vcd lbd frc + FMT(voc/v) addWav(vocw/v, 90) +endphoneme + +phoneme f + ipa f + vls lbd frc + WAV(ufric/f, 80) +endphoneme + +phoneme s + ipa s + vls alv frc sib + lengthmod 3 + voicingswitch z + Vowelin f1=0 f2=1700 -300 300 f3=-100 80 + Vowelout f1=0 f2=1700 -300 250 f3=-100 80 rms=20 + + IF nextPh(isPause) THEN + WAV(ufric/s_, 60) // quieter 's' at end of word + ELIF nextPh(p) OR nextPh(t) OR nextPh(k) THEN + WAV(ufric/s!) + ENDIF + WAV(ufric/s, 80) +endphoneme + +phoneme s. + import_phoneme base1/s. +endphoneme + +phoneme z. + import_phoneme base1/z. +endphoneme + +phoneme ts + import_phoneme consonants/ts +endphoneme + +phoneme dz + import_phoneme consonants/dz +endphoneme + +phoneme m + import_phoneme base1/m- +endphoneme + +phoneme n + import_phoneme base1/n- +endphoneme + +phoneme N + import_phoneme base1/N- +endphoneme + +phoneme r + import_phoneme base1/* +endphoneme + +phoneme l + import_phoneme base1/l +endphoneme + +phoneme j + import_phoneme base1/j +endphoneme + +phoneme C + import_phoneme base1/C +endphoneme + +phoneme ? + ipa ʔ + vls glt stp + lengthmod 1 // 5? longer preceding vowel + nolink + Vowelin glstop + Vowelout glstop + WAV(ustop/null) +endphoneme + +phoneme h + import_phoneme base1/h +endphoneme diff --git a/phsource/phonemes b/phsource/phonemes index 66b17c26..795bd937 100644 --- a/phsource/phonemes +++ b/phsource/phonemes @@ -1852,6 +1852,9 @@ include ph_kurdish phonemetable mi base2 include ph_maori +phonemetable mto base2 +include ph_mixe_mto + phonemetable nci base2 include ph_nahuatl diff --git a/tests/language-phonemes.test b/tests/language-phonemes.test index 36e0eff7..0fe7e13b 100755 --- a/tests/language-phonemes.test +++ b/tests/language-phonemes.test @@ -97,6 +97,7 @@ test_phwav mk 072d0a74acf54bea528e7dde427eb04808d38364 "ma na n^a Na pa ta xa k^ test_phwav mr 5238ba08fba349fea6c00bdd8f1672ede229b8ec "ma na n.a n^a pa t#a t.a tSa ka qa p#a t.#a c#a k#a ba d#a d.a dZa ga b#a d.#a J#a g#a fa sa Sa xa va za Za Qa Ha ra r.a la ja _:_ mI mU me m@ mo mE mV mO ma mi: mu: me: mo: mE: mO: ma: m&: mI~ mi~ mU~ mu~ mU~ me~ mo~ mE~ mV~ mO~ ma~ mAI maU" test_phwav ms 75a57a020af2b62e3448792d3f6a945a9b2c6b75 "ma na n^a Na pa ba ta da ka ga ?a tSa dZa fa va Ta Da sa za Sa xa Qa ha ja wa la Ra R2a _:_ ma mE mO m@ me mo mi mu maI meI mOI maU m@U" test_phwav mt 03231022bb750335042309d6d2acd55f214a8967 "ma na Na pa ta ka ?a ba da ga p\`a t\`a k\`a tSa dZa tS\`a Ba sa za Sa Za xa ha la ja wa ra _:_ mi me my ma m@ mo mu" +test_phwav mto bd45ab06741222328c2068f5a14a08b052dbdaa6 "a A e @ i 8 o oU u k k# ga t T t# da p p# b v f s s. z. ts dz m n N ra la j C a?e ha" test_phwav my 77eeafb213bfd0756319b2766be8364a2bff46ad "na Na la ja pa pha fa ta tha ka kha tS;a tS;ha S;a s.a tsa tsha ts.a ts.ha N-a _:_ ma mA mai mAu m@ m@r mE mei mi mi[ mi. miA miAu miE mio miou mo mo- mou mong mu muA mua muai mu@ mei muo my myu my& myE my@ myi _:_ ma11 ma21 ma214 ma22 ma33 ma35 ma44 ma51 ma53 ma55" test_phwav nb adbf0b2e74a76ff7bd2463223f648d479515a314 "m#a ma n#a na n^#a n^a N#a Na pa ta ca ka fa va Ta Da sa Ca J^a xa Qa ha l#a la tl#a r#a ra _:_ mi mi: mI mI: mE mE: ma ma: mO mO: mu mu: my my: mW mW: maI maI: meI meI: maU maU: moU moU: mYy mOI myI" test_phwav nci 8c578e588c4f0a283359d62754fde039b14c8aef "ma na Na pa ta ka ba da ga fa Ta sa Sa xa ha va Da za Za tSa dZa la ra ja wa t2a t#a d#a z#a r-a z/2a w#a m- n- N- _:_ mI mE ma m0 mV mU mi: mA: mO: mu: m3: mA@ mO@ mo@ mU@ mi@3 mIR mVR mi@ me@ mi m@ m3 me# mI# mI2 meI maI mOI moU maU maa mO2 maI@ maI3 maU@" From ae3571e1dfc05af7270d544b94c0e88998a5cfb0 Mon Sep 17 00:00:00 2001 From: Andiv06 <94701422+Andiv06@users.noreply.github.com> Date: Thu, 12 May 2022 19:58:13 +0300 Subject: [PATCH 14/50] Update K'iche --- dictsource/quc_list | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/dictsource/quc_list b/dictsource/quc_list index 8e5f29a6..4aa982c2 100644 --- a/dictsource/quc_list +++ b/dictsource/quc_list @@ -1,11 +1,11 @@ -// numbers -_1 jun -_2 keb' -_3 oxib' -_4 kajib' -_5 job' -_6 waqib' -_7 wuqub' -_8 wajxaqib' -_9 b'elejeb' -_10 lajuj +// Native numbers 1-10 +_1n jun +_2n keb' +_3n oxib' +_4n kajib' +_5n job' +_6n waqib' +_7n wuqub' +_8n wajxaqib' +_9n b'elejeb' +_10n lajuj From 3d250c6e771ede2c2af3f5b60896a4a806d54f53 Mon Sep 17 00:00:00 2001 From: Bill Dengler Date: Wed, 18 May 2022 03:12:11 -0400 Subject: [PATCH 15/50] Fix pronunciation of Boise --- dictsource/en_list | 1 + 1 file changed, 1 insertion(+) diff --git a/dictsource/en_list b/dictsource/en_list index e253fa4a..4a8cc66a 100644 --- a/dictsource/en_list +++ b/dictsource/en_list @@ -1129,6 +1129,7 @@ blurry bl3:ri boardmember $1 bobsled $alt1 boing bOIN +boise 'bOIsi $only bologna b@loUni bolognese b0l@n'eIz bombard $2 From 1321367988a94e483170f0c57bdf3d77382acce7 Mon Sep 17 00:00:00 2001 From: Andiv06 <94701422+Andiv06@users.noreply.github.com> Date: Mon, 23 May 2022 09:10:32 +0300 Subject: [PATCH 16/50] Update qdb Fix Lang Belta, because the underscore line has been removed --- espeak-ng-data/lang/art/qdb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/espeak-ng-data/lang/art/qdb b/espeak-ng-data/lang/art/qdb index c4fff975..eb5ea363 100644 --- a/espeak-ng-data/lang/art/qdb +++ b/espeak-ng-data/lang/art/qdb @@ -1,4 +1,4 @@ -name Lang_Belta +name Lang Belta language qdb numbers 4 3 From 139417e8e186ec9237ffd4ae96d07a4b76b0ebbb Mon Sep 17 00:00:00 2001 From: Sean Budd Date: Thu, 9 Jun 2022 11:23:48 +1000 Subject: [PATCH 17/50] Revert "code cleanup: don't add a \0 to voices_language in LoadVoice()." This reverts commit e91d0a58612a01954687d34c7417cf0fbd3cadaa. --- src/libespeak-ng/voices.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libespeak-ng/voices.c b/src/libespeak-ng/voices.c index a7603d47..71570208 100644 --- a/src/libespeak-ng/voices.c +++ b/src/libespeak-ng/voices.c @@ -959,6 +959,8 @@ voice_t *LoadVoice(const char *vname, int control) return NULL; // no dictionary loaded } } + + voice_languages[langix] = 0; } return voice; From afdf50bfd3711f69a86c68245b8886d789a50a4a Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Thu, 9 Jun 2022 08:12:21 +0200 Subject: [PATCH 18/50] Add a note to avoid erroneous commits like e91d0a5 Fixes #1200 --- src/libespeak-ng/voices.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libespeak-ng/voices.c b/src/libespeak-ng/voices.c index 71570208..85210481 100644 --- a/src/libespeak-ng/voices.c +++ b/src/libespeak-ng/voices.c @@ -960,6 +960,7 @@ voice_t *LoadVoice(const char *vname, int control) } } + /* Terminate languages list with a zero-priority entry */ voice_languages[langix] = 0; } From 2d3a49b1611e5e9d068f94c1f7f27c2da126a1f7 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Thu, 9 Jun 2022 08:16:02 +0200 Subject: [PATCH 19/50] Make static arrays undefined on entry into LoadVoice This would have caught #1200 --- src/libespeak-ng/voices.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libespeak-ng/voices.c b/src/libespeak-ng/voices.c index 85210481..2b91859d 100644 --- a/src/libespeak-ng/voices.c +++ b/src/libespeak-ng/voices.c @@ -554,6 +554,12 @@ voice_t *LoadVoice(const char *vname, int control) static char voice_name[40]; // voice name for current_voice_selected static char voice_languages[100]; // list of languages and priorities for current_voice_selected + if (!tone_only) { + MAKE_MEM_UNDEFINED(&voice_identifier, sizeof(voice_identifier)); + MAKE_MEM_UNDEFINED(&voice_name, sizeof(voice_name)); + MAKE_MEM_UNDEFINED(&voice_languages, sizeof(voice_languages)); + } + strncpy0(voicename, vname, sizeof(voicename)); if (control & 0x10) { strcpy(buf, vname); From a660fc04cc37f897588a444f2832d9256da89601 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Thu, 9 Jun 2022 08:40:07 +0200 Subject: [PATCH 20/50] Add more const qualifiers on static arrays So we know they are just tables, get protected from overflows, and get shared between processes --- src/espeak-ng.c | 6 +++--- src/libespeak-ng/compiledata.c | 2 +- src/libespeak-ng/compiledict.c | 8 ++++---- src/libespeak-ng/dictionary.c | 8 ++++---- src/libespeak-ng/intonation.c | 4 ++-- src/libespeak-ng/klatt.c | 16 ++++++++-------- src/libespeak-ng/numbers.c | 4 ++-- src/libespeak-ng/phonemelist.c | 2 +- src/libespeak-ng/ssml.c | 34 ++++++++++++++++----------------- src/libespeak-ng/synthdata.c | 2 +- src/libespeak-ng/synthesize.c | 2 +- src/libespeak-ng/tr_languages.c | 4 ++-- src/libespeak-ng/voices.c | 6 +++--- src/libespeak-ng/wavegen.c | 4 ++-- 14 files changed, 51 insertions(+), 51 deletions(-) diff --git a/src/espeak-ng.c b/src/espeak-ng.c index 1634cc1d..0891a24f 100644 --- a/src/espeak-ng.c +++ b/src/espeak-ng.c @@ -143,7 +143,7 @@ static void DisplayVoices(FILE *f_out, char *language) const espeak_VOICE **voices; espeak_VOICE voice_select; - static char genders[4] = { '-', 'M', 'F', '-' }; + static const char genders[4] = { '-', 'M', 'F', '-' }; if ((language != NULL) && (language[0] != 0)) { // display only voices for the specified language, in order of priority @@ -201,7 +201,7 @@ static void Write4Bytes(FILE *f, int value) static int OpenWavFile(char *path, int rate) { - static unsigned char wave_hdr[44] = { + static const unsigned char wave_hdr[44] = { 'R', 'I', 'F', 'F', 0x24, 0xf0, 0xff, 0x7f, 'W', 'A', 'V', 'E', 'f', 'm', 't', ' ', 0x10, 0, 0, 0, 1, 0, 1, 0, 9, 0x3d, 0, 0, 0x12, 0x7a, 0, 0, 2, 0, 0x10, 0, 'd', 'a', 't', 'a', 0x00, 0xf0, 0xff, 0x7f @@ -304,7 +304,7 @@ static void PrintVersion() int main(int argc, char **argv) { - static struct option long_options[] = { + static const struct option long_options[] = { { "help", no_argument, 0, 'h' }, { "stdin", no_argument, 0, 0x100 }, { "compile-debug", optional_argument, 0, 0x101 }, diff --git a/src/libespeak-ng/compiledata.c b/src/libespeak-ng/compiledata.c index 319d23b8..772f10e1 100644 --- a/src/libespeak-ng/compiledata.c +++ b/src/libespeak-ng/compiledata.c @@ -1559,7 +1559,7 @@ static void CompileSound(int keyword, int isvowel) int addr = 0; int value = 0; char path[N_ITEM_STRING]; - static int sound_instns[] = { i_FMT, i_WAV, i_VWLSTART, i_VWLENDING, i_WAVADD }; + static const int sound_instns[] = { i_FMT, i_WAV, i_VWLSTART, i_VWLENDING, i_WAVADD }; NextItemBrackets(tSTRING, 2); strcpy(path, item_string); diff --git a/src/libespeak-ng/compiledict.c b/src/libespeak-ng/compiledict.c index 26ece6fe..6e12d571 100644 --- a/src/libespeak-ng/compiledict.c +++ b/src/libespeak-ng/compiledict.c @@ -223,14 +223,14 @@ char *DecodeRule(const char *group_chars, int group_length, char *rule, int cont char suffix[20]; static char output[80]; - static char symbols[] = { + static const char symbols[] = { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '&', '%', '+', '#', 'S', 'D', 'Z', 'A', 'L', '!', ' ', '@', '?', 'J', 'N', 'K', 'V', '?', 'T', 'X', '?', 'W' }; - static char symbols_lg[] = { 'A', 'B', 'C', 'H', 'F', 'G', 'Y' }; + static const char symbols_lg[] = { 'A', 'B', 'C', 'H', 'F', 'G', 'Y' }; match_type = 0; buf_pre[0] = 0; @@ -766,8 +766,8 @@ static int isHexDigit(int c) static void copy_rule_string(char *string, int *state_out) { // state 0: conditional, 1=pre, 2=match, 3=post, 4=phonemes - static char *outbuf[5] = { rule_cond, rule_pre, rule_match, rule_post, rule_phonemes }; - static int next_state[5] = { 2, 2, 4, 4, 4 }; + static char *const outbuf[5] = { rule_cond, rule_pre, rule_match, rule_post, rule_phonemes }; + static const int next_state[5] = { 2, 2, 4, 4, 4 }; char *output; char *p; int ix; diff --git a/src/libespeak-ng/dictionary.c b/src/libespeak-ng/dictionary.c index a98caf54..51ce500a 100644 --- a/src/libespeak-ng/dictionary.c +++ b/src/libespeak-ng/dictionary.c @@ -1060,7 +1060,7 @@ void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags, char vowel_length[N_WORD_PHONEMES/2]; unsigned char phonetic[N_WORD_PHONEMES]; - static char consonant_types[16] = { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 }; + static const char consonant_types[16] = { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 }; stressflags = tr->langopts.stress_flags; @@ -1226,9 +1226,9 @@ void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags, // LANG=Russian if (stressed_syllable == 0) { // no explicit stress - guess the stress from the number of syllables - static char guess_ru[16] = { 0, 0, 1, 1, 2, 3, 3, 4, 5, 6, 7, 7, 8, 9, 10, 11 }; - static char guess_ru_v[16] = { 0, 0, 1, 1, 2, 2, 3, 3, 4, 5, 6, 7, 7, 8, 9, 10 }; // for final phoneme is a vowel - static char guess_ru_t[16] = { 0, 0, 1, 2, 3, 3, 3, 4, 5, 6, 7, 7, 7, 8, 9, 10 }; // for final phoneme is an unvoiced stop + static const char guess_ru[16] = { 0, 0, 1, 1, 2, 3, 3, 4, 5, 6, 7, 7, 8, 9, 10, 11 }; + static const char guess_ru_v[16] = { 0, 0, 1, 1, 2, 2, 3, 3, 4, 5, 6, 7, 7, 8, 9, 10 }; // for final phoneme is a vowel + static const char guess_ru_t[16] = { 0, 0, 1, 2, 3, 3, 3, 4, 5, 6, 7, 7, 7, 8, 9, 10 }; // for final phoneme is an unvoiced stop stressed_syllable = vowel_count - 3; if (vowel_count < 16) { diff --git a/src/libespeak-ng/intonation.c b/src/libespeak-ng/intonation.c index 4c9d54d9..d5e9092d 100644 --- a/src/libespeak-ng/intonation.c +++ b/src/libespeak-ng/intonation.c @@ -539,10 +539,10 @@ static int calc_pitch_segment(SYLLABLE *syllable_tab, int ix, int end_ix, TONE_H int pitch_range; int pitch_range_abs; int *drops; - signed char *overflow_tab; + const signed char *overflow_tab; SYLLABLE *syl; - static signed char continue_tab[5] = { -26, 32, 20, 8, 0 }; + static const signed char continue_tab[5] = { -26, 32, 20, 8, 0 }; drops = th->body_drops; pitch_range = (th->body_end - th->body_start) * 256; diff --git a/src/libespeak-ng/klatt.c b/src/libespeak-ng/klatt.c index b4f41059..29bf9d05 100644 --- a/src/libespeak-ng/klatt.c +++ b/src/libespeak-ng/klatt.c @@ -483,7 +483,7 @@ void KlattFini(void) static void frame_init(klatt_frame_ptr frame) { double amp_par[7]; - static double amp_par_factor[7] = { 0.6, 0.4, 0.15, 0.06, 0.04, 0.022, 0.03 }; + static const double amp_par_factor[7] = { 0.6, 0.4, 0.15, 0.06, 0.04, 0.022, 0.03 }; long Gain0_tmp; int ix; @@ -552,7 +552,7 @@ static void frame_init(klatt_frame_ptr frame) static double impulsive_source() { - static double doublet[] = { 0.0, 13000000.0, -13000000.0 }; + static const double doublet[] = { 0.0, 13000000.0, -13000000.0 }; static double vwave; if (kt_globals.nper < 3) @@ -623,7 +623,7 @@ static void pitch_synch_par_reset(klatt_frame_ptr frame) long temp; double temp1; static long skew; - static short B0[224] = { + static const short B0[224] = { 1200, 1142, 1088, 1038, 991, 948, 907, 869, 833, 799, 768, 738, 710, 683, 658, 634, 612, 590, 570, 551, 533, 515, 499, 483, 468, 454, 440, 427, 415, 403, 391, 380, 370, 360, 350, 341, 332, 323, 315, 307, 300, 292, 285, 278, 272, @@ -836,7 +836,7 @@ static double gen_noise(double noise) static double DBtoLIN(long dB) { - static short amptable[88] = { + static const short amptable[88] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 10, 11, 13, 14, 16, 18, 20, 22, 25, 28, 32, 35, 40, 45, 51, 57, 64, 71, 80, 90, 101, 114, 128, @@ -1076,10 +1076,10 @@ static void SetSynth_Klatt(int length, frame_t *fr1, frame_t *fr2, voice_t *wvoi void KlattInit() { - static short formant_hz[10] = { 280, 688, 1064, 2806, 3260, 3700, 6500, 7000, 8000, 280 }; - static short bandwidth[10] = { 89, 160, 70, 160, 200, 200, 500, 500, 500, 89 }; - static short parallel_amp[10] = { 0, 59, 59, 59, 59, 59, 59, 0, 0, 0 }; - static short parallel_bw[10] = { 59, 59, 89, 149, 200, 200, 500, 0, 0, 0 }; + static const short formant_hz[10] = { 280, 688, 1064, 2806, 3260, 3700, 6500, 7000, 8000, 280 }; + static const short bandwidth[10] = { 89, 160, 70, 160, 200, 200, 500, 500, 500, 89 }; + static const short parallel_amp[10] = { 0, 59, 59, 59, 59, 59, 59, 0, 0, 0 }; + static const short parallel_bw[10] = { 59, 59, 89, 149, 200, 200, 500, 0, 0, 0 }; int ix; diff --git a/src/libespeak-ng/numbers.c b/src/libespeak-ng/numbers.c index 4c46768e..43123503 100644 --- a/src/libespeak-ng/numbers.c +++ b/src/libespeak-ng/numbers.c @@ -691,7 +691,7 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control, ALP char ph_buf2[80]; char ph_alphabet[80]; char hexbuf[12]; - static char pause_string[] = { phonPAUSE, 0 }; + static const char pause_string[] = { phonPAUSE, 0 }; ph_buf[0] = 0; ph_alphabet[0] = 0; @@ -1039,7 +1039,7 @@ int TranslateRoman(Translator *tr, char *word, char *ph_out, WORD_TAB *wtab) char number_chars[N_WORD_BYTES]; static const char *roman_numbers = "ixcmvld"; - static int roman_values[] = { 1, 10, 100, 1000, 5, 50, 500 }; + static const int roman_values[] = { 1, 10, 100, 1000, 5, 50, 500 }; acc = 0; prev = 0; diff --git a/src/libespeak-ng/phonemelist.c b/src/libespeak-ng/phonemelist.c index 2860bf3a..850462a0 100644 --- a/src/libespeak-ng/phonemelist.c +++ b/src/libespeak-ng/phonemelist.c @@ -461,7 +461,7 @@ void MakePhonemeList(Translator *tr, int post_pause, bool start_sentence) } if ((plist3+1)->synthflags & SFLAG_LENGTHEN) { - static char types_double[] = { phFRICATIVE, phVFRICATIVE, phNASAL, phLIQUID, 0 }; + static const char types_double[] = { phFRICATIVE, phVFRICATIVE, phNASAL, phLIQUID, 0 }; if ((j > 0) && (strchr(types_double, next->type))) { // lengthen this consonant by doubling it // BUT, can't insert a phoneme at position plist3[0] because it crashes PrevPh() diff --git a/src/libespeak-ng/ssml.c b/src/libespeak-ng/ssml.c index 3696f87a..ec49b204 100644 --- a/src/libespeak-ng/ssml.c +++ b/src/libespeak-ng/ssml.c @@ -275,13 +275,13 @@ static const char *VoiceFromStack(SSML_STACK *ssml_stack, int n_ssml_stack, espe } -static wchar_t *GetSsmlAttribute(wchar_t *pw, const char *name) +static const wchar_t *GetSsmlAttribute(wchar_t *pw, const char *name) { // Gets the value string for an attribute. // Returns NULL if the attribute is not present int ix; - static wchar_t empty[1] = { 0 }; + static const wchar_t empty[1] = { 0 }; while (*pw != 0) { if (iswspace(pw[-1])) { @@ -315,11 +315,11 @@ static int GetVoiceAttributes(wchar_t *pw, int tag_type, SSML_STACK *ssml_sp, SS // a voice change. // Returns CLAUSE_TYPE_VOICE_CHANGE if there is a voice change - wchar_t *lang; - wchar_t *gender; - wchar_t *name; - wchar_t *age; - wchar_t *variant; + const wchar_t *lang; + const wchar_t *gender; + const wchar_t *name; + const wchar_t *age; + const wchar_t *variant; int value; const char *new_voice_id; @@ -384,7 +384,7 @@ static void ProcessParamStack(char *outbuf, int *outix, int n_param_stack, PARAM int value; char buf[20]; int new_parameters[N_SPEECH_PARAM]; - static char cmd_letter[N_SPEECH_PARAM] = { 0, 'S', 'A', 'P', 'R', 0, 'C', 0, 0, 0, 0, 0, 'F' }; // embedded command letters + static const char cmd_letter[N_SPEECH_PARAM] = { 0, 'S', 'A', 'P', 'R', 0, 'C', 0, 0, 0, 0, 0, 'F' }; // embedded command letters for (param = 0; param < N_SPEECH_PARAM; param++) new_parameters[param] = -1; @@ -482,7 +482,7 @@ static int ReplaceKeyName(char *outbuf, int index, int *outix) return 0; } -static void SetProsodyParameter(int param_type, wchar_t *attr1, PARAM_STACK *sp, PARAM_STACK *param_stack, int *speech_parameters) +static void SetProsodyParameter(int param_type, const wchar_t *attr1, PARAM_STACK *sp, PARAM_STACK *param_stack, int *speech_parameters) { int value; int sign; @@ -564,9 +564,9 @@ int ProcessSsmlTag(wchar_t *xml_buf, char *outbuf, int *outix, int n_outbuf, con int value3; int voice_change_flag; wchar_t *px; - wchar_t *attr1; - wchar_t *attr2; - wchar_t *attr3; + const wchar_t *attr1; + const wchar_t *attr2; + const wchar_t *attr3; int terminator; char *uri; int param_type; @@ -581,7 +581,7 @@ int ProcessSsmlTag(wchar_t *xml_buf, char *outbuf, int *outix, int n_outbuf, con } // these tags have no effect if they are self-closing, eg. - static char ignore_if_self_closing[] = { 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0 }; + static const char ignore_if_self_closing[] = { 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0 }; bool self_closing = false; int len; @@ -711,13 +711,13 @@ int ProcessSsmlTag(wchar_t *xml_buf, char *outbuf, int *outix, int n_outbuf, con value = attrlookup(attr1, mnem_emphasis); if (translator->langopts.tone_language == 1) { - static unsigned char emphasis_to_pitch_range[] = { 50, 50, 40, 70, 90, 100 }; - static unsigned char emphasis_to_volume[] = { 100, 100, 70, 110, 135, 150 }; + static const unsigned char emphasis_to_pitch_range[] = { 50, 50, 40, 70, 90, 100 }; + static const unsigned char emphasis_to_volume[] = { 100, 100, 70, 110, 135, 150 }; // tone language (eg.Chinese) do emphasis by increasing the pitch range. sp->parameter[espeakRANGE] = emphasis_to_pitch_range[value]; sp->parameter[espeakVOLUME] = emphasis_to_volume[value]; } else { - static unsigned char emphasis_to_volume2[] = { 100, 100, 75, 100, 120, 150 }; + static const unsigned char emphasis_to_volume2[] = { 100, 100, 75, 100, 120, 150 }; sp->parameter[espeakVOLUME] = emphasis_to_volume2[value]; sp->parameter[espeakEMPHASIS] = value; } @@ -855,7 +855,7 @@ int ProcessSsmlTag(wchar_t *xml_buf, char *outbuf, int *outix, int n_outbuf, con terminator = CLAUSE_NONE; if ((attr1 = GetSsmlAttribute(px, "strength")) != NULL) { - static int break_value[6] = { 0, 7, 14, 21, 40, 80 }; // *10mS + static const int break_value[6] = { 0, 7, 14, 21, 40, 80 }; // *10mS value = attrlookup(attr1, mnem_break); if (value < 3) { // adjust prepause on the following word diff --git a/src/libespeak-ng/synthdata.c b/src/libespeak-ng/synthdata.c index 128073a4..9db1b61b 100644 --- a/src/libespeak-ng/synthdata.c +++ b/src/libespeak-ng/synthdata.c @@ -428,7 +428,7 @@ static bool StressCondition(Translator *tr, PHONEME_LIST *plist, int condition, { int stress_level; PHONEME_LIST *pl; - static int condition_level[4] = { 1, 2, 4, 15 }; + static const int condition_level[4] = { 1, 2, 4, 15 }; if (phoneme_tab[plist[0].phcode]->type == phVOWEL) pl = plist; diff --git a/src/libespeak-ng/synthesize.c b/src/libespeak-ng/synthesize.c index 561de991..29789746 100644 --- a/src/libespeak-ng/synthesize.c +++ b/src/libespeak-ng/synthesize.c @@ -553,7 +553,7 @@ int FormantTransition2(frameref_t *seq, int *n_frames, unsigned int data1, unsig #define N_VCOLOUR 2 // percentage change for each formant in 256ths - static short vcolouring[N_VCOLOUR][5] = { + static const short vcolouring[N_VCOLOUR][5] = { { 243, 272, 256, 256, 256 }, // palatal consonant follows { 256, 256, 240, 240, 240 }, // retroflex }; diff --git a/src/libespeak-ng/tr_languages.c b/src/libespeak-ng/tr_languages.c index 78d28952..d02d6c5a 100644 --- a/src/libespeak-ng/tr_languages.c +++ b/src/libespeak-ng/tr_languages.c @@ -1210,7 +1210,7 @@ Translator *SelectTranslator(const char *name) break; case L('m', 'k'): // Macedonian { - static wchar_t vowels_cyrillic[] = { + static const wchar_t vowels_cyrillic[] = { // also include 'р' [R] 0x440, 0x430, 0x435, 0x438, 0x439, 0x43e, 0x443, 0x44b, 0x44d, 0x44e, 0x44f, 0x450, 0x451, 0x456, 0x457, 0x45d, 0x45e, 0 @@ -1558,7 +1558,7 @@ Translator *SelectTranslator(const char *name) { static const short stress_lengths_vi[8] = { 150, 150, 180, 180, 210, 230, 230, 240 }; static const unsigned char stress_amps_vi[] = { 16, 16, 16, 16, 22, 22, 22, 22 }; - static wchar_t vowels_vi[] = { + static const wchar_t vowels_vi[] = { 0x61, 0xe0, 0xe1, 0x1ea3, 0xe3, 0x1ea1, // a 0x103, 0x1eb1, 0x1eaf, 0x1eb3, 0x1eb5, 0x1eb7, // ă 0xe2, 0x1ea7, 0x1ea5, 0x1ea9, 0x1eab, 0x1ead, // â diff --git a/src/libespeak-ng/voices.c b/src/libespeak-ng/voices.c index 2b91859d..cc666158 100644 --- a/src/libespeak-ng/voices.c +++ b/src/libespeak-ng/voices.c @@ -356,10 +356,10 @@ void VoiceReset(int tone_only) // Set voice to the default values int pk; - static unsigned char default_heights[N_PEAKS] = { 130, 128, 120, 116, 100, 100, 128, 128, 128 }; // changed for v.1.47 - static unsigned char default_widths[N_PEAKS] = { 140, 128, 128, 160, 171, 171, 128, 128, 128 }; + static const unsigned char default_heights[N_PEAKS] = { 130, 128, 120, 116, 100, 100, 128, 128, 128 }; // changed for v.1.47 + static const unsigned char default_widths[N_PEAKS] = { 140, 128, 128, 160, 171, 171, 128, 128, 128 }; - static int breath_widths[N_PEAKS] = { 0, 200, 200, 400, 400, 400, 600, 600, 600 }; + static const int breath_widths[N_PEAKS] = { 0, 200, 200, 400, 400, 400, 600, 600, 600 }; // default is: pitch 80,118 voice->pitch_base = 0x47000; diff --git a/src/libespeak-ng/wavegen.c b/src/libespeak-ng/wavegen.c index 9441f201..271aa90c 100644 --- a/src/libespeak-ng/wavegen.c +++ b/src/libespeak-ng/wavegen.c @@ -1172,8 +1172,8 @@ static void SetSynth(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t * int length4; int qix; int cmd; - static int glottal_reduce_tab1[4] = { 0x30, 0x30, 0x40, 0x50 }; // vowel before [?], amp * 1/256 - static int glottal_reduce_tab2[4] = { 0x90, 0xa0, 0xb0, 0xc0 }; // vowel after [?], amp * 1/256 + static const int glottal_reduce_tab1[4] = { 0x30, 0x30, 0x40, 0x50 }; // vowel before [?], amp * 1/256 + static const int glottal_reduce_tab2[4] = { 0x90, 0xa0, 0xb0, 0xc0 }; // vowel after [?], amp * 1/256 end_wave = 1; From 7e608a3273750a8137157207108fb6c4bc1a7bed Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Thu, 9 Jun 2022 09:46:19 +0200 Subject: [PATCH 21/50] Make some buffers non-static These don't actually need to survive function exit. --- src/libespeak-ng/numbers.c | 2 +- src/libespeak-ng/voices.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libespeak-ng/numbers.c b/src/libespeak-ng/numbers.c index 43123503..5a627ca7 100644 --- a/src/libespeak-ng/numbers.c +++ b/src/libespeak-ng/numbers.c @@ -479,7 +479,7 @@ void LookupLetter(Translator *tr, unsigned int letter, int next_byte, char *ph_b // control, bit 0: not the first letter of a word int len; - static char single_letter[10] = { 0, 0 }; + char single_letter[10] = { 0, 0 }; unsigned int dict_flags[2]; char ph_buf3[40]; diff --git a/src/libespeak-ng/voices.c b/src/libespeak-ng/voices.c index cc666158..60d0794d 100644 --- a/src/libespeak-ng/voices.c +++ b/src/libespeak-ng/voices.c @@ -1519,7 +1519,7 @@ ESPEAK_NG_API espeak_ng_STATUS espeak_ng_SetVoiceByFile(const char *filename) int ix; espeak_VOICE voice_selector; char *variant_name; - static char buf[60]; + char buf[60]; strncpy0(buf, filename, sizeof(buf)); @@ -1556,7 +1556,7 @@ ESPEAK_NG_API espeak_ng_STATUS espeak_ng_SetVoiceByName(const char *name) int ix; espeak_VOICE voice_selector; char *variant_name; - static char buf[60]; + char buf[60]; strncpy0(buf, name, sizeof(buf)); From 24e1eaa0ccf8dc498d0b12b61b102483d8793bb0 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Thu, 9 Jun 2022 09:48:12 +0200 Subject: [PATCH 22/50] Mark static arrays undefined when they are reused So valgrind can potentially catch e.g. missing \0. --- src/libespeak-ng/compiledict.c | 2 ++ src/libespeak-ng/dictionary.c | 2 ++ src/libespeak-ng/readclause.c | 8 +++++++- src/libespeak-ng/ssml.c | 3 +++ src/libespeak-ng/synth_mbrola.c | 2 ++ src/libespeak-ng/synthdata.c | 2 ++ src/libespeak-ng/synthesize.c | 5 +++++ src/libespeak-ng/translate.c | 2 ++ src/libespeak-ng/voices.c | 6 ++++++ 9 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/libespeak-ng/compiledict.c b/src/libespeak-ng/compiledict.c index 6e12d571..dcb87475 100644 --- a/src/libespeak-ng/compiledict.c +++ b/src/libespeak-ng/compiledict.c @@ -223,6 +223,8 @@ char *DecodeRule(const char *group_chars, int group_length, char *rule, int cont char suffix[20]; static char output[80]; + MAKE_MEM_UNDEFINED(&output, sizeof(output)); + static const char symbols[] = { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '&', '%', '+', '#', 'S', 'D', 'Z', 'A', 'L', '!', diff --git a/src/libespeak-ng/dictionary.c b/src/libespeak-ng/dictionary.c index 51ce500a..a92d4771 100644 --- a/src/libespeak-ng/dictionary.c +++ b/src/libespeak-ng/dictionary.c @@ -2875,6 +2875,8 @@ int LookupDictList(Translator *tr, char **wordptr, char *ph_out, unsigned int *f char word[N_WORD_BYTES]; static char word_replacement[N_WORD_BYTES]; + MAKE_MEM_UNDEFINED(&word_replacement, sizeof(word_replacement)); + length = 0; word2 = word1 = *wordptr; diff --git a/src/libespeak-ng/readclause.c b/src/libespeak-ng/readclause.c index e8dbc57d..1c645a45 100644 --- a/src/libespeak-ng/readclause.c +++ b/src/libespeak-ng/readclause.c @@ -187,6 +187,8 @@ const char *WordToString2(unsigned int word) static char buf[5]; char *p; + MAKE_MEM_UNDEFINED(&buf, sizeof(buf)); + p = buf; for (ix = 3; ix >= 0; ix--) { if ((*p = word >> (ix*8)) != 0) @@ -227,6 +229,8 @@ static const char *LookupCharName(Translator *tr, int c, int only) char *string; static char buf[60]; + MAKE_MEM_UNDEFINED(&buf, sizeof(buf)); + buf[0] = 0; flags[0] = 0; flags[1] = 0; @@ -541,8 +545,10 @@ int ReadClause(Translator *tr, char *buf, short *charix, int *charix_top, int n_ c1 = c2; if (ungot_string_ix >= 0) { - if (ungot_string[ungot_string_ix] == 0) + if (ungot_string[ungot_string_ix] == 0) { + MAKE_MEM_UNDEFINED(&ungot_string, sizeof(ungot_string)); ungot_string_ix = -1; + } } if ((ungot_string_ix == 0) && (ungot_char2 == 0)) diff --git a/src/libespeak-ng/ssml.c b/src/libespeak-ng/ssml.c index ec49b204..dd710aaa 100644 --- a/src/libespeak-ng/ssml.c +++ b/src/libespeak-ng/ssml.c @@ -47,6 +47,7 @@ #include "synthesize.h" // for SPEED_FACTORS, speed #include "translate.h" // for CTRL_EMBEDDED, IsDigit09, utf8_out #include "voice.h" // for SelectVoice, SelectVoiceByName +#include "speech.h" // for MAKE_MEM_UNDEFINED static const MNEM_TAB ssmltags[] = { { "speak", SSML_SPEAK }, @@ -214,6 +215,8 @@ static const char *VoiceFromStack(SSML_STACK *ssml_stack, int n_ssml_stack, espe char language[40]; char buf[80]; + MAKE_MEM_UNDEFINED(&voice_name, sizeof(voice_name)); + strcpy(voice_name, ssml_stack[0].voice_name); strcpy(language, ssml_stack[0].language); voice_select.age = ssml_stack[0].voice_age; diff --git a/src/libespeak-ng/synth_mbrola.c b/src/libespeak-ng/synth_mbrola.c index 151f38ea..68e1f5e2 100644 --- a/src/libespeak-ng/synth_mbrola.c +++ b/src/libespeak-ng/synth_mbrola.c @@ -253,6 +253,8 @@ static char *WritePitch(int env, int pitch1, int pitch2, int split, int final) char buf[50]; static char output[50]; + MAKE_MEM_UNDEFINED(&output, sizeof(output)); + output[0] = 0; pitch_env = envelope_data[env]; diff --git a/src/libespeak-ng/synthdata.c b/src/libespeak-ng/synthdata.c index 9db1b61b..272fec74 100644 --- a/src/libespeak-ng/synthdata.c +++ b/src/libespeak-ng/synthdata.c @@ -208,6 +208,8 @@ frameref_t *LookupSpect(PHONEME_TAB *this_ph, int which, FMT_PARAMS *fmt_params, frame_t *frame; static frameref_t frames_buf[N_SEQ_FRAMES]; + MAKE_MEM_UNDEFINED(&frames_buf, sizeof(frames_buf)); + seq = (SPECT_SEQ *)(&phondata_ptr[fmt_params->fmt_addr]); seqk = (SPECT_SEQK *)seq; nf = seq->n_frames; diff --git a/src/libespeak-ng/synthesize.c b/src/libespeak-ng/synthesize.c index 29789746..5414871c 100644 --- a/src/libespeak-ng/synthesize.c +++ b/src/libespeak-ng/synthesize.c @@ -43,6 +43,7 @@ #include "translate.h" // for translator, LANGUAGE_OPTIONS, Trans... #include "voice.h" // for voice_t, voice, LoadVoiceVariant #include "wavegen.h" // for WcmdqInc, WcmdqFree, WcmdqStop +#include "speech.h" // for MAKE_MEM_UNDEFINED static void SmoothSpect(void); @@ -77,6 +78,8 @@ const char *WordToString(unsigned int word) int ix; static char buf[5]; + MAKE_MEM_UNDEFINED(&buf, sizeof(buf)); + for (ix = 0; ix < 4; ix++) buf[ix] = word >> (ix*8); buf[4] = 0; @@ -388,6 +391,8 @@ static frame_t *AllocFrame() ix++; if (ix >= N_FRAME_POOL) ix = 0; + + MAKE_MEM_UNDEFINED(&frame_pool[ix], sizeof(frame_pool[ix])); return &frame_pool[ix]; } diff --git a/src/libespeak-ng/translate.c b/src/libespeak-ng/translate.c index 0db80fd4..6e1d5cab 100644 --- a/src/libespeak-ng/translate.c +++ b/src/libespeak-ng/translate.c @@ -1988,6 +1988,8 @@ void TranslateClause(Translator *tr, int *tone_out, char **voice_change) if (tr == NULL) return; + MAKE_MEM_UNDEFINED(&voice_change_name, sizeof(voice_change_name)); + embedded_ix = 0; embedded_read = 0; pre_pause = 0; diff --git a/src/libespeak-ng/voices.c b/src/libespeak-ng/voices.c index 60d0794d..c96e326c 100644 --- a/src/libespeak-ng/voices.c +++ b/src/libespeak-ng/voices.c @@ -982,6 +982,7 @@ static char *ExtractVoiceVariantName(char *vname, int variant_num, int add_dir) static char variant_name[40]; char variant_prefix[5]; + MAKE_MEM_UNDEFINED(&variant_name, sizeof(variant_name)); variant_name[0] = 0; sprintf(variant_prefix, "!v%c", PATHSEP); if (add_dir == 0) @@ -1319,6 +1320,9 @@ char const *SelectVoice(espeak_VOICE *voice_select, int *found) static espeak_VOICE voice_variants[N_VOICE_VARIANTS]; static char voice_id[50]; + MAKE_MEM_UNDEFINED(&voice_variants, sizeof(voice_variants)); + MAKE_MEM_UNDEFINED(&voice_id, sizeof(voice_id)); + *found = 1; memcpy(&voice_select2, voice_select, sizeof(voice_select2)); @@ -1329,6 +1333,8 @@ char const *SelectVoice(espeak_VOICE *voice_select, int *found) // no language is specified. Get language from the named voice static char buf[60]; + MAKE_MEM_UNDEFINED(&buf, sizeof(buf)); + if (voice_select2.name == NULL) { if ((voice_select2.name = voice_select2.identifier) == NULL) voice_select2.name = ESPEAKNG_DEFAULT_VOICE; From eed7db15753b5dfb5a1321beb277491cdf1fd190 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Thu, 9 Jun 2022 11:26:17 +0200 Subject: [PATCH 23/50] Fix out-of-bound access IsLetterGroup looks for heading \0, so the padding also needs to include an \0. --- src/libespeak-ng/dictionary.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/libespeak-ng/dictionary.c b/src/libespeak-ng/dictionary.c index a92d4771..901fb040 100644 --- a/src/libespeak-ng/dictionary.c +++ b/src/libespeak-ng/dictionary.c @@ -3010,12 +3010,14 @@ int Lookup(Translator *tr, const char *word, char *ph_out) if (flags[0] & FLAG_TEXTMODE) { say_as = option_sayas; option_sayas = 0; // don't speak replacement word as letter names - // NOTE: TranslateRoman checks text[-2], so pad the start of text to prevent + // NOTE: TranslateRoman checks text[-2] and IsLetterGroup looks + // for a heading \0, so pad the start of text to prevent // it reading data on the stack. - text[0] = ' '; + text[0] = 0; text[1] = ' '; - strncpy0(text+2, word1, sizeof(text)-2); - flags0 = TranslateWord(tr, text+2, NULL, NULL); + text[2] = ' '; + strncpy0(text+3, word1, sizeof(text)-3); + flags0 = TranslateWord(tr, text+3, NULL, NULL); strcpy(ph_out, word_phonemes); option_sayas = say_as; } From e17f0764e3d11ada8ccdcfca6e8c58425f9ffacd Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Thu, 9 Jun 2022 12:06:10 +0200 Subject: [PATCH 24/50] valgrind CI: add missing debugging information --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c6c08706..385af48f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -65,7 +65,7 @@ jobs: - sanitizer: "valgrind" deps: "libtool-bin valgrind" - configflags: '' + configflags: '-g -Og' config: "" build_env: 'VALGRIND="libtool --mode=execute valgrind --track-origins=yes --leak-check=full --error-exitcode=1" ' check_env: 'VALGRIND="libtool --mode=execute valgrind --track-origins=yes --leak-check=full --error-exitcode=1" ' From 3b009398c9cd4a72f835dfc595cc56905c342267 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Thu, 9 Jun 2022 12:21:05 +0200 Subject: [PATCH 25/50] Add missing stresslevel field initialization --- src/libespeak-ng/translate.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libespeak-ng/translate.c b/src/libespeak-ng/translate.c index 6e1d5cab..f83314a7 100644 --- a/src/libespeak-ng/translate.c +++ b/src/libespeak-ng/translate.c @@ -1574,6 +1574,7 @@ static int TranslateWord2(Translator *tr, char *word, WORD_TAB *wtab, int pre_pa if (ph_code == phonSWITCH) { ph_list2[n_ph_list2].phcode = ph_code; + ph_list2[n_ph_list2].stresslevel = 0; ph_list2[n_ph_list2].sourceix = 0; ph_list2[n_ph_list2].synthflags = 0; ph_list2[n_ph_list2++].tone_ph = *p; From 6f58f75693f60ed76cda91c1d30d2b5c2b3a352d Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Thu, 9 Jun 2022 13:00:38 +0200 Subject: [PATCH 26/50] Add missing phoneme table reset When there are language switches, when we rewind to the start of the phoneme list we have to reset the phoneme table back. This avoids some branching that depends on undefined values, caught by valgrind in the case e.g. of an emoji substitution that contains a language switch. Ref #874 --- src/libespeak-ng/phonemelist.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libespeak-ng/phonemelist.c b/src/libespeak-ng/phonemelist.c index 850462a0..3628c4ca 100644 --- a/src/libespeak-ng/phonemelist.c +++ b/src/libespeak-ng/phonemelist.c @@ -291,6 +291,7 @@ void MakePhonemeList(Translator *tr, int post_pause, bool start_sentence) } } + SelectPhonemeTable(tr->phoneme_tab_ix); n_ph_list3 = SubstitutePhonemes(ph_list3) - 2; for (j = 0; (j < n_ph_list3) && (ix < N_PHONEME_LIST-3);) { @@ -321,6 +322,7 @@ void MakePhonemeList(Translator *tr, int post_pause, bool start_sentence) ph_list3[0].ph = ph; word_start = 1; + SelectPhonemeTable(tr->phoneme_tab_ix); for (j = 0; insert_ph || ((j < n_ph_list3) && (ix < N_PHONEME_LIST-3)); j++) { plist3 = &ph_list3[j]; @@ -589,4 +591,6 @@ void MakePhonemeList(Translator *tr, int post_pause, bool start_sentence) phlist[ix++].ph = phoneme_tab[phonPAUSE_SHORT]; n_phoneme_list = ix; + + SelectPhonemeTable(tr->phoneme_tab_ix); } From f4133364d1da2f5e9c836e77a75a8c911c85610d Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sat, 11 Jun 2022 16:20:19 +0200 Subject: [PATCH 27/50] Add more const qualifiers --- src/libespeak-ng/compiledict.c | 2 +- src/libespeak-ng/dictionary.c | 4 ++-- src/libespeak-ng/ssml.c | 4 ++-- src/libespeak-ng/translate.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libespeak-ng/compiledict.c b/src/libespeak-ng/compiledict.c index dcb87475..cfe31c69 100644 --- a/src/libespeak-ng/compiledict.c +++ b/src/libespeak-ng/compiledict.c @@ -768,7 +768,7 @@ static int isHexDigit(int c) static void copy_rule_string(char *string, int *state_out) { // state 0: conditional, 1=pre, 2=match, 3=post, 4=phonemes - static char *const outbuf[5] = { rule_cond, rule_pre, rule_match, rule_post, rule_phonemes }; + static char * const outbuf[5] = { rule_cond, rule_pre, rule_match, rule_post, rule_phonemes }; static const int next_state[5] = { 2, 2, 4, 4, 4 }; char *output; char *p; diff --git a/src/libespeak-ng/dictionary.c b/src/libespeak-ng/dictionary.c index 901fb040..c7c6cf89 100644 --- a/src/libespeak-ng/dictionary.c +++ b/src/libespeak-ng/dictionary.c @@ -3056,11 +3056,11 @@ int RemoveEnding(Translator *tr, char *word, int end_type, char *word_copy) char ending[50] = {0}; // these lists are language specific, but are only relevant if the 'e' suffix flag is used - static const char *add_e_exceptions[] = { + static const char * const add_e_exceptions[] = { "ion", NULL }; - static const char *add_e_additions[] = { + static const char * const add_e_additions[] = { "c", "rs", "ir", "ur", "ath", "ns", "u", "spong", // sponge "rang", // strange diff --git a/src/libespeak-ng/ssml.c b/src/libespeak-ng/ssml.c index dd710aaa..c6c2bd15 100644 --- a/src/libespeak-ng/ssml.c +++ b/src/libespeak-ng/ssml.c @@ -531,7 +531,7 @@ static void SetProsodyParameter(int param_type, const wchar_t *attr1, PARAM_STAC { NULL, -1 } }; - static const MNEM_TAB *mnem_tabs[5] = { + static const MNEM_TAB * const mnem_tabs[5] = { NULL, mnem_rate, mnem_volume, mnem_pitch, mnem_range }; @@ -648,7 +648,7 @@ int ProcessSsmlTag(wchar_t *xml_buf, char *outbuf, int *outix, int n_outbuf, con { NULL, -1 } }; - static const char *prosody_attr[5] = { + static const char * const prosody_attr[5] = { NULL, "rate", "volume", "pitch", "range" }; diff --git a/src/libespeak-ng/translate.c b/src/libespeak-ng/translate.c index f83314a7..33bf5425 100644 --- a/src/libespeak-ng/translate.c +++ b/src/libespeak-ng/translate.c @@ -342,7 +342,7 @@ int utf8_out(unsigned int c, char *buf) int n_bytes; int j; int shift; - static char unsigned code[4] = { 0, 0xc0, 0xe0, 0xf0 }; + static const char unsigned code[4] = { 0, 0xc0, 0xe0, 0xf0 }; if (c < 0x80) { buf[0] = c; From dfc322743d67abb3e154b210dcd03c0ea42bf44d Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 12 Jun 2022 00:26:11 +0200 Subject: [PATCH 28/50] MAKE_MEM_UNDEFINED: Fix warning --- src/libespeak-ng/speech.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libespeak-ng/speech.h b/src/libespeak-ng/speech.h index 5e2433b5..bf37aa96 100644 --- a/src/libespeak-ng/speech.h +++ b/src/libespeak-ng/speech.h @@ -35,7 +35,7 @@ # include # define MAKE_MEM_UNDEFINED(addr, len) VALGRIND_MAKE_MEM_UNDEFINED(addr, len) # else -# define MAKE_MEM_UNDEFINED(addr, len) ((void) (addr, len)) +# define MAKE_MEM_UNDEFINED(addr, len) ((void) ((void) addr, len)) # endif #endif From d8b5786330905118e62495b9967915a8a9c37a49 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 12 Jun 2022 01:42:12 +0200 Subject: [PATCH 29/50] Disable gradle in reprotest It seems that reprotest is breaking the gradle build --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 385af48f..8cad0ebf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -140,7 +140,7 @@ jobs: - name: autoconf run: ./autogen.sh ; chmod -x INSTALL m4/*.m4 - name: run - run: reprotest 'CFLAGS="${{ matrix.archconfigflags }}" CXXFLAGS="${{ matrix.archconfigflags }}" ./configure && make clean && make && make check && touch success' success + run: reprotest 'CFLAGS="${{ matrix.archconfigflags }}" CXXFLAGS="${{ matrix.archconfigflags }}" ./configure --without-gradle && make clean && make && make check && touch success' success distcheck: From e65278d788135e575d0038dc932bcf7962c9e360 Mon Sep 17 00:00:00 2001 From: Alexander Epaneshnikov Date: Sun, 19 Jun 2022 20:18:08 +0300 Subject: [PATCH 30/50] Android: bump versionCode we should do that on every release. Issue #1185 --- android/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/build.gradle b/android/build.gradle index 13e09910..809c950e 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -70,7 +70,7 @@ android { defaultConfig { minSdkVersion 14 targetSdkVersion 26 - versionCode 20 + versionCode 22 versionName "1.52-dev" } From e01f8d57484d861cba9227eda549802ae017ca79 Mon Sep 17 00:00:00 2001 From: Valdis Vitolins Date: Mon, 27 Jun 2022 12:29:57 +0300 Subject: [PATCH 31/50] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa303e8e..60c00d6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ The espeak-ng project is a fork of the espeak project. ### 1.52 (In Development) updated languages: +* ba (Bashkir) -- Andiv06 * be (Belarusian) -- Andiv06 * en (English) -- Bill Dengler * es (Spanish) -- Sukil Etxenike From 2f1dd8d1174160a3d468d75511d198884e5dfbc7 Mon Sep 17 00:00:00 2001 From: Valdis Vitolins Date: Mon, 27 Jun 2022 13:47:11 +0300 Subject: [PATCH 32/50] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa303e8e..efd8de0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ updated languages: * be (Belarusian) -- Andiv06 * en (English) -- Bill Dengler * es (Spanish) -- Sukil Etxenike +* it (Italian) -- Christian Leo Mameli ### 1.51 From 74cdd4053e9c1fbd4931f228d37fc263fce0afb6 Mon Sep 17 00:00:00 2001 From: Valdis Vitolins Date: Mon, 27 Jun 2022 13:57:52 +0300 Subject: [PATCH 33/50] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa303e8e..a7eedf24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ updated languages: * be (Belarusian) -- Andiv06 * en (English) -- Bill Dengler * es (Spanish) -- Sukil Etxenike +* ro (Romanian) -- Andiv06 ### 1.51 From 26099b9b7731611635a98f56e3e43c49c4ffd284 Mon Sep 17 00:00:00 2001 From: Valdis Vitolins Date: Mon, 27 Jun 2022 14:05:56 +0300 Subject: [PATCH 34/50] Update changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa303e8e..bcddf383 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,9 +10,10 @@ The espeak-ng project is a fork of the espeak project. ### 1.52 (In Development) updated languages: -* be (Belarusian) -- Andiv06 +* be (Belarusian) -- Andiv06 * en (English) -- Bill Dengler * es (Spanish) -- Sukil Etxenike +* kl (Greenlandic) -- Andiv06 ### 1.51 From f6c88196f88b87559b5761ce978b88f845b02765 Mon Sep 17 00:00:00 2001 From: Valdis Vitolins Date: Mon, 27 Jun 2022 14:09:47 +0300 Subject: [PATCH 35/50] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa303e8e..f844cef6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ updated languages: * be (Belarusian) -- Andiv06 * en (English) -- Bill Dengler * es (Spanish) -- Sukil Etxenike +* quc (K'iche') -- Andiv06 ### 1.51 From 51bb3585bbebbf233744c295081e31f5e51a6756 Mon Sep 17 00:00:00 2001 From: Valdis Vitolins Date: Mon, 27 Jun 2022 14:13:43 +0300 Subject: [PATCH 36/50] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa303e8e..8b02c1ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ updated languages: * be (Belarusian) -- Andiv06 * en (English) -- Bill Dengler * es (Spanish) -- Sukil Etxenike +* qdb (Lang Belta) -- Andiv06 ### 1.51 From 87932b85e0dbb80d0e5f392331327bd00bd80e4f Mon Sep 17 00:00:00 2001 From: MH <8741821+MH140000@users.noreply.github.com> Date: Sat, 4 Jun 2022 10:56:32 +0430 Subject: [PATCH 37/50] Update Persian --- dictsource/fa_emoji | 373 +++++++++++++++++++++++--------------------- dictsource/fa_extra | 45 ++++++ 2 files changed, 236 insertions(+), 182 deletions(-) create mode 100644 dictsource/fa_extra diff --git a/dictsource/fa_emoji b/dictsource/fa_emoji index fccfc45e..666f6330 100644 --- a/dictsource/fa_emoji +++ b/dictsource/fa_emoji @@ -26,7 +26,7 @@ $textmode //¨ double dot // [00A8] other (no translation) © حق نشر // [00A9] text|emoji //¬ not sign // [00AC] other (no translation) -® نشان تجاری ثبت‌شده // [00AE] text|emoji +® نشان تجاری ثبت شده // [00AE] text|emoji //° degrees // [00B0] other (no translation) //± plus or minus // [00B1] other (no translation) //µ micro // [00B5] other (no translation) @@ -107,7 +107,7 @@ $textmode ⌚ ساعت مچی // [231A] ⌛ ساعت شنی // [231B] -⌨ صفحه‌کلید // [2328] text|emoji +⌨ صفحه کلید // [2328] text|emoji ⏏ دکمهٔ خروج // [23CF] text|emoji ⏩ دکمهٔ سریع به جلو // [23E9] ⏪ دکمهٔ سریع به عقب // [23EA] @@ -147,7 +147,7 @@ $textmode ☁ ابر // [2601] text|emoji ☂ چتر // [2602] text|emoji ☃ آدم برفی // [2603] text|emoji -☄ ستاره دنباله‌دار // [2604] text|emoji +☄ ستاره دنباله دار // [2604] text|emoji ☎ تلفن // [260E] text|emoji ☑ علامت تیک خاکستری // [2611] text|emoji ☔ چتر خیس // [2614] @@ -187,15 +187,15 @@ $textmode //♭ flat // [266D] other (no translation) //♯ sharp // [266F] other (no translation) ♻ نماد بازیافت // [267B] text|emoji -♾ بی‌نهایتی // [267E] text|emoji -♿ علامت صندلی چرخ‌دار // [267F] +♾ بی نهایتی // [267E] text|emoji +♿ علامت صندلی چرخ دار // [267F] ⚒ چکش و کلنگ // [2692] text|emoji ⚓ لنگر // [2693] -⚔ شمشیرهای ضرب‌دری // [2694] text|emoji +⚔ شمشیرهای ضرب دری // [2694] text|emoji ⚕ نماد پزشکی // [2695] text|emoji ⚖ ترازو // [2696] text|emoji ⚗ انبیق // [2697] text|emoji -⚙ چرخ‌دنده // [2699] text|emoji +⚙ چرخ دنده // [2699] text|emoji ⚛ نماد اتم // [269B] text|emoji ⚜ نماد گل زنبق // [269C] text|emoji ⚠ هشدار // [26A0] text|emoji @@ -222,7 +222,7 @@ $textmode ⛳ پرچم در سوراخ // [26F3] ⛴ فرابر // [26F4] text|emoji ⛵ قایق بادبانی // [26F5] -⛷ اسکی‌سوار // [26F7] text|emoji +⛷ اسکی سوار // [26F7] text|emoji ⛸ اسکی روی یخ // [26F8] text|emoji ⛹ شخص با توپ // [26F9] text|emoji ⛺ چادر // [26FA] @@ -241,15 +241,15 @@ $textmode ✏ مداد // [270F] text|emoji ✒ قلم مشکی // [2712] text|emoji ✔ علامت تیک مشکی // [2714] text|emoji -✖ علامت ضرب‌در مشکی // [2716] text|emoji +✖ علامت ضرب در مشکی // [2716] text|emoji ✝ صلیب // [271D] text|emoji ✡ ستارهٔ داود // [2721] text|emoji ✨ درخشش // [2728] -✳ ستاره هشت‌پره // [2733] text|emoji -✴ ستاره هشت‌پر // [2734] text|emoji -❄ برف‌دانه // [2744] text|emoji +✳ ستاره هشت پره // [2733] text|emoji +✴ ستاره هشت پر // [2734] text|emoji +❄ برف دانه // [2744] text|emoji ❇ جرقه // [2747] text|emoji -❌ علامت ضرب‌در قرمز // [274C] +❌ علامت ضرب در قرمز // [274C] ❎ دکمه ایکس سبز // [274E] ❓ علامت سؤال قرمز // [2753] ❔ علامت سؤال سفید // [2754] @@ -281,7 +281,7 @@ $textmode // 3000..303F : CJK Symbols and Punctuation -〰 خط موج‌دار // [3030] text|emoji +〰 خط موج دار // [3030] text|emoji 〽 علامت تناوب بخش // [303D] text|emoji // 3200..32FF : Enclosed CJK Letters and Months @@ -321,7 +321,7 @@ $textmode 🈷 دکمهٔ «مقدار ماهانه» به ژاپنی // [1F237] text|emoji 🈸 دکمۀ «برنامه» به ژاپنی // [1F238] 🈹 دکمۀ «تخفیف» به ژاپنی // [1F239] -🈺 دکمۀ «آماده برای کسب‌وکار» به ژاپنی // [1F23A] +🈺 دکمۀ «آماده برای کسب وکار» به ژاپنی // [1F23A] 🉐 دکمهٔ «قیمت مناسب» به ژاپنی // [1F250] 🉑 دکمۀ «قابل قبول» به ژاپنی // [1F251] @@ -336,7 +336,7 @@ $textmode // 1F300..1F5FF : Miscellaneous Symbols and Pictographs 🌀 چرخند // [1F300] -🌁 مه‌آلود // [1F301] +🌁 مه آلود // [1F301] 🌂 چتر بسته // [1F302] 🌃 شب پرستاره // [1F303] 🌄 طلوع در کوهستان // [1F304] @@ -351,19 +351,19 @@ $textmode 🌍 نقشهٔ اروپا-افریقا روی کره // [1F30D] 🌎 نقشهٔ قارهٔ امریکا روی کره // [1F30E] 🌏 نقشهٔ آسیا-اقیانوسیه روی کره // [1F30F] -🌐 کره با نصف‌النهارها // [1F310] +🌐 کره با نصف النهارها // [1F310] 🌑 ماه نو // [1F311] 🌒 هلال فزاینده ماه // [1F312] -🌓 یک‌چهارم نخست // [1F313] +🌓 یک چهارم نخست // [1F313] 🌔 کوژماه افزاینده // [1F314] 🌕 ماه کامل // [1F315] 🌖 کوژماه کاهنده // [1F316] -🌗 یک‌چهارم پایان // [1F317] +🌗 یک چهارم پایان // [1F317] 🌘 هلال کاهنده ماه // [1F318] 🌙 هلال ماه // [1F319] 🌚 صورت ماه نو // [1F31A] -🌛 صورت یک‌چهارم اول // [1F31B] -🌜 صورت یک‌چهارم آخر // [1F31C] +🌛 صورت یک چهارم اول // [1F31B] +🌜 صورت یک چهارم آخر // [1F31C] 🌝 صورت ماه کامل // [1F31D] 🌞 صورت خورشید // [1F31E] 🌟 ستاره درخشان // [1F31F] @@ -383,8 +383,8 @@ $textmode 🌯 بوریتو // [1F32F] 🌰 فندق // [1F330] 🌱 جوانه // [1F331] -🌲 همیشه‌سبز // [1F332] -🌳 برگ‌ریز // [1F333] +🌲 همیشه سبز // [1F332] +🌳 برگ ریز // [1F333] 🌴 نخل // [1F334] 🌵 کاکتوس // [1F335] 🌶 فلفل قرمز // [1F336] text|emoji @@ -399,10 +399,10 @@ $textmode 🌿 گیاه دارویی // [1F33F] 🍀 شبدر چهاربرگ // [1F340] 🍁 برگ افرا // [1F341] -🍂 برگ‌ریزان // [1F342] +🍂 برگ ریزان // [1F342] 🍃 رقص برگ در باد // [1F343] 🍄 قارچ // [1F344] -🍅 گوجه‌فرنگی // [1F345] +🍅 گوجه فرنگی // [1F345] 🍆 بادمجان // [1F346] 🍇 انگور // [1F347] 🍈 طالبی // [1F348] @@ -416,7 +416,7 @@ $textmode 🍐 گلابی // [1F350] 🍑 هلو // [1F351] 🍒 گیلاس // [1F352] -🍓 توت‌فرنگی // [1F353] +🍓 توت فرنگی // [1F353] 🍔 همبرگر // [1F354] 🍕 پیتزا // [1F355] 🍖 گوشت با استخوان // [1F356] @@ -428,8 +428,8 @@ $textmode 🍜 کاسه نودل // [1F35C] 🍝 اسپاگتی // [1F35D] 🍞 نان // [1F35E] -🍟 سیب‌زمینی سرخ‌کرده // [1F35F] -🍠 سیب‌زمینی شیرین کباب‌شده // [1F360] +🍟 سیب زمینی سرخ‌کرده // [1F35F] +🍠 سیب زمینی شیرین کباب شده // [1F360] 🍡 دانگو // [1F361] 🍢 اودن // [1F362] 🍣 سوشی // [1F363] @@ -441,11 +441,11 @@ $textmode 🍩 دونات // [1F369] 🍪 کلوچه // [1F36A] 🍫 تخته شکلات // [1F36B] -🍬 آب‌نبات‌ // [1F36C] -🍭 آب‌نبات‌چوبی // [1F36D] +🍬 آب نبات // [1F36C] +🍭 آب نبات چوبی // [1F36D] 🍮 کاستارد // [1F36E] 🍯 ظرف عسل // [1F36F] -🍰 شُرت‌کیک // [1F370] +🍰 شُرت کیک // [1F370] 🍱 جعبه بنتو // [1F371] 🍲 ظرف غذا // [1F372] 🍳 آشپزی // [1F373] @@ -455,8 +455,8 @@ $textmode 🍷 جام شراب // [1F377] 🍸 جام کوکتل // [1F378] 🍹 نوشیدنی استوایی // [1F379] -🍺 لیوان آب‌جو // [1F37A] -🍻 لیوان‌های آبجو را به‌هم زدن // [1F37B] +🍺 لیوان آب جو // [1F37A] +🍻 لیوان های آبجو را به هم زدن // [1F37B] 🍼 شیشه شیر // [1F37C] 🍽 بشقاب و کارد و چنگال // [1F37D] text|emoji 🍾 شامپاین جوشان // [1F37E] @@ -467,29 +467,29 @@ $textmode 🎃 فانوس کدو تنبل // [1F383] 🎄 درخت کریسمس // [1F384] 🎅 بابا نوئل // [1F385] -🎆 آتش‌بازی // [1F386] +🎆 آتش بازی // [1F386] 🎇 فشفشه // [1F387] 🎈 بادکنک // [1F388] 🎉 بمب کاغذ رنگی // [1F389] 🎊 توپ پولکی // [1F38A] 🎋 درخت تاناباتا // [1F38B] -🎌 پرچم‌های ضرب‌دری // [1F38C] +🎌 پرچم های ضرب دری // [1F38C] 🎍 تزئین کاج // [1F38D] -🎎 عروسک‌های ژاپنی // [1F38E] -🎏 پرچم‌های ماهی در باد // [1F38F] +🎎 عروسک های ژاپنی // [1F38E] +🎏 پرچم های ماهی در باد // [1F38F] 🎐 باد سِنج // [1F390] 🎑 آئین مشاهدهٔ ماه کامل // [1F391] -🎒 کوله‌پشتی // [1F392] -🎓 کلاه فارغ‌التحصیلی // [1F393] +🎒 کوله پشتی // [1F392] +🎓 کلاه فارغ التحصیلی // [1F393] 🎖 مدال ارتشی // [1F396] text|emoji 🎗 روبان یادآوری // [1F397] text|emoji 🎙 میکروفون استودیویی // [1F399] text|emoji -🎚 درجهٔ تنظیم‌کننده // [1F39A] text|emoji -🎛 دسته‌های کنترل // [1F39B] text|emoji +🎚 درجهٔ تنظیم کننده // [1F39A] text|emoji +🎛 دسته های کنترل // [1F39B] text|emoji 🎞 حلقهٔ فیلم // [1F39E] text|emoji 🎟 بلیت ورود // [1F39F] text|emoji -🎠 چرخ‌وفلک اسبی // [1F3A0] -🎡 چرخ‌وفلک // [1F3A1] +🎠 چرخ و فلک اسبی // [1F3A0] +🎡 چرخ و فلک // [1F3A1] 🎢 ترن هوایی // [1F3A2] 🎣 چوب ماهیگیری // [1F3A3] 🎤 میکروفون // [1F3A4] @@ -497,7 +497,7 @@ $textmode 🎦 سینما // [1F3A6] 🎧 هدفون // [1F3A7] 🎨 پالت نقاشی // [1F3A8] -🎩 کلاه مردانه استوانه‌ای // [1F3A9] +🎩 کلاه مردانه استوانه ای // [1F3A9] 🎪 چادر سیرک // [1F3AA] 🎫 بلیت // [1F3AB] 🎬 کلاکت // [1F3AC] @@ -508,9 +508,9 @@ $textmode 🎱 بیلیارد // [1F3B1] 🎲 تاس بازی // [1F3B2] 🎳 بولینگ // [1F3B3] -🎴 کارت بازی گل‌دار // [1F3B4] +🎴 کارت بازی گل دار // [1F3B4] 🎵 نت موسیقی // [1F3B5] -🎶 نت‌های موسیقی // [1F3B6] +🎶 نت های موسیقی // [1F3B6] 🎷 ساکسیفون // [1F3B7] 🎸 گیتار // [1F3B8] 🎹 کیبورد موسیقی // [1F3B9] @@ -524,26 +524,26 @@ $textmode 🏁 پرچم شطرنجی // [1F3C1] 🏂 اسنوبرد // [1F3C2] 🏃 دونده // [1F3C3] -🏄 موج‌سوار // [1F3C4] +🏄 موج سوار // [1F3C4] 🏅 مدال ورزشی // [1F3C5] 🏆 جام ورزشی // [1F3C6] -🏇 مسابقه اسب‌سواری // [1F3C7] +🏇 مسابقه اسب سواری // [1F3C7] 🏈 فوتبال امریکایی // [1F3C8] 🏉 راگبی // [1F3C9] 🏊 شناگر // [1F3CA] -🏋 وزنه‌بردار // [1F3CB] text|emoji -🏌 گلف‌باز // [1F3CC] text|emoji +🏋 وزنه بردار // [1F3CB] text|emoji +🏌 گلف باز // [1F3CC] text|emoji 🏍 موتورسیکلت // [1F3CD] text|emoji 🏎 ماشین مسابقه // [1F3CE] text|emoji 🏏 کریکت // [1F3CF] 🏐 والیبال // [1F3D0] 🏑 هاکی روی چمن // [1F3D1] 🏒 هاکی روی یخ // [1F3D2] -🏓 پینگ‌پونگ // [1F3D3] +🏓 پینگ پونگ // [1F3D3] 🏔 قلهٔ برفی // [1F3D4] text|emoji 🏕 چادرزنی // [1F3D5] text|emoji 🏖 ساحل و سایبان // [1F3D6] text|emoji -🏗 ساخت‌وساز ساختمانی // [1F3D7] text|emoji +🏗 ساخت وساز ساختمانی // [1F3D7] text|emoji 🏘 منازل // [1F3D8] text|emoji 🏙 نمای شهر // [1F3D9] text|emoji 🏚 خانهٔ متروکه // [1F3DA] text|emoji @@ -553,15 +553,15 @@ $textmode 🏞 پارک ملی // [1F3DE] text|emoji 🏟 ورزشگاه // [1F3DF] text|emoji 🏠 خانه // [1F3E0] -🏡 خانهٔ حیاط‌دار // [1F3E1] +🏡 خانهٔ حیاط دار // [1F3E1] 🏢 ساختمان اداری // [1F3E2] -🏣 پست‌خانهٔ ژاپنی // [1F3E3] +🏣 پست خانهٔ ژاپنی // [1F3E3] 🏤 ادارهٔ پست // [1F3E4] 🏥 بیمارستان // [1F3E5] 🏦 بانک // [1F3E6] 🏧 نشان خودپرداز // [1F3E7] 🏨 هتل // [1F3E8] -🏩 هتل عشق‌ورزی // [1F3E9] +🏩 هتل عشق ورزی // [1F3E9] 🏪 بقالی // [1F3EA] 🏫 مدرسه // [1F3EB] 🏬 فروشگاه بزرگ // [1F3EC] @@ -606,7 +606,7 @@ $textmode 🐖 خوک // [1F416] 🐗 گراز نر // [1F417] 🐘 فیل // [1F418] -🐙 هشت‌پا // [1F419] +🐙 هشت پا // [1F419] 🐚 صدف مارپیچی // [1F41A] 🐛 حشره // [1F41B] 🐜 مورچه // [1F41C] @@ -615,8 +615,8 @@ $textmode 🐟 ماهی // [1F41F] 🐠 ماهی استوایی // [1F420] 🐡 ماهی بادکنکی // [1F421] -🐢 لاک‌پشت // [1F422] -🐣 جوجه ازتخم‌بیرون‌آمده // [1F423] +🐢 لاک پشت // [1F422] +🐣 جوجه از تخم بیرون آمده // [1F423] 🐤 جوجه // [1F424] 🐥 جوجه از روبرو // [1F425] 🐦 پرنده // [1F426] @@ -632,7 +632,7 @@ $textmode 🐰 صورت خرگوش // [1F430] 🐱 صورت گربه // [1F431] 🐲 صورت اژدها // [1F432] -🐳 نهنگ در حال آب‌فشانی // [1F433] +🐳 نهنگ در حال آب فشانی // [1F433] 🐴 صورت اسب // [1F434] 🐵 صورت میمون // [1F435] 🐶 صورت سگ // [1F436] @@ -644,7 +644,7 @@ $textmode 🐼 صورت پاندا // [1F43C] 🐽 دماغ خوک // [1F43D] 🐾 رد پنجه // [1F43E] -🐿 سنجاب راه‌راه // [1F43F] text|emoji +🐿 سنجاب راه راه // [1F43F] text|emoji 👀 دو چشم // [1F440] 👁 چشم // [1F441] text|emoji 👂 گوش // [1F442] @@ -657,38 +657,38 @@ $textmode 👉 اشاره به راست // [1F449] 👊 با مشت کوبیدن // [1F44A] 👋 تکان دادن دست // [1F44B] -👌 علامت اوکی // [1F44C] +👌 علامت اُکِی // [1F44C] 👍 پسندیدن // [1F44D] 👎 نپسندیدن // [1F44E] 👏 دست زدن // [1F44F] -👐 دست‌های باز // [1F450] +👐 دست های باز // [1F450] 👑 تاج // [1F451] 👒 کلاه زنانه // [1F452] 👓 عینک طبی // [1F453] 👔 کراوات // [1F454] -👕 تی‌شرت // [1F455] +👕 تی شِرت // [1F455] 👖 شلوار جین // [1F456] 👗 پیراهن زنانه // [1F457] 👘 کیمونو // [1F458] 👙 بیکینی // [1F459] 👚 لباس زنانه // [1F45A] -👛 کیف دستی // [1F45B] -👜 کیف دوشی // [1F45C] -👝 کیف بدون تسمه زنانه // [1F45D] +👛 کییف دستی // [1F45B] +👜 کییف دوشی // [1F45C] +👝 کییف بدون تسمه زنانه // [1F45D] 👞 کفش مردانه // [1F45E] 👟 کفش دویدن // [1F45F] 👠 کفش پاشنه بلند // [1F460] 👡 صندل زنانه // [1F461] 👢 پوتین زنانه // [1F462] 👣 رد پا // [1F463] -👤 تندیس سایه‌نما // [1F464] -👥 تندیس‌های سایه‌نما // [1F465] +👤 تندیس سایه نما // [1F464] +👥 تندیس های سایه نما // [1F465] 👦 پسر // [1F466] 👧 دختر // [1F467] 👨 مرد // [1F468] 👩 زن // [1F469] 👪 خانواده // [1F46A] -👫 زن و مرد دست در‌ دست // [1F46B] +👫 زن و مرد دست در دست // [1F46B] 👬 دو مرد دست در دست // [1F46C] 👭 دو زن دست در دست // [1F46D] 👮 پلیس // [1F46E] @@ -696,7 +696,7 @@ $textmode 👰 عروس // [1F470] 👱 آدم بلوند // [1F471] 👲 مرد با کلاه چینی // [1F472] -👳 مرد عمامه‌دار // [1F473] +👳 مرد عمامه دار // [1F473] 👴 پیرمرد // [1F474] 👵 پیرزن // [1F475] 👶 نوزاد // [1F476] @@ -713,7 +713,7 @@ $textmode 💁 آماده کمک // [1F481] 💂 گارد نظامی // [1F482] 💃 رقاص // [1F483] -💄 رژلب // [1F484] +💄 رُژلب // [1F484] 💅 لاک زدن // [1F485] 💆 ماساژ صورت // [1F486] 💇 آرایشگاه // [1F487] @@ -732,7 +732,7 @@ $textmode 💔 قلب شکسته // [1F494] 💕 دو قلب // [1F495] 💖 قلب درخشان // [1F496] -💗 قلب هیجان‌زده // [1F497] +💗 قلب هیجان زده // [1F497] 💘 قلب تیرخورده // [1F498] 💙 قلب آبی // [1F499] 💚 قلب سبز // [1F49A] @@ -741,16 +741,16 @@ $textmode 💝 قلب با روبان // [1F49D] 💞 قلب چرخان // [1F49E] 💟 قلب تزئینی // [1F49F] -💠 لوزی نقطه‌دار // [1F4A0] +💠 لوزی نقطه دار // [1F4A0] 💡 لامپ // [1F4A1] 💢 نماد عصبانیت // [1F4A2] 💣 بمب // [1F4A3] -💤 خروپف // [1F4A4] +💤 خُر و پف // [1F4A4] 💥 برخورد // [1F4A5] -💦 قطره‌های عرق // [1F4A6] +💦 قطره های عرق // [1F4A6] 💧 قطره // [1F4A7] 💨 به سرعت باد // [1F4A8] -💩 یه تپهٔ گه // [1F4A9] +💩 یه تپهٔ گوه // [1F4A9] 💪 عضله بازو // [1F4AA] 💫 سرگیجه // [1F4AB] 💬 بالن گفتار // [1F4AC] @@ -765,32 +765,32 @@ $textmode 💵 اسکناس دلار // [1F4B5] 💶 اسکناس یورو // [1F4B6] 💷 اسکناس پوند // [1F4B7] -💸 اسکناس بال‌دار // [1F4B8] +💸 اسکناس بال دار // [1F4B8] 💹 نمودار صعودی با ین // [1F4B9] 💺 صندلی // [1F4BA] 💻 رایانهٔ کیفی // [1F4BB] 💼 کیف اسناد // [1F4BC] 💽 مینی دیسک // [1F4BD] 💾 فلاپی دیسک // [1F4BE] -💿 سی‌دی // [1F4BF] -📀 دی‌وی‌دی // [1F4C0] +💿 سیدی // [1F4BF] +📀 دی وی دی // [1F4C0] 📁 پوشه // [1F4C1] 📂 پوشهٔ باز // [1F4C2] 📃 صفحهٔ تاشده // [1F4C3] -📄 صفحهٔ روبه‌بالا // [1F4C4] +📄 صفحهٔ روبه بالا // [1F4C4] 📅 تقویم // [1F4C5] 📆 تقویم رومیزی // [1F4C6] -📇 کارت‌های راهنما // [1F4C7] +📇 کارت های راهنما // [1F4C7] 📈 نمودار صعودی // [1F4C8] 📉 نمودار نزولی // [1F4C9] 📊 نمودار ستونی // [1F4CA] -📋 تختهٔ گیره‌دار // [1F4CB] +📋 تختهٔ گیره دار // [1F4CB] 📌 سنجاق // [1F4CC] -📍 سنجاق ته‌گرد // [1F4CD] +📍 سنجاق ته گِرد // [1F4CD] 📎 گیرهٔ کاغذ // [1F4CE] -📏 خط‌کش // [1F4CF] +📏 خط کش // [1F4CF] 📐 گونیا // [1F4D0] -📑 برچسب‌های نشانه‌گذاری // [1F4D1] +📑 برچسب های نشانه گذاری // [1F4D1] 📒 دفتر سیمی // [1F4D2] 📓 دفتر یادداشت // [1F4D3] 📔 دفتر با جلد سخت // [1F4D4] @@ -830,7 +830,7 @@ $textmode 📶 نوار سیگنال // [1F4F6] 📷 دوربین // [1F4F7] 📸 دوربین با فلاش // [1F4F8] -📹 دوربین فیلم‌برداری // [1F4F9] +📹 دوربین فیلم برداری // [1F4F9] 📺 تلویزیون // [1F4FA] 📻 رادیو // [1F4FB] 📼 کاست ویدیویی // [1F4FC] @@ -838,9 +838,9 @@ $textmode 📿 تسبیح // [1F4FF] 🔀 دکمهٔ پخش تصادفی // [1F500] 🔁 دکمهٔ تکرار // [1F501] -🔂 دکمهٔ یک‌بار تکرار // [1F502] -🔃 جهت عقربه‌های ساعت // [1F503] -🔄 خلاف جهت عقربه‌های ساعت // [1F504] +🔂 دکمهٔ یک بار تکرار // [1F502] +🔃 جهت عقربه های ساعت // [1F503] +🔄 خلاف جهت عقربه های ساعت // [1F504] 🔅 دکمهٔ تار کردن صفحه // [1F505] 🔆 دکمهٔ روشن کردن صفحه // [1F506] 🔇 بلندگوی خاموش // [1F507] @@ -849,8 +849,8 @@ $textmode 🔊 بلندگو با صدای بلند // [1F50A] 🔋 باتری // [1F50B] 🔌 دوشاخه // [1F50C] -🔍 ذره‌بین روبه‌چپ // [1F50D] -🔎 ذره‌بین روبه‌راست // [1F50E] +🔍 ذره بین روبه چپ // [1F50D] +🔎 ذره بین روبه راست // [1F50E] 🔏 قفل با قلم // [1F50F] 🔐 قفل و کلید // [1F510] 🔑 کلید // [1F511] @@ -858,13 +858,13 @@ $textmode 🔓 قفل باز // [1F513] 🔔 زنگ // [1F514] 🔕 خط قرمز روی زنگوله // [1F515] -🔖 نشان‌گذار کتاب // [1F516] +🔖 نشان گذار کتاب // [1F516] 🔗 حلقهٔ زنجیر // [1F517] 🔘 دکمهٔ رادیویی // [1F518] 🔙 پیکان عقب // [1F519] 🔚 پیکان پایان // [1F51A] 🔛 پیکان روشن // [1F51B] -🔜 پیکان به‌زودی // [1F51C] +🔜 پیکان به زودی // [1F51C] 🔝 پیکان رو // [1F51D] 🔞 زیر ۱۸ سال ممنوع // [1F51E] 🔟 جلد کلید: 10 // [1F51F] @@ -874,7 +874,7 @@ $textmode 🔣 ورودی نماد // [1F523] 🔤 ورودی حروف لاتین // [1F524] 🔥 آتش // [1F525] -🔦 چراغ‌قوه // [1F526] +🔦 چراغ قوه // [1F526] 🔧 آچار // [1F527] 🔨 چکش // [1F528] 🔩 پیچ و مهره // [1F529] @@ -883,9 +883,9 @@ $textmode 🔬 میکروسکوپ // [1F52C] 🔭 تلسکوپ // [1F52D] 🔮 گوی // [1F52E] -🔯 ستارهٔ شش‌پر // [1F52F] +🔯 ستارهٔ شش پر // [1F52F] 🔰 نماد ژاپنی سطح مبتدی // [1F530] -🔱 نیزهٔ سه‌شاخه // [1F531] +🔱 نیزهٔ سه شاخه // [1F531] 🔲 دکمۀ مربع مشکی // [1F532] 🔳 دکمۀ مربع سفید // [1F533] 🔴 دایره قرمز // [1F534] @@ -929,7 +929,7 @@ $textmode 🕦 ساعت یازده و نیم // [1F566] 🕧 ساعت دوازده و نیم // [1F567] 🕯 شمع // [1F56F] text|emoji -🕰 ساعت طاقچه‌ای // [1F570] text|emoji +🕰 ساعت طاقچه ای // [1F570] text|emoji 🕳 چاله // [1F573] text|emoji 🕴 پرواز مرد با لباس رسمی // [1F574] text|emoji 🕵 کارآگاه // [1F575] text|emoji @@ -941,7 +941,7 @@ $textmode 🖇 زنجیرهٔ گیره // [1F587] text|emoji 🖊 خودکار // [1F58A] text|emoji 🖋 خودنویس // [1F58B] text|emoji -🖌 قلم‌مو // [1F58C] text|emoji +🖌 قلم مو // [1F58C] text|emoji 🖍 مدادشمعی // [1F58D] text|emoji 🖐 بزن قدش // [1F590] text|emoji 🖕 انگشت میانه // [1F595] @@ -953,7 +953,7 @@ $textmode 🖲 توپک // [1F5B2] text|emoji 🖼 عکس در قاب // [1F5BC] text|emoji 🗂 جداکننده // [1F5C2] text|emoji -🗃 جعبه نگه‌داری کارت // [1F5C3] text|emoji +🗃 جعبه نگه داری کارت // [1F5C3] text|emoji 🗄 کشوی پرونده // [1F5C4] text|emoji 🗑 سطل کاغذ باطله // [1F5D1] text|emoji 🗒 دفترچهٔ یادداشت سیمی // [1F5D2] text|emoji @@ -977,26 +977,26 @@ $textmode 😀 خنده // [1F600] 😁 خندهٔ دندانی // [1F601] -😂 روده‌بر // [1F602] +😂 روده بُر // [1F602] 😃 صورت خندان // [1F603] 😄 خندان // [1F604] 😅 خنده و عرق خوشحالی // [1F605] -😆 قاه‌قاه // [1F606] -😇 هاله‌دار // [1F607] +😆 قاه قاه // [1F606] +😇 هاله دار // [1F607] 😈 خنده شرورانه // [1F608] 😉 چشمک // [1F609] 😊 لبخند خجالتی // [1F60A] 😋 صورت با زبان آب افتاده // [1F60B] -😌 آسوده‌خاطر // [1F60C] -😍 چشم‌های عاشق // [1F60D] +😌 آسوده خاطر // [1F60C] +😍 چشم های عاشق // [1F60D] 😎 باحال // [1F60E] 😏 پوزخند // [1F60F] 😐 خنثی // [1F610] -😑 صورت بی‌حالت // [1F611] +😑 صورت بی حالت // [1F611] 😒 کسل // [1F612] 😓 عرق سرد // [1F613] 😔 افسرده // [1F614] -😕 گیج‌شده // [1F615] +😕 گیج شده // [1F615] 😖 سردرگم // [1F616] 😗 بوسیدن // [1F617] 😘 بوسه فرستادن // [1F618] @@ -1005,41 +1005,41 @@ $textmode 😛 زبونک // [1F61B] 😜 زبونک و چشمک // [1F61C] 😝 زبونک با چشم بسته // [1F61D] -😞 ناامید // [1F61E] +😞 نا امید // [1F61E] 😟 نگران // [1F61F] 😠 عصبانی // [1F620] 😡 خشمگین // [1F621] 😢 گریان // [1F622] 😣 پافشاری // [1F623] 😤 ژست برندگی با دلخوری // [1F624] -😥 ناامید اما تسکین‌یافته // [1F625] +😥 نا امید اما تسکین یافته // [1F625] 😦 ناباور // [1F626] 😧 دردمند // [1F627] 😨 ترسیده // [1F628] -😩 ازپاافتاده // [1F629] -😪 خواب‌آلود // [1F62A] +😩 از پا افتاده // [1F629] +😪 خواب آلود // [1F62A] 😫 صورت خسته // [1F62B] -😬 دهن‌کجی // [1F62C] -😭 هق‌هق گریه // [1F62D] +😬 دهن کجی // [1F62C] +😭 هِق هِق گریه // [1F62D] 😮 دهان باز از تعجب // [1F62E] 😯 مات و مبهوت // [1F62F] 😰 عرق ترس // [1F630] 😱 جیغ ترس // [1F631] -😲 بهت‌زده // [1F632] -😳 سرخ‌شده // [1F633] +😲 بهت زده // [1F632] +😳 سرخ شده // [1F633] 😴 خوابیده // [1F634] 😵 گیج // [1F635] 😶 صورت بدون لب // [1F636] 😷 صورت با ماسک پزشکی // [1F637] -😸 گربه با چشم‌های خندان // [1F638] +😸 گربه با چشم های خندان // [1F638] 😹 گربه و قاه قاه خنده // [1F639] 😺 گربهٔ خندان // [1F63A] 😻 گربهٔ عاشق // [1F63B] 😼 گربه با پوزخند // [1F63C] 😽 گربه و بوسه خجالتی // [1F63D] -😾 گربهٔ اخم‌کرده // [1F63E] +😾 گربهٔ اخم کرده // [1F63E] 😿 گربهٔ گریان // [1F63F] -🙀 گربهٔ بهت‌زده // [1F640] +🙀 گربهٔ بهت زده // [1F640] 🙁 دلخور // [1F641] 🙂 لبخند ملایم // [1F642] 🙃 صورت وارونه // [1F643] @@ -1047,14 +1047,14 @@ $textmode 🙅 ابداً نه // [1F645] 🙆 باشه // [1F646] 🙇 عذرخواهی // [1F647] -🙈 میمون شرنبین // [1F648] -🙉 میمون شرنشنو // [1F649] -🙊 میمون شرنگو // [1F64A] -🙋 ای ول // [1F64B] +🙈 میمون شر نبین // [1F648] +🙉 میمون شر نشنو // [1F649] +🙊 میمون شر نگو // [1F64A] +🙋 اِی وَل // [1F64B] 🙌 تمجید // [1F64C] 🙍 آدم اخمو // [1F64D] 🙎 آدم ناراضی // [1F64E] -🙏 خواهش می‌کنم // [1F64F] +🙏 خواهش می کنم // [1F64F] // 1F680..1F6FF : Transport and Map Symbols @@ -1062,7 +1062,7 @@ $textmode 🚁 هلیکوپتر // [1F681] 🚂 لوکوموتیو // [1F682] 🚃 واگن ریلی // [1F683] -🚄 قطار سریع‌السیر // [1F684] +🚄 قطار سریع السیر // [1F684] 🚅 قطار تندرو // [1F685] 🚆 قطار // [1F686] 🚇 قطار شهری // [1F687] @@ -1071,46 +1071,46 @@ $textmode 🚊 تراموا // [1F68A] 🚋 قطار خیابانی // [1F68B] 🚌 اتوبوس // [1F68C] -🚍 اتوبوس روبه‌جلو // [1F68D] +🚍 اتوبوس روبه جلو // [1F68D] 🚎 اتوبوس برقی // [1F68E] 🚏 ایستگاه اتوبوس // [1F68F] -🚐 مینی‌بوس // [1F690] +🚐 مینی بوس // [1F690] 🚑 آمبولانس // [1F691] -🚒 ماشین آتش‌نشانی // [1F692] +🚒 ماشین آتش نشانی // [1F692] 🚓 ماشین پلیس // [1F693] -🚔 ماشین پلیسی که نزدیک می‌شود // [1F694] +🚔 ماشین پلیسی که نزدیک می شود // [1F694] 🚕 تاکسی // [1F695] -🚖 تاکسی‌ای که نزدیک می‌شود // [1F696] +🚖 تاکسی ای که نزدیک می شود // [1F696] 🚗 خودرو // [1F697] -🚘 خودرویی که نزدیک می‌شود // [1F698] -🚙 خودروی شاسی‌بلند // [1F699] +🚘 خودرویی که نزدیک می شود // [1F698] +🚙 خودروی شاسی بلند // [1F699] 🚚 کامیون پخش // [1F69A] 🚛 کامیون مفصلی // [1F69B] 🚜 تراکتور // [1F69C] -🚝 تک‌ریل // [1F69D] +🚝 تک ریل // [1F69D] 🚞 ریل کوهستانی // [1F69E] 🚟 قطار معلق // [1F69F] -🚠 تله‌کابین کوهستانی // [1F6A0] +🚠 تله کابین کوهستانی // [1F6A0] 🚡 تراموای هوایی // [1F6A1] 🚢 کشتی // [1F6A2] 🚣 قایق پارویی // [1F6A3] 🚤 قایق تندرو // [1F6A4] 🚥 چراغ راهنمایی افقی // [1F6A5] 🚦 چراغ راهنمایی عمودی // [1F6A6] -🚧 ساخت‌وساز // [1F6A7] +🚧 ساخت وساز // [1F6A7] 🚨 چراغ ماشین پلیس // [1F6A8] 🚩 پرچم مثلثی // [1F6A9] 🚪 در // [1F6AA] 🚫 ممنوع // [1F6AB] 🚬 سیگار // [1F6AC] 🚭 سیگار کشیدن ممنوع // [1F6AD] -🚮 علامت ریختن زباله در زباله‌دان // [1F6AE] +🚮 علامت ریختن زباله در زباله دان // [1F6AE] 🚯 ریختن زباله ممنوع // [1F6AF] 🚰 آب آشامیدنی // [1F6B0] 🚱 آب غیرآشامیدنی // [1F6B1] 🚲 دوچرخه // [1F6B2] 🚳 دوچرخه ممنوع // [1F6B3] -🚴 دوچرخه‌سوار // [1F6B4] +🚴 دوچرخه سوار // [1F6B4] 🚵 دوچرخه کوهستان // [1F6B5] 🚶 عابر پیاده // [1F6B6] 🚷 عابر پیاده ممنوع // [1F6B7] @@ -1151,17 +1151,17 @@ $textmode 🛵 اسکوتر // [1F6F5] 🛶 بلم // [1F6F6] 🛷 سورتمه // [1F6F7] -🛸 بشقاب‌پرنده // [1F6F8] +🛸 بشقاب پرنده // [1F6F8] 🛹 تختهٔ اسکیت // [1F6F9] // 1F900..1F9FF : Supplemental Symbols and Pictographs 🤐 دهان چفت // [1F910] -🤑 صورت پول‌دوست // [1F911] -🤒 تب‌دار // [1F912] +🤑 صورت پول دوست // [1F911] +🤒 تب دار // [1F912] 🤓 خوره // [1F913] 🤔 درحال تفکر // [1F914] -🤕 سر باندپیچی‌شده // [1F915] +🤕 سر باند پیچی شده // [1F915] 🤖 روبات // [1F916] 🤗 بغل کردن // [1F917] 🤘 شاخ شیطان // [1F918] @@ -1199,22 +1199,22 @@ $textmode 🤸 حرکت چرخ و فلک // [1F938] 🤹 ژانگولربازی // [1F939] 🤺 شمشیربازی // [1F93A] -🤼 کُشتی‌گیران // [1F93C] +🤼 کُشتی گیران // [1F93C] 🤽 واترپلو // [1F93D] 🤾 هندبال // [1F93E] 🥀 گل پژمرده // [1F940] 🥁 طبل // [1F941] -🥂 صدای به‌هم خوردن پیاله‌ها // [1F942] -🥃 لیوان ته‌گنبدی // [1F943] +🥂 صدای به هم خوردن پیاله ها // [1F942] +🥃 لیوان ته گنبدی // [1F943] 🥄 قاشق // [1F944] 🥅 دروازه // [1F945] 🥇 مدال طلا // [1F947] 🥈 مدال نقره // [1F948] 🥉 مدال برنز // [1F949] -🥊 دست‌کش بوکس // [1F94A] +🥊 دست کش بوکس // [1F94A] 🥋 لباس هنرهای رزمی // [1F94B] 🥌 سنگ کرلینگ // [1F94C] -🥎 سافت‌بال // [1F94E] +🥎 سافت بال // [1F94E] 🥏 فریزبی // [1F94F] 🥐 کرواسان // [1F950] 🥑 آووکادو // [1F951] @@ -1234,35 +1234,35 @@ $textmode 🥟 کوفته // [1F95F] 🥠 شیرینی شانس // [1F960] 🥡 جعبه بردنی // [1F961] -🥢 چاپ‌استیک // [1F962] +🥢 چاپ استیک // [1F962] 🥣 کاسه و قاشق // [1F963] 🥤 فنجان با نی // [1F964] 🥥 نارگیل // [1F965] 🥦 بروکلی // [1F966] 🥧 پای // [1F967] -🥨 چوب‌شور // [1F968] +🥨 چوب شور // [1F968] 🥩 برش گوشت // [1F969] 🥪 ساندویچ // [1F96A] 🥫 غذای کنسروشده // [1F96B] -🥬 برگ‌سبز // [1F96C] +🥬 برگ سبز // [1F96C] 🥭 انبه // [1F96D] 🥮 کیک ماه // [1F96E] 🥯 نان بیگل // [1F96F] -🥰 صورت خندان با ۳ قلب // [1F970] +🥰 صورت خندان با 3 قلب // [1F970] 🥳 جشن و سور // [1F973] 🥴 نشئه // [1F974] 🥵 خیلی گرم // [1F975] 🥶 خیلی سرد // [1F976] -🥺 التماس‌کنان // [1F97A] +🥺 التماس کنان // [1F97A] 🥼 روپوش آزمایشگاه // [1F97C] 🥽 عینک ایمنی // [1F97D] -🥾 چکمه راه‌پیمایی // [1F97E] -🥿 کفش بی‌پاشنه // [1F97F] +🥾 چکمه راه پیمایی // [1F97E] +🥿 کفش بی پاشنه // [1F97F] 🦀 خرچنگ // [1F980] 🦁 صورت شیر // [1F981] 🦂 عقرب // [1F982] 🦃 بوقلمون // [1F983] -🦄 صورت تک‌شاخ // [1F984] +🦄 صورت تک شاخ // [1F984] 🦅 عقاب // [1F985] 🦆 مرغابی // [1F986] 🦇 خفاش // [1F987] @@ -1278,9 +1278,9 @@ $textmode 🦑 ماهی مرکب // [1F991] 🦒 زرافه // [1F992] 🦓 گورخر // [1F993] -🦔 جوجه‌تیغی // [1F994] +🦔 جوجه تیغی // [1F994] 🦕 سوسمار // [1F995] -🦖 تی‌رکس // [1F996] +🦖 تی رکس // [1F996] 🦗 جیرجیرک // [1F997] 🦘 کانگورو // [1F998] 🦙 لاما // [1F999] @@ -1293,8 +1293,8 @@ $textmode 🦠 میکروب // [1F9A0] 🦡 گورکن // [1F9A1] 🦢 قو // [1F9A2] -🦰 موقرمز // [1F9B0] -🦱 موفرفری // [1F9B1] +🦰 مو قرمز // [1F9B0] +🦱 مو فرفری // [1F9B1] 🦲 تاس // [1F9B2] 🦳 موسفید // [1F9B3] 🦴 استخوان // [1F9B4] @@ -1306,25 +1306,25 @@ $textmode 🧀 قاچ پنیر // [1F9C0] 🧁 کیک فنجانی // [1F9C1] 🧂 نمک // [1F9C2] -🧐 صورت با عینک یک‌چشمی // [1F9D0] +🧐 صورت با عینک یک چشمی // [1F9D0] 🧑 بزرگسال // [1F9D1] 🧒 بچه // [1F9D2] -🧓 میان‌سال // [1F9D3] -🧔 ریش‌دار // [1F9D4] +🧓 میان سال // [1F9D3] +🧔 ریش دار // [1F9D4] 🧕 زن با روسری // [1F9D5] 🧖 فردی در حمام بخار // [1F9D6] -🧗 فردی کوه‌نوردی می‌کند // [1F9D7] +🧗 فردی کوه نوردی می کند // [1F9D7] 🧘 فرد در حالت خلسه // [1F9D8] 🧙 ساحر // [1F9D9] 🧚 پری // [1F9DA] -🧛 خون‌آشام // [1F9DB] +🧛 خون آشام // [1F9DB] 🧜 دریامردمان // [1F9DC] 🧝 اِلف // [1F9DD] 🧞 جن // [1F9DE] 🧟 مرده متحرک // [1F9DF] 🧠 مغز // [1F9E0] 🧡 قلب نارنجی // [1F9E1] -🧢 کلاه لبه‌دار // [1F9E2] +🧢 کلاه لبه دار // [1F9E2] 🧣 روسری // [1F9E3] 🧤 دستکش // [1F9E4] 🧥 پالتو // [1F9E5] @@ -1334,12 +1334,12 @@ $textmode 🧩 پازل // [1F9E9] 🧪 لولهٔ آزمایشگاه // [1F9EA] 🧫 ظرف کشت // [1F9EB] -🧬 دی‌ان‌ای // [1F9EC] -🧭 قطب‌نما // [1F9ED] +🧬 دی ان ای // [1F9EC] +🧭 قطب نما // [1F9ED] 🧮 چرتکه // [1F9EE] -🧰 جعبه‌ابزار // [1F9F0] +🧰 جعبه ابزار // [1F9F0] 🧱 دیوار آجری // [1F9F1] -🧲 آهن‌ربا // [1F9F2] +🧲 آهن ربا // [1F9F2] 🧳 چمدان // [1F9F3] 🧴 بطری لوسیون // [1F9F4] 🧵 نخ // [1F9F5] @@ -1409,13 +1409,13 @@ $textmode 🇨🇵 پرچم: جزایر کلیپرتون // [1F1E8 1F1F5] CP 🇨🇷 پرچم: کاستاریکا // [1F1E8 1F1F7] CR 🇨🇺 پرچم: کوبا // [1F1E8 1F1FA] CU -🇨🇻 پرچم: کیپ‌ورد // [1F1E8 1F1FB] CV +🇨🇻 پرچم: کیپ ورد // [1F1E8 1F1FB] CV 🇨🇼 پرچم: کوراسائو // [1F1E8 1F1FC] CW 🇨🇽 پرچم: جزیرهٔ کریسمس // [1F1E8 1F1FD] CX 🇨🇾 پرچم: قبرس // [1F1E8 1F1FE] CY 🇨🇿 پرچم: جمهوری چک // [1F1E8 1F1FF] CZ 🇩🇪 پرچم: آلمان // [1F1E9 1F1EA] DE -🇩🇬 پرچم: دیه‌گو گارسیا // [1F1E9 1F1EC] DG +🇩🇬 پرچم: دیه گو گارسیا // [1F1E9 1F1EC] DG 🇩🇯 پرچم: جیبوتی // [1F1E9 1F1EF] DJ 🇩🇰 پرچم: دانمارک // [1F1E9 1F1F0] DK 🇩🇲 پرچم: دومینیکا // [1F1E9 1F1F2] DM @@ -1443,7 +1443,7 @@ $textmode 🇬🇫 پرچم: گویان فرانسه // [1F1EC 1F1EB] GF 🇬🇬 پرچم: گرنزی // [1F1EC 1F1EC] GG 🇬🇭 پرچم: غنا // [1F1EC 1F1ED] GH -🇬🇮 پرچم: جبل‌الطارق // [1F1EC 1F1EE] GI +🇬🇮 پرچم: جبل الطارق // [1F1EC 1F1EE] GI 🇬🇱 پرچم: گرینلند // [1F1EC 1F1F1] GL 🇬🇲 پرچم: گامبیا // [1F1EC 1F1F2] GM 🇬🇳 پرچم: گینه // [1F1EC 1F1F3] GN @@ -1455,8 +1455,8 @@ $textmode 🇬🇺 پرچم: گوام // [1F1EC 1F1FA] GU 🇬🇼 پرچم: گینهٔ بیسائو // [1F1EC 1F1FC] GW 🇬🇾 پرچم: گویان // [1F1EC 1F1FE] GY -🇭🇰 پرچم: هنگ‌کنگ، ناحیهٔ ویژهٔ حکومتی چین // [1F1ED 1F1F0] HK -🇭🇲 پرچم: جزیرهٔ هرد و جزایر مک‌دونالد // [1F1ED 1F1F2] HM +🇭🇰 پرچم: هنگ کنگ، ناحیهٔ ویژهٔ حکومتی چین // [1F1ED 1F1F0] HK +🇭🇲 پرچم: جزیرهٔ هرد و جزایر مک دونالد // [1F1ED 1F1F2] HM 🇭🇳 پرچم: هندوراس // [1F1ED 1F1F3] HN 🇭🇷 پرچم: کرواسی // [1F1ED 1F1F7] HR 🇭🇹 پرچم: هائیتی // [1F1ED 1F1F9] HT @@ -1490,8 +1490,8 @@ $textmode 🇱🇦 پرچم: لائوس // [1F1F1 1F1E6] LA 🇱🇧 پرچم: لبنان // [1F1F1 1F1E7] LB 🇱🇨 پرچم: سنت لوسیا // [1F1F1 1F1E8] LC -🇱🇮 پرچم: لیختن‌اشتاین // [1F1F1 1F1EE] LI -🇱🇰 پرچم: سری‌لانکا // [1F1F1 1F1F0] LK +🇱🇮 پرچم: لیختن اشتاین // [1F1F1 1F1EE] LI +🇱🇰 پرچم: سری لانکا // [1F1F1 1F1F0] LK 🇱🇷 پرچم: لیبریا // [1F1F1 1F1F7] LR 🇱🇸 پرچم: لسوتو // [1F1F1 1F1F8] LS 🇱🇹 پرچم: لیتوانی // [1F1F1 1F1F9] LT @@ -1501,7 +1501,7 @@ $textmode 🇲🇦 پرچم: مراکش // [1F1F2 1F1E6] MA 🇲🇨 پرچم: موناکو // [1F1F2 1F1E8] MC 🇲🇩 پرچم: مولداوی // [1F1F2 1F1E9] MD -🇲🇪 پرچم: مونته‌نگرو // [1F1F2 1F1EA] ME +🇲🇪 پرچم: مونته نگرو // [1F1F2 1F1EA] ME 🇲🇫 پرچم: سنت مارتین // [1F1F2 1F1EB] MF 🇲🇬 پرچم: ماداگاسکار // [1F1F2 1F1EC] MG 🇲🇭 پرچم: جزایر مارشال // [1F1F2 1F1ED] MH @@ -1513,7 +1513,7 @@ $textmode 🇲🇵 پرچم: جزایر ماریانای شمالی // [1F1F2 1F1F5] MP 🇲🇶 پرچم: مارتینیک // [1F1F2 1F1F6] MQ 🇲🇷 پرچم: موریتانی // [1F1F2 1F1F7] MR -🇲🇸 پرچم: مونت‌سرات // [1F1F2 1F1F8] MS +🇲🇸 پرچم: مونت سرات // [1F1F2 1F1F8] MS 🇲🇹 پرچم: مالت // [1F1F2 1F1F9] MT 🇲🇺 پرچم: موریس // [1F1F2 1F1FA] MU 🇲🇻 پرچم: مالدیو // [1F1F2 1F1FB] MV @@ -1536,15 +1536,15 @@ $textmode 🇴🇲 پرچم: عمان // [1F1F4 1F1F2] OM 🇵🇦 پرچم: پاناما // [1F1F5 1F1E6] PA 🇵🇪 پرچم: پرو // [1F1F5 1F1EA] PE -🇵🇫 پرچم: پلی‌نزی فرانسه // [1F1F5 1F1EB] PF +🇵🇫 پرچم: پلی نزی فرانسه // [1F1F5 1F1EB] PF 🇵🇬 پرچم: پاپوا گینهٔ نو // [1F1F5 1F1EC] PG 🇵🇭 پرچم: فیلیپین // [1F1F5 1F1ED] PH 🇵🇰 پرچم: پاکستان // [1F1F5 1F1F0] PK 🇵🇱 پرچم: لهستان // [1F1F5 1F1F1] PL 🇵🇲 پرچم: سن پیر و میکلن // [1F1F5 1F1F2] PM -🇵🇳 پرچم: جزایر پیت‌کرن // [1F1F5 1F1F3] PN +🇵🇳 پرچم: جزایر پیت کرن // [1F1F5 1F1F3] PN 🇵🇷 پرچم: پورتوریکو // [1F1F5 1F1F7] PR -🇵🇸 پرچم: سرزمین‌های فلسطینی // [1F1F5 1F1F8] PS +🇵🇸 پرچم: سرزمین های فلسطینی // [1F1F5 1F1F8] PS 🇵🇹 پرچم: پرتغال // [1F1F5 1F1F9] PT 🇵🇼 پرچم: پالائو // [1F1F5 1F1FC] PW 🇵🇾 پرچم: پاراگوئه // [1F1F5 1F1FE] PY @@ -1562,10 +1562,10 @@ $textmode 🇸🇬 پرچم: سنگاپور // [1F1F8 1F1EC] SG 🇸🇭 پرچم: سنت هلن // [1F1F8 1F1ED] SH 🇸🇮 پرچم: اسلوونی // [1F1F8 1F1EE] SI -🇸🇯 پرچم: اسوالبارد و جان‌ماین // [1F1F8 1F1EF] SJ +🇸🇯 پرچم: اسوالبارد و جان ماین // [1F1F8 1F1EF] SJ 🇸🇰 پرچم: اسلواکی // [1F1F8 1F1F0] SK 🇸🇱 پرچم: سیرالئون // [1F1F8 1F1F1] SL -🇸🇲 پرچم: سان‌مارینو // [1F1F8 1F1F2] SM +🇸🇲 پرچم: سان مارینو // [1F1F8 1F1F2] SM 🇸🇳 پرچم: سنگال // [1F1F8 1F1F3] SN 🇸🇴 پرچم: سومالی // [1F1F8 1F1F4] SO 🇸🇷 پرچم: سورینام // [1F1F8 1F1F7] SR @@ -1594,7 +1594,7 @@ $textmode 🇹🇿 پرچم: تانزانیا // [1F1F9 1F1FF] TZ 🇺🇦 پرچم: اوکراین // [1F1FA 1F1E6] UA 🇺🇬 پرچم: اوگاندا // [1F1FA 1F1EC] UG -🇺🇲 پرچم: جزایر دورافتادهٔ ایالات متحده // [1F1FA 1F1F2] UM +🇺🇲 پرچم: جزایر دور افتادهٔ ایالات متحده // [1F1FA 1F1F2] UM 🇺🇳 پرچم: سازمان ملل متحد // [1F1FA 1F1F3] UN 🇺🇸 پرچم: ایالات متحده // [1F1FA 1F1F8] US 🇺🇾 پرچم: اروگوئه // [1F1FA 1F1FE] UY @@ -1809,7 +1809,16 @@ $textmode 🏳‍🌈 پرچم رنگین‌کمان // [1F3F3 200D 1F308] 🏴‍☠ پرچم دزدان دریایی // [1F3F4 200D 2620] 👁‍🗨 چشم در حباب گفتار // [1F441 200D 1F5E8] - +🥲 چهرهٔ خندان با اشک // [0x1F972] +🥹 چهره با چشمان پر اشک // [0x1F979] +🥸 تغییر قیافه داده // [0x1F978] +🫣 چهره با نگاه دزدکی // [0x1FAE3] +🫢 چهره با چشمان باز و دست روی دهان // [0x1FAE2] +🫡 چهره سلام‌کنان // [0x1FAE1] +🫠 چهره درحال ذوب شدن // [0x1FAE0] +🫥 چهره با خط‌چین // [0x1FAE5] +🫤 صورت با دهان کج // [0x1FAE4] +🥱 صورت خمیازه‌کش // [0x1F971] // References: // [UCD] Unicode Character Database 11.0.0 [http://www.unicode.org/Public/11.0.0/ucd/] // [Emoji] Unicode Emoji 11.0 [http://www.unicode.org/Public/emoji/11.0/] diff --git a/dictsource/fa_extra b/dictsource/fa_extra new file mode 100644 index 00000000..9ef12b9e --- /dev/null +++ b/dictsource/fa_extra @@ -0,0 +1,45 @@ +قشنگه q1aSange: +شکلکش 'SeklakeS +دلتنگشی deltange:Si +بگیم begim +دورکاری duRkARi +اسکل oskol +فروزش foRuzeS +لانچر lAntSeR +نهایتی nahAjati +ضامنش zAmenaS +ضامنم zAmenam +ضامنت zAmenat +کرونا koRonA +نکونام nekunAm +میمند mejmand +ایوا ivA +ویجت vidZet +استیکر estikeR +ندارمش nadARameS +ندارمشون nadARameSun +میرقاسمی mirq1Asemi +کرگ koRg +آرتروز ARtRoz +دارمت dARamat +دارمش dARamaS +عبری ?ebRi +لطفته lotfete: +کورتون koRton +حوصلت ho:selat +حوصلتون ho:selatun +حوصلمون ho:selamun +حوصلشون ho:selaSun +محمدقلی mohammadq1oli +سامسونگه sAmsonge: +نقی naq1i +گلستانی golestAni +وریا vurijA +دوبلور dubloR +بهزاد behzAd +پژو peZo +اسنپ esnap +مراحم moRAhem +مراحمی moRAhemi +نمیده nemide: +سوپرمارکت supeRmARket From a0786c0354548b4a024a9ffd86943186723d9da6 Mon Sep 17 00:00:00 2001 From: Valdis Vitolins Date: Mon, 27 Jun 2022 14:28:04 +0300 Subject: [PATCH 38/50] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa303e8e..30280be3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ updated languages: * be (Belarusian) -- Andiv06 * en (English) -- Bill Dengler * es (Spanish) -- Sukil Etxenike +* fa (Persian) -- MH ### 1.51 From 99430bf13a6f098650cff6a6ff5d81baa91bfde2 Mon Sep 17 00:00:00 2001 From: "Omer I.S" <66558205+omeritzics@users.noreply.github.com> Date: Sun, 26 Jun 2022 14:08:33 +0300 Subject: [PATCH 39/50] Add Dgeshim and some rules --- dictsource/he_list | 29 +++++++++++++++++------ dictsource/he_listx | 5 +++- dictsource/he_rules | 57 +++++++++++++++++++++++++++++++++++++-------- 3 files changed, 73 insertions(+), 18 deletions(-) diff --git a/dictsource/he_list b/dictsource/he_list index 08c8ebbe..81086e43 100644 --- a/dictsource/he_list +++ b/dictsource/he_list @@ -3,32 +3,47 @@ בּ bet ב vet ג 'gimel +גּ 'gimel ד 'dalet +דּ 'dalet ה he ו vav ז 'zajin +זּ 'zajin ח Xet ט tet +טּ tet י jod +יּ jod כּ kaf כ Xaf -ךּ kaf sofit -ך Xaf sofit +ךּ kaf so'fit +ך kaf so'fit ל 'lamed +לּ 'lamed מ mem -ם mem sofit +מּ mem +ם mem so'fit נ nun -ן nun sofit +נּ nun +ן nun so'fit ס 'sameX +סּ 'sameX ע ?ajin פּ pe פ fe ף pe sofit צ 'tsadi +צּ 'tsadi ץ 'tsadi sofit -ק kof -ר Q"eS +ק kof +קּ kof +ר Q"ejS +ש Sin +שּ Sin שׁ Sin +שּׁ Sin שׂ sin +שּׂ sin תּ tav -ת Tav +ת tav diff --git a/dictsource/he_listx b/dictsource/he_listx index cc731c0f..22fcd81c 100644 --- a/dictsource/he_listx +++ b/dictsource/he_listx @@ -9,8 +9,8 @@ בדיקה bdi'ka אנגלית ang'lit אני a'ni -הוא hu היא hi +הוא hu הם hem (את רוצה) at||Q"o'tsa באנגלית be?ang'lit @@ -135,3 +135,6 @@ אמת e'met נכון na'Xon ישר ja'SaQ" +בה ba +תה te +שה se diff --git a/dictsource/he_rules b/dictsource/he_rules index cd6d25e1..c936d5c3 100644 --- a/dictsource/he_rules +++ b/dictsource/he_rules @@ -17,6 +17,7 @@ אוּי ui אָ o אָ a + אה a .group ב ב v @@ -41,19 +42,34 @@ בּוּ bu בׇּ bo בָּ ba + בה va .group ג ג g + גּ g גַ ga + גַּ ga גֵ ge + גֵּ ge גֶ ge + גֶּ ge גְ g + גְּ g גִ gi + גִּ gi גוֹ go + גּוֹ go גי gi + גִּי gi גוּ gu + גּוּ gu + גֻ gu + גֻּ gu גׇ go + גׇּ go גָ ga + גָּ ga + גה ga ג' dZ גַ' dZa גֵ' dZe @@ -76,6 +92,8 @@ דוֹ do די di דוּ du + דו du + דה da דׇ do דָ da דּ d @@ -92,17 +110,19 @@ דָ' Da .group ה - ה ? - הַ a - הֵ e - הֶ e + ה h + הַ ha + הֵ he + הֶ he + הֱ he הְ h - הִ i - הוֹ o - הי i - הוּ u - הׇ o - הָ a + הִ hi + הוֹ ho + הי hi + הוּ hu + הׇ ho + הָ ha + הּ h .group ו ו v @@ -148,6 +168,7 @@ חוּ Xu חׇ Xo חָ Xa + חה Xa .group ט ט t @@ -161,6 +182,7 @@ טוּ tu טׇ to טָ ta + טה ta .group י י j @@ -195,6 +217,8 @@ ך X ךָ Xa ךְ X + ךָּ ka + ךְּ k .group ל ל l @@ -208,6 +232,7 @@ לוּ lu לׇ lo לָ la + לה la .group מ מ m @@ -221,6 +246,7 @@ מוּ mu מׇ mo מָ ma + מה ma .group ם ם m @@ -237,6 +263,7 @@ נוּ nu נׇ no נָ na + נה na נג N .group ן @@ -254,11 +281,13 @@ סוּ su סׇ so סָ sa + סה sa .group ע ע ? עַ aa עַי ai + עיי ai עֵ e עֶ e עֶי ei @@ -271,6 +300,7 @@ עוּי ui עָ o עָ a + עה a .group פ פ f @@ -298,6 +328,7 @@ .group ף ף f + ףּ p .group צ צ ts @@ -309,6 +340,7 @@ צוֹ tso צי tsi צוּ tsu + צה tsa צׇ tso צָ tsa צ' tS @@ -322,6 +354,7 @@ צ'וּ tSu צׇ' tSo צָ' tSa + צ'ה tSa .group ץ ץ ts @@ -339,6 +372,7 @@ קוּ ku קׇ ko קָ ka + קה ka .group ר ר Q" @@ -352,6 +386,7 @@ רוּ Q"u רׇ Q"o רָ Q"a + רה Q"a .group ש ש S @@ -377,6 +412,7 @@ שׂוּ su שׇׂ so שָׂ sa + שה Sa .group ת ת t @@ -402,6 +438,7 @@ ת'וּ Tu תׇ' To תָ' Ta + תה ta .group ׇ ׇ o From 24e837efaaf81fa9dbae5eb24a9b879908238cd1 Mon Sep 17 00:00:00 2001 From: Sean Budd Date: Mon, 27 Jun 2022 21:49:07 +1000 Subject: [PATCH 40/50] Map phonemone table ms rules to id rules As this is the behaviour when building eSpeak --- phsource/phonemes | 2 ++ 1 file changed, 2 insertions(+) diff --git a/phsource/phonemes b/phsource/phonemes index 795bd937..4a13d66e 100644 --- a/phsource/phonemes +++ b/phsource/phonemes @@ -2061,3 +2061,5 @@ include ph_langbelta phonemetable be ru include ph_belarusian + +phonemetable ms id From 0711194531aaaca2db278ee42e646d76251cc302 Mon Sep 17 00:00:00 2001 From: Valdis Vitolins Date: Mon, 27 Jun 2022 14:49:53 +0300 Subject: [PATCH 41/50] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa303e8e..b02f2bf1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ updated languages: * be (Belarusian) -- Andiv06 * en (English) -- Bill Dengler * es (Spanish) -- Sukil Etxenike +* he (Hebrew) -- Omer I.S ### 1.51 From 55e452cd9b40bcd78860b808790d83ab43ef3c62 Mon Sep 17 00:00:00 2001 From: Bill Dengler Date: Wed, 29 Jun 2022 20:54:57 -0700 Subject: [PATCH 42/50] Fix pronunciation of Sammamish --- dictsource/en_list | 1 + 1 file changed, 1 insertion(+) diff --git a/dictsource/en_list b/dictsource/en_list index fa9ce00f..94c4b786 100644 --- a/dictsource/en_list +++ b/dictsource/en_list @@ -3260,6 +3260,7 @@ saliva s@laIv@ salmon sam@n ?3 salon $alt3 saloon $alt3 +sammamish s@'m'amIS san ,san $only sanguine $alt2 santoor $alt3 From 128f224cc4fbbadb0240549daf3491ce3a5a2d94 Mon Sep 17 00:00:00 2001 From: Bill Dengler Date: Wed, 29 Jun 2022 20:59:13 -0700 Subject: [PATCH 43/50] And Snohomish --- dictsource/en_list | 1 + 1 file changed, 1 insertion(+) diff --git a/dictsource/en_list b/dictsource/en_list index 94c4b786..164f8c53 100644 --- a/dictsource/en_list +++ b/dictsource/en_list @@ -3406,6 +3406,7 @@ slough slVf $verb slugabed slVg@bEd snafu snafu: snafus snafu:z +snohomish snoU'hoUmIS snooker snu:k3 sociopath soUsI@paT sofa soUf@ From f042d2357ee1debb16df8341309f56347c6f7dc1 Mon Sep 17 00:00:00 2001 From: Bill Dengler Date: Wed, 29 Jun 2022 21:07:00 -0700 Subject: [PATCH 44/50] And Puget --- dictsource/en_list | 1 + 1 file changed, 1 insertion(+) diff --git a/dictsource/en_list b/dictsource/en_list index 164f8c53..7759e3fd 100644 --- a/dictsource/en_list +++ b/dictsource/en_list @@ -3036,6 +3036,7 @@ psychosis saIk'oUsIs psychotic saIk'0tIk pud pUd // and pudding pueblo pwEbloU +puget pju:dZIt punative pju:n@tIv puny pju:ni purist pjU@Ist From 9decedb8c229e1a4219baceaab7a3d656e889e31 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Thu, 30 Jun 2022 00:50:18 +0200 Subject: [PATCH 45/50] Fix missing checks for EOF --- src/libespeak-ng/readclause.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libespeak-ng/readclause.c b/src/libespeak-ng/readclause.c index 1c645a45..902eecb7 100644 --- a/src/libespeak-ng/readclause.c +++ b/src/libespeak-ng/readclause.c @@ -339,7 +339,7 @@ static int AnnouncePunctuation(Translator *tr, int c1, int *c2_ptr, char *output if ((*bufix == 0) || (end_clause == 0) || (tr->langopts.param[LOPT_ANNOUNCE_PUNCT] & 2)) { punct_count = 1; - while ((c2 == c1) && (c1 != '<')) { // don't eat extra '<', it can miss XML tags + while (!Eof() && (c2 == c1) && (c1 != '<')) { // don't eat extra '<', it can miss XML tags punct_count++; c2 = GetC(); } @@ -653,7 +653,7 @@ int ReadClause(Translator *tr, char *buf, short *charix, int *charix_top, int n_ // an embedded command. If it's a voice change, end the clause if (c2 == 'V') { buf[ix++] = 0; // end the clause at this point - while (!iswspace(c1 = GetC()) && !Eof() && (ix < (n_buf-1))) + while (!Eof() && !iswspace(c1 = GetC()) && (ix < (n_buf-1))) buf[ix++] = c1; // add voice name to end of buffer, after the text buf[ix++] = 0; return CLAUSE_VOICE; @@ -663,7 +663,7 @@ int ReadClause(Translator *tr, char *buf, short *charix, int *charix_top, int n_ strcpy(&buf[ix], " "); ix += 3; - if ((c2 = GetC()) == '0') + if (!Eof() && (c2 = GetC()) == '0') option_punctuation = 0; else { option_punctuation = 1; @@ -671,7 +671,7 @@ int ReadClause(Translator *tr, char *buf, short *charix, int *charix_top, int n_ if (c2 != '1') { // a list of punctuation characters to be spoken, terminated by space j = 0; - while (!iswspace(c2) && !Eof()) { + while (!Eof() && !iswspace(c2)) { option_punctlist[j++] = c2; c2 = GetC(); buf[ix++] = ' '; @@ -797,7 +797,7 @@ int ReadClause(Translator *tr, char *buf, short *charix, int *charix_top, int n_ } if ((c1 == '.') && (c2 == '.')) { - while ((c_next = GetC()) == '.') { + while (!Eof() && (c_next = GetC()) == '.') { // 3 or more dots, replace by elipsis c1 = 0x2026; c2 = ' '; @@ -814,7 +814,7 @@ int ReadClause(Translator *tr, char *buf, short *charix, int *charix_top, int n_ // Handling of sequences of ? and ! like ??!?, !!??!, ?!! etc // Use only first char as determinant if(punct_data & (CLAUSE_QUESTION | CLAUSE_EXCLAMATION)) { - while(clause_type_from_codepoint(c2) & (CLAUSE_QUESTION | CLAUSE_EXCLAMATION)) { + while(!Eof() && clause_type_from_codepoint(c2) & (CLAUSE_QUESTION | CLAUSE_EXCLAMATION)) { c_next = GetC(); c2 = c_next; } From 1f76c4b8bd320714aa61ad8abb527c5d92cc5164 Mon Sep 17 00:00:00 2001 From: kmamadoudram <55332951+kmamadoudram@users.noreply.github.com> Date: Thu, 30 Jun 2022 13:06:47 +0200 Subject: [PATCH 46/50] adding fuzzer for espeak_synth (#1178) * Add: fuzzer files and modifications in config & compil * add configure.ac change * add minimize-corpus.sh * add fuzzing directory and readme * add to check if CC support libfuzzer * Make workflow dump the crash POC * Add debugging information * Run fuzzing only once a week for now Co-authored-by: kmamadoudram Co-authored-by: yocvito Co-authored-by: Samuel Thibault --- .github/workflows/ci.yml | 14 ++-- .github/workflows/fuzzing.yml | 64 +++++++++++++++ .gitignore | 11 ++- Makefile.am | 15 ++++ configure.ac | 31 ++++++- tests/fuzzing/README.md | 61 ++++++++++++++ tests/fuzzing/create_dict_corpus_file.py | 68 ++++++++++++++++ tests/fuzzing/minimize-corpus.sh | 36 +++++++++ tests/fuzzing/synth_fuzzer.c | 80 +++++++++++++++++++ ...-executable-files-with-executable-bit.test | 2 + 10 files changed, 373 insertions(+), 9 deletions(-) create mode 100644 .github/workflows/fuzzing.yml create mode 100644 tests/fuzzing/README.md create mode 100755 tests/fuzzing/create_dict_corpus_file.py create mode 100755 tests/fuzzing/minimize-corpus.sh create mode 100644 tests/fuzzing/synth_fuzzer.c diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8cad0ebf..b1425976 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,21 +22,21 @@ jobs: include: - sanitizer: "no" deps: "" - configflags: "" + configflags: "-g -Og -fno-omit-frame-pointer" config: "" build_env: "" check_env: "" - sanitizer: "address" deps: "" - configflags: "-fsanitize=address -g -Og" + configflags: "-fsanitize=address -g -Og -fno-omit-frame-pointer" config: "" build_env: "ASAN_OPTIONS=detect_leaks=0" check_env: "ASAN_OPTIONS=detect_leaks=0" - sanitizer: "leak" deps: "" - configflags: '-fsanitize=leak -g -Og' + configflags: '-fsanitize=leak -g -Og -fno-omit-frame-pointer' config: "" build_env: "LSAN_OPTIONS=fast_unwind_on_malloc=0" check_env: "LSAN_OPTIONS=fast_unwind_on_malloc=0" @@ -44,28 +44,28 @@ jobs: - sanitizer: "memory" deps: "clang" configenv: "CC=clang CXX=clang++" - configflags: "-fsanitize=memory -fsanitize-memory-track-origins=2 -g -Og" + configflags: "-fsanitize=memory -fsanitize-memory-track-origins=2 -g -Og -fno-omit-frame-pointer" config: "--without-pcaudiolib" build_env: "MSAN_OPTIONS=exitcode=42" check_env: "MSAN_OPTIONS=exitcode=42" - sanitizer: "thread" deps: "" - configflags: "-fsanitize=thread -g -Og" + configflags: "-fsanitize=thread -g -Og -fno-omit-frame-pointer" config: "" build_env: "" check_env: "" - sanitizer: "undefined" deps: "" - configflags: "-fsanitize=undefined -g -Og" + configflags: "-fsanitize=undefined -g -Og -fno-omit-frame-pointer" config: "" build_env: "UBSAN_OPTIONS=halt_on_error=1" check_env: "UBSAN_OPTIONS=halt_on_error=1" - sanitizer: "valgrind" deps: "libtool-bin valgrind" - configflags: '-g -Og' + configflags: '-g -Og -fno-omit-frame-pointer' config: "" build_env: 'VALGRIND="libtool --mode=execute valgrind --track-origins=yes --leak-check=full --error-exitcode=1" ' check_env: 'VALGRIND="libtool --mode=execute valgrind --track-origins=yes --leak-check=full --error-exitcode=1" ' diff --git a/.github/workflows/fuzzing.yml b/.github/workflows/fuzzing.yml new file mode 100644 index 00000000..287d598b --- /dev/null +++ b/.github/workflows/fuzzing.yml @@ -0,0 +1,64 @@ +name: fuzzing + +on: + workflow_dispatch: + schedule: + - cron: "0 4 * * 1" + +jobs: + fuzzing: + + runs-on: ubuntu-latest + name: Fuzz synth_espeak on ${{ matrix.arch }} for ${{ matrix.lang }} + strategy: + fail-fast: false + matrix: + arch: [x86-32, x86-64] + lang: [af, am, an, ar, as, az, ba, be, bg, bn, bpy, bs, ca, chr, cmn, cs, cv, cy, da, de, el, en, eo, es, et, eu, fa, fi, fr, ga, gd, gn, grc, gu, hak, haw, he, hi, hr, ht, hu, hy, ia, id, io, is, it, ja, jbo, ka, kk, kl, kn, ko, kok, ku, ky, la, lb, lfn, lt, lv, mi, mk, ml, mr, ms, mt, my, nci, ne, nl, no, nog, om, or, pa, pap, piqd, pl, pt, py, qdb, qu, quc, qya, ro, ru, sd, shn, si, sjn, sk, sl, smj, sq, sr, sv, sw, ta, te, th, tk, tn, tr, tt, ug, uk, ur, uz, vi, yue] + include: + - arch: x86-32 + archdeps: "gcc-multilib g++-multilib libpcaudio-dev:i386 libsonic-dev:i386 libc6-dbg:i386" + archconfigflags: "-m32" + + - arch: x86-64 + archdeps: "" + archconfigflags: '' + steps: + - uses: actions/checkout@v2 + - name: enable 32bit architecture + run: sudo dpkg --add-architecture i386 + if: matrix.arch == 'x86-32' + - name: dependencies + run: sudo apt-get update && sudo apt-get install libpcaudio-dev libsonic-dev ronn kramdown clang llvm ${{ matrix.archdeps }} + - name: autoconf + run: ./autogen.sh ; chmod -x INSTALL m4/*.m4 + - name: configure + run: CC=clang CXX=clang++ + CFLAGS="${{ matrix.archconfigflags }} -fsanitize=address,undefined -fstack-protector-strong -g -Og -fno-omit-frame-pointer" + CXXFLAGS="${{ matrix.archconfigflags }} -fsanitize=address,undefined -fstack-protector-strong -g -Og -fno-omit-frame-pointer" + LDFLAGS="-fsanitize=address,undefined -lubsan" + ./configure --with-libfuzzer + - name: Store the fuzzer config + if: ${{ failure() }} + uses: actions/upload-artifact@v2 + with: + name: config-${{ matrix.arch }}-${{ matrix.lang }}.log + path: config.log + - name: make + run: make -j + - name: Fuzz function synth_espeak() + run: mkdir tests/fuzzing/CORPUS_DIR ; FUZZ_VOICE=${{ matrix.lang }} tests/fuzzing/synth_fuzzer.test -seed=1 -runs=10000 -max_len=4096 tests/fuzzing/CORPUS_DIR + - name: Store the crash POC + if: ${{ failure() }} + uses: actions/upload-artifact@v2 + with: + name: crash-${{ matrix.arch }}-${{ matrix.lang }}.1 + path: crash-* + - name: Fuzz function synth_espeak() with language-specific input + run: cp dictsource/${{ matrix.lang }}_* tests/fuzzing/CORPUS_DIR/ ; FUZZ_VOICE=${{ matrix.lang }} tests/fuzzing/synth_fuzzer.test -seed=1 -runs=10000 -max_len=4096 tests/fuzzing/CORPUS_DIR + - name: Store the crash POC + if: ${{ failure() }} + uses: actions/upload-artifact@v2 + with: + name: crash-${{ matrix.arch }}-${{ matrix.lang }}.2 + path: crash-* diff --git a/.gitignore b/.gitignore index fe6bbdae..73dd7f93 100644 --- a/.gitignore +++ b/.gitignore @@ -123,10 +123,19 @@ espeak-ng.pc espeak-ng-*.tar.gz espeak-ng-*.*/ +# /tests/fuzzing/ +/tests/fuzzing/crash-* +/tests/fuzzing/oom-* +/tests/fuzzing/leak-* +/tests/fuzzing/fuzz-*.log +/tests/fuzzing/*.profdata +/tests/fuzzing/*.profraw +/tests/fuzzing/.deps/*.Po +/tests/fuzzing/.dirstamp +!tests/fuzzing/CORPUS*/*.txt # Windows builds src/pcaudiolib/ - !src/windows/config.h *.obj diff --git a/Makefile.am b/Makefile.am index 0efbb6d2..0ba39b90 100644 --- a/Makefile.am +++ b/Makefile.am @@ -18,6 +18,12 @@ MKDIR=mkdir -p AM_CFLAGS = \ -Isrc/include -Isrc/include/compat -I$(srcdir)/src/speechPlayer/include -I$(srcdir)/src/ucd-tools/src/include \ -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200112L +AM_CXXFLAGS = + +if USE_COVERAGE +AM_CFLAGS += -fprofile-instr-generate -fcoverage-mapping +AM_CXXFLAGS += -fprofile-instr-generate -fcoverage-mapping +endif EXTRA_DIST= CLEANFILES = dictsource/ru_listx dictsource/cmn_listx dictsource/yue_listx @@ -321,6 +327,8 @@ tests_libfuzzrunner_la_CFLAGS = -Isrc/libespeak-ng ${AM_CFLAGS} tests_libfuzzrunner_la_SOURCES = tests/fuzzrunner.c endif + + check_PROGRAMS += tests/ssml-fuzzer.test tests_ssml_fuzzer_test_CFLAGS = ${AM_CFLAGS} tests_ssml_fuzzer_test_SOURCES = tests/ssml-fuzzer.c @@ -333,9 +341,16 @@ tests_readclause_test_SOURCES += tests/dummy.cpp tests_ssml_fuzzer_test_SOURCES += tests/dummy.cpp endif + if HAVE_LIBFUZZER tests_ssml_fuzzer_test_CFLAGS += -fsanitize=fuzzer tests_ssml_fuzzer_test_LDFLAGS = -fsanitize=fuzzer + +noinst_PROGRAMS = tests/fuzzing/synth_fuzzer.test +tests_fuzzing_synth_fuzzer_test_SOURCES = tests/fuzzing/synth_fuzzer.c +tests_fuzzing_synth_fuzzer_test_LDADD = src/libespeak-ng.la +tests_fuzzing_synth_fuzzer_test_CFLAGS= ${AM_CFLAGS} -fsanitize=fuzzer -DPATH_ESPEAK_DATA=\"$(abs_top_srcdir)/espeak-ng-data\" -Isrc/libespeak-ng +tests_fuzzing_synth_fuzzer_test_LDFLAGS= ${AM_LDFLAGS} -fsanitize=fuzzer -static -lm -Wl,-z,relro ${PCAUDIOLIB_LIBS} else tests_ssml_fuzzer_test_LDADD += tests/libfuzzrunner.la endif diff --git a/configure.ac b/configure.ac index 780b2e1b..ed5c97ff 100644 --- a/configure.ac +++ b/configure.ac @@ -64,6 +64,10 @@ AC_ARG_WITH([libfuzzer], [AS_HELP_STRING([--with-libfuzzer], [enable libFuzzer in the fuzzer tests @<:@default=no@:>@])], []) +AC_ARG_WITH([coverage], + [AS_HELP_STRING([--with-coverage], [enable clang coverage in the fuzzer tests (also add coverage to lib sources) @<:@default=no@:>@])], + []) + dnl ================================================================ dnl Program checks. dnl ================================================================ @@ -131,6 +135,19 @@ else AC_MSG_ERROR([C99 is not supported by $CC.]) fi + +AC_LANG_PUSH(C) +TEMP_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS -fsanitize=fuzzer" +AC_MSG_CHECKING([if $CC supports fuzzer with the -fsanitize=fuzzer flag]) +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( [[]], [[]])], + [have_fuzzer_fuzzer=yes], + [have_fuzzer_fuzzer=no]) +AC_MSG_RESULT($have_fuzzer_fuzzer) +CFLAGS="$TEMP_CFLAGS" +AC_LANG_POP(C) + dnl ================================================================ dnl FreeBSD check. dnl ================================================================ @@ -330,7 +347,19 @@ else have_libfuzzer=no fi -AM_CONDITIONAL(HAVE_LIBFUZZER, [test x"$have_libfuzzer" = xyes]) +AM_CONDITIONAL(HAVE_LIBFUZZER, [test x"$have_libfuzzer" = xyes -a x"$have_fuzzer_fuzzer" = xyes]) + +dnl ================================================================ +dnl clang-coverage checks. +dnl ================================================================ + +if test "$with_coverage" = "yes" ; then + use_coverage=yes +else + use_coverage=no +fi + +AM_CONDITIONAL(USE_COVERAGE, [test x"$use_coverage" = xyes]) dnl ================================================================ dnl Generate output. diff --git a/tests/fuzzing/README.md b/tests/fuzzing/README.md new file mode 100644 index 00000000..122bd688 --- /dev/null +++ b/tests/fuzzing/README.md @@ -0,0 +1,61 @@ +All fuzzers here are run continously through OSS-fuzz. + +Link to OSS-fuzz integration: Pending + +# Translation fuzzers + +Currently, there is a fuzzer related to synthetizer, **synth_fuzzer** that will target **espak_Synth**. The following sections will explain how to configure the fuzzers, how to use them and how to get a coverage report of the fuzzing result. + +## Configure the project for fuzzing + +We have added some switchs to configure.ac for fuzzing and coverage. The `--with-fuzzer` switch will check if your are actually using clang and clang++ as compilers (by looking at CC and CXX) and allows generation of compilation instructions for fuzzer targets. The `--with-coverage` will add `-fprofile-instr-generate -fcoverage-mapping` to AM_CPPFLAGS in espeak/Makefile.am. + +To configure and build the project with coverage and fuzzer. +```./autogen.sh +CC=clang CXX=clang++ ./configure --with-coverage --with-fuzzer +make -j8 +``` + +## Run the fuzzers + +You are now able to run the fuzzer and will have to give 2 parameters to it. First, you need to choose a language to fuzz and set the `FUZZ_VOICE` environment variable to them. Then, you need to provide a corpus with files containing sample inputs that will be used by libfuzzer to craft the data passed to the fuzzing function (the idea is to keep corpus as minimal as possible). If you don't provide any corpus directory, libfuzzer just generates random inputs. + +Here is how you can start fuzzing `espeak_Synth` function. +``` + +# first we move to tests/fuzzing directory +cd tests/fuzzing +#to have interesting file in the corpus , there is a simple python script that allows you to do that +./create_dict_corpus_file.py -c CORPUS/ + +# we consider here you have added corpus files into tests/fuzzing/CORPUS directory +FUZZ_VOICE=en ./synth_fuzzer CORPUS/ + +# to run the fuzzer using parallelization +# you can even set more jobs than workers (the ones that just stopped will be instantly replaced by a new fuzzer process) +FUZZ_VOICE=en ./synth_fuzzer CORPUS/ -workers=8 -jobs=8 +``` +After running the fuzzer multiple times with the same corpus directory, it might be possible that many corpus files added by the fuzzer explores the same paths. Hopefully, libfuzzer allows you to minimize a corpus. There is a simple bash script in tests/fuzzing that allows you to do that. +``` +./minimize-corpus.sh CORPUS/ + + +# if you have added a POC file in the corpus directory and you want to keep it intact, change his extension to .txt and use --preserve-txt switch that keep .txt files intact in the directory +./minimize-corpus.sh --preserve-txt CORPUS/ +``` +## Look at fuzzer coverage + +If you want to see what are the source code parts that are explored by the fuzzer, you can use clang coverage. So, you have to configure with coverage switch, run the fuzzer and show coverage data from the run with llvm tools. +To be able to use the coverage data, you need first to compile the raw profile data file of the run. By default, this file is created after execution under the name of default.profraw but you can specify it with `LLVM_PROFILE_FILE`. +Here is how to do that. +``` +LLVM_PROFILE_FILE=synth_fuzzer.profraw FUZZ_VOICE=en ./synth_fuzzer CORPUS/ -workers=8 -jobs=8 + +# wait for a bit and press CTRL+C + +# compile raw profile +llvm-profdata merge -sparse synth_fuzzer.profraw -o synth_fuzzer.profdata + +# show coverage (redlines are the one wich are reached) +llvm-cov show ./synth_fuzzer -instr-profile=synth_fuzzer.profdata +``` diff --git a/tests/fuzzing/create_dict_corpus_file.py b/tests/fuzzing/create_dict_corpus_file.py new file mode 100755 index 00000000..a27c1f39 --- /dev/null +++ b/tests/fuzzing/create_dict_corpus_file.py @@ -0,0 +1,68 @@ +#!/bin/python3 +# /* +# * Copyright (C) 2022 Anna Stan , Mamaodou Dramé Kalilou , Nicolas Morel +# * +# * 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 +# * the Free Software Foundation; either version 3 of the License, or +# * (at your option) any later version. +# * +# * This program is distributed in the hope that it will be useful, +# * but WITHOUT ANY WARRANTY; without even the implied warranty of +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# * GNU General Public License for more details. +# * +# * You should have received a copy of the GNU General Public License +# * along with this program; if not, see: . +# */ +import sys +import mmap +import argparse +import shutil +import os +from os import O_RDONLY, O_RDWR, O_WRONLY, O_TRUNC, O_CREAT, SEEK_END, SEEK_CUR, SEEK_SET + +def main(argc, argv): + if argc < 2: + print('Summary: add file to the corpus ', file=sys.stderr) + print(f'Usage: {argv[0]} -c ', file=sys.stderr) + exit(1) + + ap = argparse.ArgumentParser() + + # Add the arguments to the parser + ap.add_argument("-c", "--corpus_dir", required=True, + help="corpus directory where to add the file") + args = vars(ap.parse_args()) + + + lang_list=os.getenv("FUZZ_VOICE") + if(lang_list): + list=lang_list+"_list" + else: + list="en_list" + output_name = list+"_dict_corpus.txt" + output_path=args['corpus_dir']+output_name + output= open(output_path, "w") + + path="../../dictsource/"+list + + + file = open( path, "r") + lines=file.readlines() + index=1 + for line in lines: + if line[0]=='/' and line[1]=='/': + continue + res = line.split() + if len(res): + output.write("kw") + output.write(str(index)) + index=index+1 + output.write("=") + output.write(res[0]) + output.write('\n') + file.close() + output.close() +if __name__ == "__main__": + main(len(sys.argv), sys.argv) diff --git a/tests/fuzzing/minimize-corpus.sh b/tests/fuzzing/minimize-corpus.sh new file mode 100755 index 00000000..82e21826 --- /dev/null +++ b/tests/fuzzing/minimize-corpus.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +if [[ $# -lt 1 ]] +then + echo "Usage: $0 " + echo "Usage: $0 --preserve-txt (minimize corpus but keep .txt files intact)" + exit 1 +fi + +preserve_txt=0 +if [[ "$1" == "--preserve-txt" ]] +then + preserve_txt=1 + CORPUS_DIR=$2 +else + CORPUS_DIR=$1 +fi + + +export FUZZ_VOICE=en +FUZZER=./synth_fuzzer + +TMP_DIR=$(mktemp -d) +echo "Merging..." +`$FUZZER -merge=1 $TMP_DIR $CORPUS_DIR` +echo "Removing old files..." +if [[ $preserve_txt -eq 1 ]] +then + echo " => Preserve .txt files" + rm -rvf $(find $CORPUS_DIR | grep -vE "*.txt|$CORPUS_DIR") 2>/dev/null +else + rm -rf $CORPUS_DIR/* 2>/dev/null +fi +cp $TMP_DIR/* $CORPUS_DIR 2>/dev/null +rm -rf $TMP_DIR +echo "Merging done !" diff --git a/tests/fuzzing/synth_fuzzer.c b/tests/fuzzing/synth_fuzzer.c new file mode 100644 index 00000000..ca3dddac --- /dev/null +++ b/tests/fuzzing/synth_fuzzer.c @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2018 Sascha Brawer + * + * 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 + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write see: + * . + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include +#define BOLDRED(x) "\x1b[31m\x1b[1m" x "\x1b[0m" + +static int initialized = 0; + +static int +espeak_callback(short *data, int samples, espeak_EVENT *events) +{ + (void)data; + (void)samples; + (void)events; + + return 0; +} + +/* See http://llvm.org/docs/LibFuzzer.html */ +extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); + +extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) + +{ + int buflength = size+1; + if (!initialized) + { + int options = espeakINITIALIZE_DONT_EXIT; + espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS, buflength, PATH_ESPEAK_DATA, options); + espeak_SetSynthCallback(espeak_callback); + const char *lang = getenv("FUZZ_VOICE"); + if (lang == NULL) + { + fprintf(stderr, "\n" BOLDRED("[Please set up FUZZ_VOICE env var before starting fuzzer]") "\n\n"); + exit(1); + } + if (espeak_SetVoiceByName(lang) != EE_OK) + { + fprintf(stderr, "\n" BOLDRED("[Please supply a valid voice in FUZZ_VOICE]") "\n\n"); + exit(1); + } + initialized = 1; + fprintf(stderr, "VOICE FUZZED = %s\n", lang); + } + char *mutable_data = strndup((char *)data, size); + if (!mutable_data) + { + perror("malloc"); + exit(1); + } + unsigned int position = 0, position_type = POS_CHARACTER, end_position = 0 , synth_flags = espeakCHARS_AUTO; + espeak_Synth(mutable_data, buflength, position, position_type, end_position, + synth_flags, NULL, NULL); + free(mutable_data); + + return 0; +} diff --git a/tests/non-executable-files-with-executable-bit.test b/tests/non-executable-files-with-executable-bit.test index 443067c5..d88cab00 100755 --- a/tests/non-executable-files-with-executable-bit.test +++ b/tests/non-executable-files-with-executable-bit.test @@ -8,6 +8,8 @@ find * -executable -type f | \ grep -vE ".*\.sh|tools/emoji" | # Ignore helper scripts \ grep -vE "src/ucd-tools/tools/(.*\.py|mkencodingtable)" | # Ignore ucd-tools helper scripts \ grep -vE "tests/.libs|src/ucd-tools/tests/print(ucd|c)data(_cpp)?" | # Ignore ucd-tools test programs \ + grep -vE "tests/fuzzing/.*\.py" | #Ignore fuzzing python helper script + grep -vE "tests/fuzzing/.*\.sh" | #Ignore fuzzing python helper script tee tests/non-executable-files-with-executable-bit.check > /dev/null if [ -s tests/non-executable-files-with-executable-bit.check ] ; then From 1da9ad10e80f2e2365c4c00b532fe908b4b8fe19 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sat, 2 Jul 2022 01:04:21 +0200 Subject: [PATCH 47/50] Add tertiary translator TranslateWord2 passes translator2 as tr to TranslateWord which may call TranslateWord3, SpeakIndividualLetters, TranslateLetter, which was calling SetTranslator2 again, thus freeing the very tr being used. Make that latter use another translator. --- src/libespeak-ng/numbers.c | 26 ++++++++++++------------ src/libespeak-ng/translate.c | 38 ++++++++++++++++++++++++------------ src/libespeak-ng/translate.h | 2 ++ 3 files changed, 40 insertions(+), 26 deletions(-) diff --git a/src/libespeak-ng/numbers.c b/src/libespeak-ng/numbers.c index 5a627ca7..04f95913 100644 --- a/src/libespeak-ng/numbers.c +++ b/src/libespeak-ng/numbers.c @@ -500,8 +500,8 @@ void LookupLetter(Translator *tr, unsigned int letter, int next_byte, char *ph_b if (tr->translator_name == L('e', 'n')) return; // we are already using English - SetTranslator2(ESPEAKNG_DEFAULT_VOICE); - if (Lookup(translator2, &single_letter[2], ph_buf3) != 0) { + SetTranslator3(ESPEAKNG_DEFAULT_VOICE); + if (Lookup(translator3, &single_letter[2], ph_buf3) != 0) { // yes, switch to English and re-translate the word sprintf(ph_buf1, "%c", phonSWITCH); } @@ -719,8 +719,8 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control, ALP // don't say "superscript" during normal text reading Lookup(tr, modifier, capital); if (capital[0] == 0) { - capital[2] = SetTranslator2(ESPEAKNG_DEFAULT_VOICE); // overwrites previous contents of translator2 - Lookup(translator2, modifier, &capital[3]); + capital[2] = SetTranslator3(ESPEAKNG_DEFAULT_VOICE); // overwrites previous contents of translator3 + Lookup(translator3, modifier, &capital[3]); if (capital[3] != 0) { capital[0] = phonPAUSE; capital[1] = phonSWITCH; @@ -763,8 +763,8 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control, ALP ph_buf2[0] = 0; if (Lookup(translator, alphabet->name, ph_alphabet) == 0) { // the original language for the current voice // Can't find the local name for this alphabet, use the English name - ph_alphabet[2] = SetTranslator2(ESPEAKNG_DEFAULT_VOICE); // overwrites previous contents of translator2 - Lookup(translator2, alphabet->name, ph_buf2); + ph_alphabet[2] = SetTranslator3(ESPEAKNG_DEFAULT_VOICE); // overwrites previous contents of translator3 + Lookup(translator3, alphabet->name, ph_buf2); } else if (translator != tr) { phontab_1 = tr->phoneme_tab_ix; strcpy(ph_buf2, ph_alphabet); @@ -801,9 +801,9 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control, ALP char hangul_buf[12]; // speak in the language for this alphabet (or English) - ph_buf[2] = SetTranslator2(WordToString2(language)); + ph_buf[2] = SetTranslator3(WordToString2(language)); - if (translator2 != NULL) { + if (translator3 != NULL) { if (((code = letter - 0xac00) >= 0) && (letter <= 0xd7af)) { // Special case for Korean letters. // break a syllable hangul into 2 or 3 individual jamo @@ -818,15 +818,15 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control, ALP p3[6] = ' '; p3[7] = 0; ph_buf[3] = 0; - TranslateRules(translator2, &hangul_buf[1], &ph_buf[3], sizeof(ph_buf)-3, NULL, 0, NULL); - SetWordStress(translator2, &ph_buf[3], NULL, -1, 0); + TranslateRules(translator3, &hangul_buf[1], &ph_buf[3], sizeof(ph_buf)-3, NULL, 0, NULL); + SetWordStress(translator3, &ph_buf[3], NULL, -1, 0); } else - LookupLetter(translator2, letter, word[n_bytes], &ph_buf[3], control & 1); + LookupLetter(translator3, letter, word[n_bytes], &ph_buf[3], control & 1); if (ph_buf[3] == phonSWITCH) { // another level of language change - ph_buf[2] = SetTranslator2(&ph_buf[4]); - LookupLetter(translator2, letter, word[n_bytes], &ph_buf[3], control & 1); + ph_buf[2] = SetTranslator3(&ph_buf[4]); + LookupLetter(translator3, letter, word[n_bytes], &ph_buf[3], control & 1); } SelectPhonemeTable(voice->phoneme_tab_ix); // revert to original phoneme table diff --git a/src/libespeak-ng/translate.c b/src/libespeak-ng/translate.c index 33bf5425..19f95051 100644 --- a/src/libespeak-ng/translate.c +++ b/src/libespeak-ng/translate.c @@ -47,6 +47,8 @@ Translator *translator = NULL; // the main translator Translator *translator2 = NULL; // secondary translator for certain words static char translator2_language[20] = { 0 }; +Translator *translator3 = NULL; // tertiary translator for certain words +static char translator3_language[20] = { 0 }; FILE *f_trans = NULL; // phoneme output text int option_tone_flags = 0; // bit 8=emphasize allcaps, bit 9=emphasize penultimate stress @@ -1206,35 +1208,45 @@ static void Word_EmbeddedCmd() } while (((embedded_cmd & 0x80) == 0) && (embedded_read < embedded_ix)); } -int SetTranslator2(const char *new_language) +static int SetAlternateTranslator(const char *new_language, Translator **translator, char translator_language[20]) { - // Set translator2 to a second language + // Set alternate translator to a second language int new_phoneme_tab; if ((new_phoneme_tab = SelectPhonemeTableName(new_language)) >= 0) { - if ((translator2 != NULL) && (strcmp(new_language, translator2_language) != 0)) { + if ((*translator != NULL) && (strcmp(new_language, translator_language) != 0)) { // we already have an alternative translator, but not for the required language, delete it - DeleteTranslator(translator2); - translator2 = NULL; + DeleteTranslator(*translator); + *translator = NULL; } - if (translator2 == NULL) { - translator2 = SelectTranslator(new_language); - strcpy(translator2_language, new_language); + if (*translator == NULL) { + *translator = SelectTranslator(new_language); + strcpy(translator_language, new_language); - if (LoadDictionary(translator2, translator2->dictionary_name, 0) != 0) { + if (LoadDictionary(*translator, (*translator)->dictionary_name, 0) != 0) { SelectPhonemeTable(voice->phoneme_tab_ix); // revert to original phoneme table new_phoneme_tab = -1; - translator2_language[0] = 0; + translator_language[0] = 0; } - translator2->phoneme_tab_ix = new_phoneme_tab; + (*translator)->phoneme_tab_ix = new_phoneme_tab; } } - if (translator2 != NULL) - translator2->phonemes_repeat[0] = 0; + if (*translator != NULL) + (*translator)->phonemes_repeat[0] = 0; return new_phoneme_tab; } +int SetTranslator2(const char *new_language) +{ + return SetAlternateTranslator(new_language, &translator2, translator2_language); +} + +int SetTranslator3(const char *new_language) +{ + return SetAlternateTranslator(new_language, &translator3, translator3_language); +} + static int TranslateWord2(Translator *tr, char *word, WORD_TAB *wtab, int pre_pause) { int flags = 0; diff --git a/src/libespeak-ng/translate.h b/src/libespeak-ng/translate.h index 7af96608..0be35ce5 100644 --- a/src/libespeak-ng/translate.h +++ b/src/libespeak-ng/translate.h @@ -649,6 +649,7 @@ extern wchar_t option_punctlist[N_PUNCTLIST]; // which punctuation characters t extern Translator *translator; extern Translator *translator2; +extern Translator *translator3; extern char dictionary_name[40]; extern espeak_ng_TEXT_DECODER *p_decoder; extern int dictionary_skipwords; @@ -679,6 +680,7 @@ ALPHABET *AlphabetFromChar(int c); Translator *SelectTranslator(const char *name); int SetTranslator2(const char *name); +int SetTranslator3(const char *name); void DeleteTranslator(Translator *tr); void ProcessLanguageOptions(LANGUAGE_OPTIONS *langopts); From f60a27a7cd16486eec5fe2e5207184d1060c0f5c Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sat, 2 Jul 2022 01:56:25 +0200 Subject: [PATCH 48/50] Do not overflow ph_buf With emojis, phoneme strings can be very long --- src/libespeak-ng/dictionary.c | 6 ++++-- src/libespeak-ng/translate.h | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/libespeak-ng/dictionary.c b/src/libespeak-ng/dictionary.c index c7c6cf89..4cd87ded 100644 --- a/src/libespeak-ng/dictionary.c +++ b/src/libespeak-ng/dictionary.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -2228,7 +2229,7 @@ int TranslateRules(Translator *tr, char *p_start, char *phonemes, int ph_size, c int dict_flags0 = 0; MatchRecord match1; MatchRecord match2; - char ph_buf[40]; + char ph_buf[N_PHONEME_BYTES]; char word_copy[N_WORD_BYTES]; static const char str_pause[2] = { phonPAUSE_NOLINK, 0 }; @@ -2660,8 +2661,9 @@ static const char *LookupDict2(Translator *tr, const char *word, const char *wor phonetic[0] = 0; phoneme_len = 0; } else { - strcpy(phonetic, p); phoneme_len = strlen(p); + assert(phoneme_len < N_PHONEME_BYTES); + strcpy(phonetic, p); p += (phoneme_len + 1); } diff --git a/src/libespeak-ng/translate.h b/src/libespeak-ng/translate.h index 0be35ce5..dfa5e118 100644 --- a/src/libespeak-ng/translate.h +++ b/src/libespeak-ng/translate.h @@ -39,6 +39,7 @@ extern "C" #define N_WORD_PHONEMES 200 // max phonemes in a word #define N_WORD_BYTES 160 // max bytes for the UTF8 characters in a word +#define N_PHONEME_BYTES 160 // max bytes for a phoneme #define N_CLAUSE_WORDS 300 // max words in a clause #define N_TR_SOURCE 800 // the source text of a single clause (UTF8 bytes) From 0fa9737a002cc9c99330f32b650e8804241e7436 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sat, 2 Jul 2022 02:06:58 +0200 Subject: [PATCH 49/50] CI: run 64bit before 32bit So developers get the 64bit results first --- .github/workflows/ci.yml | 4 ++-- .github/workflows/fuzzing.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b1425976..8e349b16 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: strategy: fail-fast: false matrix: - arch: [x86-32, x86-64] + arch: [x86-64, x86-32] sanitizer: [no, address, leak, memory, thread, undefined, valgrind] include: @@ -119,7 +119,7 @@ jobs: strategy: fail-fast: false matrix: - arch: [x86-32, x86-64] + arch: [x86-64, x86-32] include: - arch: x86-32 diff --git a/.github/workflows/fuzzing.yml b/.github/workflows/fuzzing.yml index 287d598b..c4cfd424 100644 --- a/.github/workflows/fuzzing.yml +++ b/.github/workflows/fuzzing.yml @@ -13,7 +13,7 @@ jobs: strategy: fail-fast: false matrix: - arch: [x86-32, x86-64] + arch: [x86-64, x86-32] lang: [af, am, an, ar, as, az, ba, be, bg, bn, bpy, bs, ca, chr, cmn, cs, cv, cy, da, de, el, en, eo, es, et, eu, fa, fi, fr, ga, gd, gn, grc, gu, hak, haw, he, hi, hr, ht, hu, hy, ia, id, io, is, it, ja, jbo, ka, kk, kl, kn, ko, kok, ku, ky, la, lb, lfn, lt, lv, mi, mk, ml, mr, ms, mt, my, nci, ne, nl, no, nog, om, or, pa, pap, piqd, pl, pt, py, qdb, qu, quc, qya, ro, ru, sd, shn, si, sjn, sk, sl, smj, sq, sr, sv, sw, ta, te, th, tk, tn, tr, tt, ug, uk, ur, uz, vi, yue] include: - arch: x86-32 From 482ee1da05189252c3dee49514506e1d2271a2c0 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sat, 2 Jul 2022 02:43:23 +0200 Subject: [PATCH 50/50] Add missing check for EOF --- src/libespeak-ng/readclause.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libespeak-ng/readclause.c b/src/libespeak-ng/readclause.c index 902eecb7..c126f4f4 100644 --- a/src/libespeak-ng/readclause.c +++ b/src/libespeak-ng/readclause.c @@ -680,7 +680,8 @@ int ReadClause(Translator *tr, char *buf, short *charix, int *charix_top, int n_ option_punctuation = 2; } } - c2 = GetC(); + if (!Eof()) + c2 = GetC(); continue; } }