Browse Source

Merge branch 'espeak-ng:master' into master

master
MH 3 years ago
parent
commit
0d037db6dd
No account linked to committer's email address
50 changed files with 1254 additions and 184 deletions
  1. 10
    10
      .github/workflows/ci.yml
  2. 64
    0
      .github/workflows/fuzzing.yml
  3. 10
    1
      .gitignore
  4. 11
    0
      CHANGELOG.md
  5. 19
    0
      Makefile.am
  6. 1
    1
      android/build.gradle
  7. 34
    5
      configure.ac
  8. 11
    20
      dictsource/ba_list
  9. 5
    5
      dictsource/be_list
  10. 5
    0
      dictsource/en_list
  11. 1
    1
      dictsource/es_list
  12. 22
    7
      dictsource/he_list
  13. 4
    1
      dictsource/he_listx
  14. 47
    10
      dictsource/he_rules
  15. 14
    5
      dictsource/it_list
  16. 2
    0
      dictsource/it_listx
  17. 13
    3
      dictsource/kl_list
  18. 214
    0
      dictsource/mto_list
  19. 107
    0
      dictsource/mto_rules
  20. 11
    11
      dictsource/quc_list
  21. 1
    1
      espeak-ng-data/lang/art/qdb
  22. 8
    0
      espeak-ng-data/lang/miz/mto
  23. 216
    0
      phsource/ph_mixe_mto
  24. 5
    1
      phsource/ph_romanian
  25. 5
    0
      phsource/phonemes
  26. 3
    3
      src/espeak-ng.c
  27. 1
    1
      src/libespeak-ng/compiledata.c
  28. 6
    4
      src/libespeak-ng/compiledict.c
  29. 18
    12
      src/libespeak-ng/dictionary.c
  30. 2
    2
      src/libespeak-ng/intonation.c
  31. 8
    8
      src/libespeak-ng/klatt.c
  32. 16
    16
      src/libespeak-ng/numbers.c
  33. 5
    1
      src/libespeak-ng/phonemelist.c
  34. 15
    8
      src/libespeak-ng/readclause.c
  35. 1
    1
      src/libespeak-ng/speech.h
  36. 22
    19
      src/libespeak-ng/ssml.c
  37. 2
    0
      src/libespeak-ng/synth_mbrola.c
  38. 3
    1
      src/libespeak-ng/synthdata.c
  39. 6
    1
      src/libespeak-ng/synthesize.c
  40. 2
    2
      src/libespeak-ng/tr_languages.c
  41. 29
    14
      src/libespeak-ng/translate.c
  42. 3
    0
      src/libespeak-ng/translate.h
  43. 20
    5
      src/libespeak-ng/voices.c
  44. 2
    2
      src/libespeak-ng/wavegen.c
  45. 61
    0
      tests/fuzzing/README.md
  46. 68
    0
      tests/fuzzing/create_dict_corpus_file.py
  47. 36
    0
      tests/fuzzing/minimize-corpus.sh
  48. 80
    0
      tests/fuzzing/synth_fuzzer.c
  49. 1
    0
      tests/language-phonemes.test
  50. 4
    2
      tests/non-executable-files-with-executable-bit.test

+ 10
- 10
.github/workflows/ci.yml View File

@@ -16,27 +16,27 @@ 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:
- 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: ''
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" '
@@ -119,7 +119,7 @@ jobs:
strategy:
fail-fast: false
matrix:
arch: [x86-32, x86-64]
arch: [x86-64, x86-32]

include:
- arch: x86-32
@@ -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:


+ 64
- 0
.github/workflows/fuzzing.yml View File

@@ -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-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
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-*

+ 10
- 1
.gitignore View File

@@ -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

+ 11
- 0
CHANGELOG.md View File

@@ -10,9 +10,20 @@ 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
* fa (Persian) -- MH
* he (Hebrew) -- Omer I.S
* it (Italian) -- Christian Leo Mameli
* ro (Romanian) -- Andiv06
* be (Belarusian) -- Andiv06
* en (English) -- Bill Dengler
* es (Spanish) -- Sukil Etxenike
* kl (Greenlandic) -- Andiv06
* qdb (Lang Belta) -- Andiv06
* quc (K'iche') -- Andiv06

### 1.51


+ 19
- 0
Makefile.am View File

@@ -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
@@ -488,6 +503,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 +766,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


+ 1
- 1
android/build.gradle View File

@@ -70,7 +70,7 @@ android {
defaultConfig {
minSdkVersion 14
targetSdkVersion 26
versionCode 20
versionCode 22
versionName "1.52-dev"
}


+ 34
- 5
configure.ac View File

@@ -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 ================================================================
@@ -79,13 +83,13 @@ dnl gradle checks.
dnl ================================================================

AC_MSG_CHECKING([for gradle])
if test -e ${GRADLE} ; then
AC_MSG_RESULT([${GRADLE}])
AM_CONDITIONAL(HAVE_GRADLE, [test 1 = 1])
if command -v "$GRADLE" >/dev/null; then
AC_MSG_RESULT([$GRADLE])
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)

@@ -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.

+ 11
- 20
dictsource/ba_list View File

@@ -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

+ 5
- 5
dictsource/be_list View File

@@ -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

+ 5
- 0
dictsource/en_list View File

@@ -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
@@ -2295,6 +2296,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

@@ -3034,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
@@ -3258,6 +3261,7 @@ saliva s@laIv@
salmon sam@n
?3 salon $alt3
saloon $alt3
sammamish s@'m'amIS
san ,san $only
sanguine $alt2
santoor $alt3
@@ -3403,6 +3407,7 @@ slough slVf $verb
slugabed slVg@bEd
snafu snafu:
snafus snafu:z
snohomish snoU'hoUmIS
snooker snu:k3
sociopath soUsI@paT
sofa soUf@

+ 1
- 1
dictsource/es_list View File

@@ -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

+ 22
- 7
dictsource/he_list View File

@@ -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

+ 4
- 1
dictsource/he_listx View File

@@ -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

+ 47
- 10
dictsource/he_rules View File

@@ -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

+ 14
- 5
dictsource/it_list View File

@@ -1,6 +1,6 @@

// This file is UTF-8 encoded
// Updated 2021 December 22 by Christian Leo M, <llajta2012@gmail.com>
// Updated 2022 april 30 by Christian Leo Mameli, <llajta2012ATgmail.com>

// $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

+ 2
- 0
dictsource/it_listx View File

@@ -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

+ 13
- 3
dictsource/kl_list View File

@@ -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

+ 214
- 0
dictsource/mto_list View File

@@ -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

+ 107
- 0
dictsource/mto_rules View File

@@ -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

+ 11
- 11
dictsource/quc_list View File

@@ -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

+ 1
- 1
espeak-ng-data/lang/art/qdb View File

@@ -1,4 +1,4 @@
name Lang_Belta
name Lang Belta
language qdb

numbers 4 3

+ 8
- 0
espeak-ng-data/lang/miz/mto View File

@@ -0,0 +1,8 @@
name Totontepec Mixe
language mto

maintainer Bill Dengler <[email protected]> and Elizabeth Resendiz <[email protected]>
status testing

lowercaseSentence
tunes s6 c6 q6 e6

+ 216
- 0
phsource/ph_mixe_mto View File

@@ -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

+ 5
- 1
phsource/ph_romanian View File

@@ -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



+ 5
- 0
phsource/phonemes View File

@@ -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

@@ -2058,3 +2061,5 @@ include ph_langbelta

phonemetable be ru
include ph_belarusian

phonemetable ms id

+ 3
- 3
src/espeak-ng.c View File

@@ -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 },

+ 1
- 1
src/libespeak-ng/compiledata.c View File

@@ -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);

+ 6
- 4
src/libespeak-ng/compiledict.c View File

@@ -223,14 +223,16 @@ char *DecodeRule(const char *group_chars, int group_length, char *rule, int cont
char suffix[20];
static char output[80];

static char symbols[] = {
MAKE_MEM_UNDEFINED(&output, sizeof(output));

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 +768,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;

+ 18
- 12
src/libespeak-ng/dictionary.c View File

@@ -26,6 +26,7 @@
#include <string.h>
#include <wctype.h>
#include <wchar.h>
#include <assert.h>

#include <espeak-ng/espeak_ng.h>
#include <espeak-ng/speak_lib.h>
@@ -1060,7 +1061,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 +1227,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) {
@@ -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);
}

@@ -2875,6 +2877,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;

@@ -3008,12 +3012,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;
}
@@ -3052,11 +3058,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

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

@@ -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;

+ 8
- 8
src/libespeak-ng/klatt.c View File

@@ -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;


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

@@ -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];

@@ -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);
}
@@ -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;
@@ -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
@@ -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;

+ 5
- 1
src/libespeak-ng/phonemelist.c View File

@@ -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];

@@ -461,7 +463,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()
@@ -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);
}

+ 15
- 8
src/libespeak-ng/readclause.c View File

@@ -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;
@@ -335,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();
}
@@ -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))
@@ -647,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;
@@ -657,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;
@@ -665,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++] = ' ';
@@ -674,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;
}
}
@@ -791,7 +798,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 = ' ';
@@ -808,7 +815,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;
}

+ 1
- 1
src/libespeak-ng/speech.h View File

@@ -35,7 +35,7 @@
# include <valgrind/memcheck.h>
# 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


+ 22
- 19
src/libespeak-ng/ssml.c View File

@@ -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;
@@ -275,13 +278,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 +318,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 +387,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 +485,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;
@@ -528,7 +531,7 @@ static void SetProsodyParameter(int param_type, wchar_t *attr1, PARAM_STACK *sp,
{ 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
};

@@ -564,9 +567,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 +584,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. <voice />
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;
@@ -645,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"
};

@@ -711,13 +714,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 +858,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

+ 2
- 0
src/libespeak-ng/synth_mbrola.c View File

@@ -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];


+ 3
- 1
src/libespeak-ng/synthdata.c View File

@@ -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;
@@ -428,7 +430,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;

+ 6
- 1
src/libespeak-ng/synthesize.c View File

@@ -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];
}

@@ -553,7 +558,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
};

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

@@ -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, // â

+ 29
- 14
src/libespeak-ng/translate.c View File

@@ -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
@@ -342,7 +344,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;
@@ -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;
@@ -1574,6 +1586,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;
@@ -1988,6 +2001,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;

+ 3
- 0
src/libespeak-ng/translate.h View File

@@ -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)

@@ -649,6 +650,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 +681,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);


+ 20
- 5
src/libespeak-ng/voices.c View File

@@ -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;
@@ -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);
@@ -959,6 +965,9 @@ voice_t *LoadVoice(const char *vname, int control)
return NULL; // no dictionary loaded
}
}

/* Terminate languages list with a zero-priority entry */
voice_languages[langix] = 0;
}

return voice;
@@ -973,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)
@@ -1310,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));

@@ -1320,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;
@@ -1510,7 +1525,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));

@@ -1547,7 +1562,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));


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

@@ -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;


+ 61
- 0
tests/fuzzing/README.md View File

@@ -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
```

+ 68
- 0
tests/fuzzing/create_dict_corpus_file.py View File

@@ -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: <http://www.gnu.org/licenses/>.
# */
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 <corpus_dir>', 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)

+ 36
- 0
tests/fuzzing/minimize-corpus.sh View File

@@ -0,0 +1,36 @@
#!/bin/bash

if [[ $# -lt 1 ]]
then
echo "Usage: $0 <corpus-dir>"
echo "Usage: $0 --preserve-txt <corpus-dir> (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 !"

+ 80
- 0
tests/fuzzing/synth_fuzzer.c View File

@@ -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:
* <http://www.gnu.org/licenses/>.
*/

#include "config.h"

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <libgen.h>
#include <time.h>

#include <espeak-ng/espeak_ng.h>
#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;
}

+ 1
- 0
tests/language-phonemes.test View File

@@ -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@"

+ 4
- 2
tests/non-executable-files-with-executable-bit.test View File

@@ -4,10 +4,12 @@ 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 \
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

Loading…
Cancel
Save