1 /***************************************************************************
2 * Copyright 1991, 1992, 1993, 1994, 1995, 1996, 2001, 2002 *
3 * David R. Hill, Leonard Manzara, Craig Schock *
4 * *
5 * This program is free software: you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation, either version 3 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
18 // 2014-09
19 // This file was copied from Gnuspeech and modified by Marcelo Y. Matuda.
20
21 #include "en/letter_to_sound/word_to_patphone.h"
22
23 #include <array>
24 #include <string.h>
25
26 #include "en/letter_to_sound/vowel_before.h"
27 #include "en/letter_to_sound/check_word_list.h"
28 #include "en/letter_to_sound/final_s.h"
29 #include "en/letter_to_sound/ie_to_y.h"
30 #include "en/letter_to_sound/mark_final_e.h"
31 #include "en/letter_to_sound/long_medial_vowels.h"
32 #include "en/letter_to_sound/medial_silent_e.h"
33 #include "en/letter_to_sound/medial_s.h"
34 #include "en/number_pronunciations.h"
35
36
37
38 /* LOCAL DEFINES ***********************************************************/
39 #define SPELL_STRING_LEN 8192
40
41
42
43 namespace {
44
45 int spell_it(char* word);
46 int all_caps(char* in);
47
48
49
50 const char* letters[] = {
51 BLANK, EXCLAMATION_POINT, DOUBLE_QUOTE, NUMBER_SIGN, DOLLAR_SIGN,
52 PERCENT_SIGN, AMPERSAND, SINGLE_QUOTE, OPEN_PARENTHESIS, CLOSE_PARENTHESIS,
53 ASTERISK, PLUS_SIGN, COMMA, HYPHEN, PERIOD, SLASH,
54 ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE,
55 COLON, SEMICOLON, OPEN_ANGLE_BRACKET, EQUAL_SIGN, CLOSE_ANGLE_BRACKET,
56 QUESTION_MARK, AT_SIGN,
57 A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
58 OPEN_SQUARE_BRACKET, BACKSLASH, CLOSE_SQUARE_BRACKET, CARET, UNDERSCORE,
59 GRAVE_ACCENT,
60 A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
61 OPEN_BRACE, VERTICAL_BAR, CLOSE_BRACE, TILDE, UNKNOWN
62 };
63
64
65
66 /******************************************************************************
67 *
68 * function: spell_it
69 *
70 * purpose:
71 *
72 *
73 * arguments: word
74 *
75 * internal
76 * functions: none
77 *
78 * library
79 * functions: strcpy
80 *
81 ******************************************************************************/
82 int
spell_it(char * word)83 spell_it(char* word)
84 {
85 std::array<char, SPELL_STRING_LEN> spell_string;
86 spell_string.fill(0);
87
88 char* s = &spell_string[0];
89 const char* t;
90 char* hold = word;
91
92 /* EAT THE '#' */
93 word++;
94
95 do {
96 if (*word < ' ') {
97 if (*word == '\t') {
98 t = "'t_aa_b";
99 } else {
100 t = "'u_p_s"; /* (OOPS!) */
101 }
102 } else {
103 t = letters[*word - ' '];
104 }
105 word++;
106 while (*t) {
107 *s++ = *t++;
108 }
109 } while (*word != '#');
110
111 *s = 0;
112
113 strcpy(hold, &spell_string[0]);
114 return 2;
115 }
116
117 /******************************************************************************
118 *
119 * function: all_caps
120 *
121 * purpose:
122 *
123 *
124 * arguments: in
125 *
126 * internal
127 * functions: none
128 *
129 * library
130 * functions: none
131 *
132 ******************************************************************************/
133 int
all_caps(char * in)134 all_caps(char *in)
135 {
136 int all_up = 1;
137 int force_up = 0;
138
139 in++;
140 if (*in == '#')
141 force_up = 1;
142
143 while (*in != '#') {
144 if ((*in <= 'z') && (*in >= 'a'))
145 all_up = 0;
146 else if ((*in <= 'Z') && (*in >= 'A'))
147 *in |= 0x20;
148 else if (*in != '\'')
149 force_up = 1;
150 in++;
151 }
152 return (all_up || force_up);
153 }
154
155 } /* namespace */
156
157 //==============================================================================
158
159 namespace GS {
160 namespace En {
161
162 /******************************************************************************
163 *
164 * function: word_to_patphone
165 *
166 * purpose:
167 *
168 *
169 * arguments: word
170 *
171 * internal
172 * functions: all_caps, spell_it, vowel_before, check_word_list,
173 * final_s, ie_to_y, mark_final_e, long_medial_vowels,
174 * medial_silent_e, medial_s
175 *
176 * library
177 * functions: none
178 *
179 ******************************************************************************/
180 int
word_to_patphone(char * word)181 word_to_patphone(char *word)
182 {
183 char *end_of_word;
184 register char replace_s = 0;
185
186
187 /* FIND END OF WORD */
188 end_of_word = word + 1;
189 while (*end_of_word != '#')
190 end_of_word++;
191
192 /* IF NO LITTLE LETTERS SPELL THE WORD */
193 if (all_caps(word))
194 return(spell_it(word));
195
196 /* IF SINGLE LETTER, SPELL IT */
197 if (end_of_word == (word + 2))
198 return(spell_it(word));
199
200 /* IF NO VOWELS SPELL THE WORD */
201 if (!vowel_before(word, end_of_word))
202 return(spell_it(word));
203
204 /* SEE IF IT IS IN THE EXCEPTION LIST */
205 if (check_word_list(word, &end_of_word)) {
206 *++end_of_word = 0;
207 return(1);
208 }
209
210 /* KILL ANY TRAILING S */
211 replace_s = final_s(word, &end_of_word);
212
213 /* FLIP IE TO Y, IF ANY CHANGES RECHECK WORD LIST */
214 if (ie_to_y(word, &end_of_word) || replace_s)
215 /* IN WORD LIST NOW ALL DONE */
216 if (check_word_list(word, &end_of_word)) { /* Will eliminate this as well */
217 if (replace_s) {
218 *++end_of_word = replace_s; /* & 0x5f [source of problems] */
219 *++end_of_word = '/';
220 }
221 *++end_of_word = 0;
222 return(1);
223 }
224
225 mark_final_e(word, &end_of_word);
226 long_medial_vowels(word, &end_of_word);
227 medial_silent_e(word, &end_of_word);
228 medial_s(word, &end_of_word);
229
230 if (replace_s) {
231 *end_of_word++ = replace_s;
232 *end_of_word = '#';
233 }
234 *++end_of_word = 0;
235 return(0);
236 }
237
238 } /* namespace En */
239 } /* namespace GS */
240