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