871b899eeac5cd2d12b113114a19733e26442409
[asterisk/asterisk.git] / main / say.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  * George Konstantoulakis <gkon@inaccessnetworks.com>
8  *
9  * See http://www.asterisk.org for more information about
10  * the Asterisk project. Please do not directly contact
11  * any of the maintainers of this project for assistance;
12  * the project provides a web site, mailing lists and IRC
13  * channels for your use.
14  *
15  * This program is free software, distributed under the terms of
16  * the GNU General Public License Version 2. See the LICENSE file
17  * at the top of the source tree.
18  */
19
20 /*! \file
21  *
22  * \brief Say numbers and dates (maybe words one day too)
23  *
24  * \author Mark Spencer <markster@digium.com>
25  * 
26  * \note 12-16-2004 : Support for Greek added by InAccess Networks (work funded by HOL, www.hol.gr) George Konstantoulakis <gkon@inaccessnetworks.com>
27  *                                              
28  * \note 2007-02-08 : Support for Georgian added by Alexander Shaduri <ashaduri@gmail.com>,
29  *                                              Next Generation Networks (NGN).
30  * \note 2007-03-20 : Support for Thai added by Dome C. <dome@tel.co.th>,
31  *                                              IP Crossing Co., Ltd.
32  */
33
34 #include "asterisk.h"
35
36 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
37
38 #include <netinet/in.h>
39 #include <time.h>
40 #include <ctype.h>
41 #include <math.h>
42
43 #ifdef SOLARIS
44 #include <iso/limits_iso.h>
45 #endif
46
47 #include "asterisk/file.h"
48 #include "asterisk/channel.h"
49 #include "asterisk/say.h"
50 #include "asterisk/lock.h"
51 #include "asterisk/localtime.h"
52 #include "asterisk/utils.h"
53 #include "asterisk/app.h"
54
55 /* Forward declaration */
56 static int wait_file(struct ast_channel *chan, const char *ints, const char *file, const char *lang);
57
58
59 static int say_character_str_full(struct ast_channel *chan, const char *str, const char *ints, const char *lang, int audiofd, int ctrlfd)
60 {
61         const char *fn;
62         char fnbuf[10], asciibuf[20] = "letters/ascii";
63         char ltr;
64         int num = 0;
65         int res = 0;
66
67         while (str[num] && !res) {
68                 fn = NULL;
69                 switch (str[num]) {
70                 case ('*'):
71                         fn = "digits/star";
72                         break;
73                 case ('#'):
74                         fn = "digits/pound";
75                         break;
76                 case ('!'):
77                         fn = "letters/exclaimation-point";
78                         break;
79                 case ('@'):
80                         fn = "letters/at";
81                         break;
82                 case ('$'):
83                         fn = "letters/dollar";
84                         break;
85                 case ('-'):
86                         fn = "letters/dash";
87                         break;
88                 case ('.'):
89                         fn = "letters/dot";
90                         break;
91                 case ('='):
92                         fn = "letters/equals";
93                         break;
94                 case ('+'):
95                         fn = "letters/plus";
96                         break;
97                 case ('/'):
98                         fn = "letters/slash";
99                         break;
100                 case (' '):
101                         fn = "letters/space";
102                         break;
103                 case ('0'):
104                 case ('1'):
105                 case ('2'):
106                 case ('3'):
107                 case ('4'):
108                 case ('5'):
109                 case ('6'):
110                 case ('7'):
111                 case ('8'):
112                 case ('9'):
113                         strcpy(fnbuf, "digits/X");
114                         fnbuf[7] = str[num];
115                         fn = fnbuf;
116                         break;
117                 default:
118                         ltr = str[num];
119                         if ('A' <= ltr && ltr <= 'Z') ltr += 'a' - 'A';         /* file names are all lower-case */
120                         strcpy(fnbuf, "letters/X");
121                         fnbuf[8] = ltr;
122                         fn = fnbuf;
123                 }
124                 if ((fn && ast_fileexists(fn, NULL, lang) > 0) ||
125                         (snprintf(asciibuf + 13, sizeof(asciibuf) - 13, "%d", str[num]) > 0 && ast_fileexists(asciibuf, NULL, lang) > 0 && (fn = asciibuf))) {
126                         res = ast_streamfile(chan, fn, lang);
127                         if (!res) {
128                                 if ((audiofd  > -1) && (ctrlfd > -1))
129                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
130                                 else
131                                         res = ast_waitstream(chan, ints);
132                         }
133                         ast_stopstream(chan);
134                 }
135                 num++;
136         }
137
138         return res;
139 }
140
141 static int say_phonetic_str_full(struct ast_channel *chan, const char *str, const char *ints, const char *lang, int audiofd, int ctrlfd)
142 {
143         const char *fn;
144         char fnbuf[256];
145         char ltr;
146         int num = 0;
147         int res = 0;
148
149         while (str[num] && !res) {
150                 fn = NULL;
151                 switch (str[num]) {
152                 case ('*'):
153                         fn = "digits/star";
154                         break;
155                 case ('#'):
156                         fn = "digits/pound";
157                         break;
158                 case ('!'):
159                         fn = "letters/exclaimation-point";
160                         break;
161                 case ('@'):
162                         fn = "letters/at";
163                         break;
164                 case ('$'):
165                         fn = "letters/dollar";
166                         break;
167                 case ('-'):
168                         fn = "letters/dash";
169                         break;
170                 case ('.'):
171                         fn = "letters/dot";
172                         break;
173                 case ('='):
174                         fn = "letters/equals";
175                         break;
176                 case ('+'):
177                         fn = "letters/plus";
178                         break;
179                 case ('/'):
180                         fn = "letters/slash";
181                         break;
182                 case (' '):
183                         fn = "letters/space";
184                         break;
185                 case ('0'):
186                 case ('1'):
187                 case ('2'):
188                 case ('3'):
189                 case ('4'):
190                 case ('5'):
191                 case ('6'):
192                 case ('7'):
193                 case ('8'):
194                         strcpy(fnbuf, "digits/X");
195                         fnbuf[7] = str[num];
196                         fn = fnbuf;
197                         break;
198                 default:        /* '9' falls here... */
199                         ltr = str[num];
200                         if ('A' <= ltr && ltr <= 'Z') ltr += 'a' - 'A';         /* file names are all lower-case */
201                         strcpy(fnbuf, "phonetic/X_p");
202                         fnbuf[9] = ltr;
203                         fn = fnbuf;
204                 }
205                 if (fn && ast_fileexists(fn, NULL, lang) > 0) {
206                         res = ast_streamfile(chan, fn, lang);
207                         if (!res) {
208                                 if ((audiofd  > -1) && (ctrlfd > -1))
209                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
210                                 else
211                                         res = ast_waitstream(chan, ints);
212                         }
213                         ast_stopstream(chan);
214                 }
215                 num++;
216         }
217
218         return res;
219 }
220
221 static int say_digit_str_full(struct ast_channel *chan, const char *str, const char *ints, const char *lang, int audiofd, int ctrlfd)
222 {
223         const char *fn;
224         char fnbuf[256];
225         int num = 0;
226         int res = 0;
227
228         while (str[num] && !res) {
229                 fn = NULL;
230                 switch (str[num]) {
231                 case ('*'):
232                         fn = "digits/star";
233                         break;
234                 case ('#'):
235                         fn = "digits/pound";
236                         break;
237                 case ('-'):
238                         fn = "digits/minus";
239                         break;
240                 case '0':
241                 case '1':
242                 case '2':
243                 case '3':
244                 case '4':
245                 case '5':
246                 case '6':
247                 case '7':
248                 case '8':
249                 case '9':
250                         strcpy(fnbuf, "digits/X");
251                         fnbuf[7] = str[num];
252                         fn = fnbuf;
253                         break;
254                 }
255                 if (fn && ast_fileexists(fn, NULL, lang) > 0) {
256                         res = ast_streamfile(chan, fn, lang);
257                         if (!res) {
258                                 if ((audiofd  > -1) && (ctrlfd > -1))
259                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
260                                 else
261                                         res = ast_waitstream(chan, ints);
262                         }
263                         ast_stopstream(chan);
264                 }
265                 num++;
266         }
267
268         return res;
269 }
270
271 /* Forward declarations */
272 /*! \page Def_syntaxlang Asterisk Language Syntaxes supported
273     \note Not really language codes.
274         For these language codes, Asterisk will change the syntax when
275         saying numbers (and in some cases dates and voicemail messages
276         as well)
277       \arg \b da    - Danish
278       \arg \b de    - German
279       \arg \b en    - English (US)
280       \arg \b en_GB - English (British)
281       \arg \b es    - Spanish, Mexican
282       \arg \b fr    - French
283       \arg \b he    - Hebrew
284       \arg \b it    - Italian
285       \arg \b nl    - Dutch
286       \arg \b no    - Norwegian
287       \arg \b pl    - Polish       
288       \arg \b pt    - Portuguese
289       \arg \b pt_BR - Portuguese (Brazil)
290       \arg \b se    - Swedish
291       \arg \b zh    - Taiwanese / Chinese
292       \arg \b ru    - Russian
293       \arg \b ka    - Georgian
294       \arg \b hu    - Hungarian
295
296  \par Gender:
297  For Some languages the numbers differ for gender and plural.
298  \arg Use the option argument 'f' for female, 'm' for male and 'n' for neuter in languages like Portuguese, French, Spanish and German.
299  \arg use the option argument 'c' is for commune and 'n' for neuter gender in nordic languages like Danish, Swedish and Norwegian.
300  use the option argument 'p' for plural enumerations like in German
301  
302  Date/Time functions currently have less languages supported than saynumber().
303
304  \todo Note that in future, we need to move to a model where we can differentiate further - e.g. between en_US & en_UK
305
306  See contrib/i18n.testsuite.conf for some examples of the different syntaxes
307
308  \par Portuguese
309  Portuguese sound files needed for Time/Date functions:
310  pt-ah
311  pt-ao
312  pt-de
313  pt-e
314  pt-ora
315  pt-meianoite
316  pt-meiodia
317  pt-sss
318
319  \par Spanish
320  Spanish sound files needed for Time/Date functions:
321  es-de
322  es-el
323
324  \par Italian
325  Italian sound files needed for Time/Date functions:
326  ore-una
327  ore-mezzanotte
328
329 */
330
331 /* Forward declarations of language specific variants of ast_say_number_full */
332 static int ast_say_number_full_en(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
333 static int ast_say_number_full_cs(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
334 static int ast_say_number_full_da(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
335 static int ast_say_number_full_de(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
336 static int ast_say_number_full_en_GB(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
337 static int ast_say_number_full_es(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
338 static int ast_say_number_full_fr(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
339 static int ast_say_number_full_he(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
340 static int ast_say_number_full_it(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
341 static int ast_say_number_full_nl(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
342 static int ast_say_number_full_no(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
343 static int ast_say_number_full_pl(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
344 static int ast_say_number_full_pt(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
345 static int ast_say_number_full_se(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
346 static int ast_say_number_full_zh(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
347 static int ast_say_number_full_gr(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
348 static int ast_say_number_full_ru(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
349 static int ast_say_number_full_ka(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
350 static int ast_say_number_full_hu(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
351 static int ast_say_number_full_th(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
352 static int ast_say_number_full_ur(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
353 static int ast_say_number_full_vi(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
354
355 /* Forward declarations of language specific variants of ast_say_enumeration_full */
356 static int ast_say_enumeration_full_en(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
357 static int ast_say_enumeration_full_da(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
358 static int ast_say_enumeration_full_de(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
359 static int ast_say_enumeration_full_he(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
360 static int ast_say_enumeration_full_vi(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
361
362 /* Forward declarations of ast_say_date, ast_say_datetime and ast_say_time functions */
363 static int ast_say_date_en(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
364 static int ast_say_date_da(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
365 static int ast_say_date_de(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
366 static int ast_say_date_fr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
367 static int ast_say_date_nl(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
368 static int ast_say_date_pt(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
369 static int ast_say_date_gr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
370 static int ast_say_date_ka(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
371 static int ast_say_date_hu(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
372 static int ast_say_date_th(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
373 static int ast_say_date_he(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
374
375 static int ast_say_date_with_format_en(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone);
376 static int ast_say_date_with_format_da(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone);
377 static int ast_say_date_with_format_de(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone);
378 static int ast_say_date_with_format_es(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone);
379 static int ast_say_date_with_format_he(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone);
380 static int ast_say_date_with_format_fr(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone);
381 static int ast_say_date_with_format_it(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone);
382 static int ast_say_date_with_format_nl(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone);
383 static int ast_say_date_with_format_pl(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone);
384 static int ast_say_date_with_format_pt(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone);
385 static int ast_say_date_with_format_zh(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone);
386 static int ast_say_date_with_format_gr(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone);
387 static int ast_say_date_with_format_th(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone);
388 static int ast_say_date_with_format_vi(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone);
389
390 static int ast_say_time_en(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
391 static int ast_say_time_de(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
392 static int ast_say_time_fr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
393 static int ast_say_time_nl(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
394 static int ast_say_time_pt(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
395 static int ast_say_time_pt_BR(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
396 static int ast_say_time_zh(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
397 static int ast_say_time_gr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
398 static int ast_say_time_ka(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
399 static int ast_say_time_hu(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
400 static int ast_say_time_th(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
401 static int ast_say_time_he(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
402
403 static int ast_say_datetime_en(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
404 static int ast_say_datetime_de(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
405 static int ast_say_datetime_fr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
406 static int ast_say_datetime_nl(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
407 static int ast_say_datetime_pt(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
408 static int ast_say_datetime_pt_BR(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
409 static int ast_say_datetime_zh(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
410 static int ast_say_datetime_gr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
411 static int ast_say_datetime_ka(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
412 static int ast_say_datetime_hu(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
413 static int ast_say_datetime_th(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
414 static int ast_say_datetime_he(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
415
416 static int ast_say_datetime_from_now_en(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
417 static int ast_say_datetime_from_now_fr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
418 static int ast_say_datetime_from_now_pt(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
419 static int ast_say_datetime_from_now_ka(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
420 static int ast_say_datetime_from_now_he(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
421
422 static int wait_file(struct ast_channel *chan, const char *ints, const char *file, const char *lang) 
423 {
424         int res;
425         if ((res = ast_streamfile(chan, file, lang)))
426                 ast_log(LOG_WARNING, "Unable to play message %s\n", file);
427         if (!res)
428                 res = ast_waitstream(chan, ints);
429         return res;
430 }
431
432 /*! \brief  ast_say_number_full: call language-specific functions 
433      \note Called from AGI */
434 static int say_number_full(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
435 {
436         if (!strncasecmp(language, "en_GB", 5)) {     /* British syntax */
437            return ast_say_number_full_en_GB(chan, num, ints, language, audiofd, ctrlfd);
438         } else if (!strncasecmp(language, "en", 2)) { /* English syntax */
439            return ast_say_number_full_en(chan, num, ints, language, audiofd, ctrlfd);
440         } else if (!strncasecmp(language, "cs", 2)) { /* Czech syntax */
441            return ast_say_number_full_cs(chan, num, ints, language, options, audiofd, ctrlfd);
442         } else if (!strncasecmp(language, "cz", 2)) { /* deprecated Czech syntax */
443                 static int deprecation_warning = 0;
444                 if (deprecation_warning++ % 10 == 0) {
445                         ast_log(LOG_WARNING, "cz is not a standard language code.  Please switch to using cs instead.\n");
446                 }
447                 return ast_say_number_full_cs(chan, num, ints, language, options, audiofd, ctrlfd);
448         } else if (!strncasecmp(language, "da", 2)) { /* Danish syntax */
449            return ast_say_number_full_da(chan, num, ints, language, options, audiofd, ctrlfd);
450         } else if (!strncasecmp(language, "de", 2)) { /* German syntax */
451            return ast_say_number_full_de(chan, num, ints, language, options, audiofd, ctrlfd);
452         } else if (!strncasecmp(language, "es", 2)) { /* Spanish syntax */
453            return ast_say_number_full_es(chan, num, ints, language, options, audiofd, ctrlfd);
454         } else if (!strncasecmp(language, "fr", 2)) { /* French syntax */
455            return ast_say_number_full_fr(chan, num, ints, language, options, audiofd, ctrlfd);
456         } else if (!strncasecmp(language, "ge", 2)) { /* deprecated Georgian syntax */
457                 static int deprecation_warning = 0;
458                 if (deprecation_warning++ % 10 == 0) {
459                         ast_log(LOG_WARNING, "ge is not a standard language code.  Please switch to using ka instead.\n");
460                 }
461                 return ast_say_number_full_ka(chan, num, ints, language, options, audiofd, ctrlfd);
462         } else if (!strncasecmp(language, "gr", 2)) { /* Greek syntax */
463            return ast_say_number_full_gr(chan, num, ints, language, audiofd, ctrlfd);
464         } else if (!strncasecmp(language, "he", 2)) { /* Hebrew syntax */
465            return ast_say_number_full_he(chan, num, ints, language, options, audiofd, ctrlfd);
466         } else if (!strncasecmp(language, "hu", 2)) { /* Hungarian syntax */
467                 return ast_say_number_full_hu(chan, num, ints, language, audiofd, ctrlfd);
468         } else if (!strncasecmp(language, "it", 2)) { /* Italian syntax */
469            return ast_say_number_full_it(chan, num, ints, language, audiofd, ctrlfd);
470         } else if (!strncasecmp(language, "ka", 2)) { /* Georgian syntax */
471            return ast_say_number_full_ka(chan, num, ints, language, options, audiofd, ctrlfd);
472         } else if (!strncasecmp(language, "mx", 2)) { /* deprecated Mexican syntax */
473                 static int deprecation_warning = 0;
474                 if (deprecation_warning++ % 10 == 0) {
475                         ast_log(LOG_WARNING, "mx is not a standard language code.  Please switch to using es_MX instead.\n");
476                 }
477                 return ast_say_number_full_es(chan, num, ints, language, options, audiofd, ctrlfd);
478         } else if (!strncasecmp(language, "nl", 2)) { /* Dutch syntax */
479            return ast_say_number_full_nl(chan, num, ints, language, audiofd, ctrlfd);
480         } else if (!strncasecmp(language, "no", 2)) { /* Norwegian syntax */
481            return ast_say_number_full_no(chan, num, ints, language, options, audiofd, ctrlfd);
482         } else if (!strncasecmp(language, "pl", 2)) { /* Polish syntax */
483            return ast_say_number_full_pl(chan, num, ints, language, options, audiofd, ctrlfd);
484         } else if (!strncasecmp(language, "pt", 2)) { /* Portuguese syntax */
485            return ast_say_number_full_pt(chan, num, ints, language, options, audiofd, ctrlfd);
486         } else if (!strncasecmp(language, "ru", 2)) { /* Russian syntax */
487            return ast_say_number_full_ru(chan, num, ints, language, options, audiofd, ctrlfd);
488         } else if (!strncasecmp(language, "se", 2)) { /* Swedish syntax */
489            return ast_say_number_full_se(chan, num, ints, language, options, audiofd, ctrlfd);
490         } else if (!strncasecmp(language, "th", 2)) { /* Thai syntax */
491                 return ast_say_number_full_th(chan, num, ints, language, audiofd, ctrlfd);
492         } else if (!strncasecmp(language, "tw", 2)) { /* deprecated Taiwanese syntax */
493                 static int deprecation_warning = 0;
494                 if (deprecation_warning++ % 10 == 0) {
495                         ast_log(LOG_WARNING, "tw is a standard language code for Twi, not Taiwanese.  Please switch to using zh_TW instead.\n");
496                 }
497                 return ast_say_number_full_zh(chan, num, ints, language, audiofd, ctrlfd);
498         } else if (!strncasecmp(language, "zh", 2)) { /* Taiwanese / Chinese syntax */
499            return ast_say_number_full_zh(chan, num, ints, language, audiofd, ctrlfd);
500         } else if (!strncasecmp(language, "ur", 2)) { /* Urdu syntax */
501                 return ast_say_number_full_ur(chan, num, ints, language, options, audiofd, ctrlfd);
502         } else if (!strncasecmp(language, "vi", 2)) { /* Vietnamese syntax */
503                 return ast_say_number_full_vi(chan, num, ints, language, audiofd, ctrlfd);
504         }
505
506         /* Default to english */
507         return ast_say_number_full_en(chan, num, ints, language, audiofd, ctrlfd);
508 }
509
510 /*! \brief  ast_say_number_full_en: English syntax 
511         \note This is the default syntax, if no other syntax defined in this file is used */
512 static int ast_say_number_full_en(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
513 {
514         int res = 0;
515         int playh = 0;
516         char fn[256] = "";
517         if (!num) 
518                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
519
520         while (!res && (num || playh)) {
521                 if (num < 0) {
522                         ast_copy_string(fn, "digits/minus", sizeof(fn));
523                         if ( num > INT_MIN ) {
524                                 num = -num;
525                         } else {
526                                 num = 0;
527                         }       
528                 } else if (playh) {
529                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
530                         playh = 0;
531                 } else  if (num < 20) {
532                         snprintf(fn, sizeof(fn), "digits/%d", num);
533                         num = 0;
534                 } else  if (num < 100) {
535                         snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
536                         num %= 10;
537                 } else {
538                         if (num < 1000){
539                                 snprintf(fn, sizeof(fn), "digits/%d", (num/100));
540                                 playh++;
541                                 num %= 100;
542                         } else {
543                                 if (num < 1000000) { /* 1,000,000 */
544                                         res = ast_say_number_full_en(chan, num / 1000, ints, language, audiofd, ctrlfd);
545                                         if (res)
546                                                 return res;
547                                         num %= 1000;
548                                         snprintf(fn, sizeof(fn), "digits/thousand");
549                                 } else {
550                                         if (num < 1000000000) { /* 1,000,000,000 */
551                                                 res = ast_say_number_full_en(chan, num / 1000000, ints, language, audiofd, ctrlfd);
552                                                 if (res)
553                                                         return res;
554                                                 num %= 1000000;
555                                                 ast_copy_string(fn, "digits/million", sizeof(fn));
556                                         } else {
557                                                 ast_debug(1, "Number '%d' is too big for me\n", num);
558                                                 res = -1;
559                                         }
560                                 }
561                         }
562                 }
563                 if (!res) {
564                         if (!ast_streamfile(chan, fn, language)) {
565                                 if ((audiofd  > -1) && (ctrlfd > -1))
566                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
567                                 else
568                                         res = ast_waitstream(chan, ints);
569                         }
570                         ast_stopstream(chan);
571                 }
572         }
573         return res;
574 }
575
576 static int exp10_int(int power)
577 {
578         int x, res= 1;
579         for (x=0;x<power;x++)
580                 res *= 10;
581         return res;
582 }
583
584 /*! \brief  ast_say_number_full_cs: Czech syntax 
585  *
586  * files needed:
587  * - 1m,2m - gender male
588  * - 1w,2w - gender female
589  * - 3,4,...,20
590  * - 30,40,...,90
591  * 
592  * - hundereds - 100 - sto, 200 - 2ste, 300,400 3,4sta, 500,600,...,900 5,6,...9set 
593  * 
594  * for each number 10^(3n + 3) exist 3 files represented as:
595  *              1 tousand = jeden tisic = 1_E3
596  *              2,3,4 tousands = dva,tri,ctyri tisice = 2-3_E3
597  *              5,6,... tousands = pet,sest,... tisic = 5_E3
598  *
599  *              million = _E6
600  *              miliard = _E9
601  *              etc...
602  *
603  * tousand, milion are  gender male, so 1 and 2 is 1m 2m
604  * miliard is gender female, so 1 and 2 is 1w 2w
605  */
606 static int ast_say_number_full_cs(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
607 {
608         int res = 0;
609         int playh = 0;
610         char fn[256] = "";
611         
612         int hundered = 0;
613         int left = 0;
614         int length = 0;
615         
616         /* options - w = woman, m = man, n = neutral. Defaultl is woman */
617         if (!options)
618                 options = "w";
619         
620         if (!num) 
621                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
622         
623         while (!res && (num || playh)) {
624                 if (num < 0) {
625                         ast_copy_string(fn, "digits/minus", sizeof(fn));
626                         if ( num > INT_MIN ) {
627                                 num = -num;
628                         } else {
629                                 num = 0;
630                         }       
631                 } else if (num < 3 ) {
632                         snprintf(fn, sizeof(fn), "digits/%d%c", num, options[0]);
633                         playh = 0;
634                         num = 0;
635                 } else if (num < 20) {
636                         snprintf(fn, sizeof(fn), "digits/%d", num);
637                         playh = 0;
638                         num = 0;
639                 } else if (num < 100) {
640                         snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
641                         num %= 10;
642                 } else if (num < 1000) {
643                         hundered = num / 100;
644                         if ( hundered == 1 ) {
645                                 ast_copy_string(fn, "digits/1sto", sizeof(fn));
646                         } else if ( hundered == 2 ) {
647                                 ast_copy_string(fn, "digits/2ste", sizeof(fn));
648                         } else {
649                                 res = ast_say_number_full_cs(chan, hundered, ints, language, options, audiofd, ctrlfd);
650                                 if (res)
651                                         return res;
652                                 if (hundered == 3 || hundered == 4) {   
653                                         ast_copy_string(fn, "digits/sta", sizeof(fn));
654                                 } else if ( hundered > 4 ) {
655                                         ast_copy_string(fn, "digits/set", sizeof(fn));
656                                 }
657                         }
658                         num -= (hundered * 100);
659                 } else { /* num > 1000 */
660                         length = (int)log10(num)+1;  
661                         while ( (length % 3 ) != 1 ) {
662                                 length--;               
663                         }
664                         left = num / (exp10_int(length-1));
665                         if ( left == 2 ) {  
666                                 switch (length-1) {
667                                         case 9: options = "w";  /* 1,000,000,000 gender female */
668                                                 break;
669                                         default : options = "m"; /* others are male */
670                                 }
671                         }
672                         if ( left > 1 ) { /* we don't say "one thousand" but only thousand */
673                                 res = ast_say_number_full_cs(chan, left, ints, language, options, audiofd, ctrlfd);
674                                 if (res) 
675                                         return res;
676                         }
677                         if ( left >= 5 ) { /* >= 5 have the same declesion */
678                                 snprintf(fn, sizeof(fn), "digits/5_E%d", length - 1);   
679                         } else if ( left >= 2 && left <= 4 ) {
680                                 snprintf(fn, sizeof(fn), "digits/2-4_E%d", length - 1);
681                         } else { /* left == 1 */
682                                 snprintf(fn, sizeof(fn), "digits/1_E%d", length - 1);
683                         }
684                         num -= left * (exp10_int(length-1));
685                 }
686                 if (!res) {
687                         if (!ast_streamfile(chan, fn, language)) {
688                                 if ((audiofd > -1) && (ctrlfd > -1)) {
689                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
690                                 } else {
691                                         res = ast_waitstream(chan, ints);
692                                 }
693                         }
694                         ast_stopstream(chan);
695                 }
696         }
697         return res; 
698 }
699
700 /*! \brief  ast_say_number_full_da: Danish syntax
701  New files:
702  - In addition to English, the following sounds are required: "1N", "millions", "and" and "1-and" through "9-and" 
703  */
704 static int ast_say_number_full_da(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
705 {
706         int res = 0;
707         int playh = 0;
708         int playa = 0;
709         int cn = 1;             /* +1 = commune; -1 = neuter */
710         char fn[256] = "";
711         if (!num) 
712                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
713
714         if (options && !strncasecmp(options, "n", 1)) cn = -1;
715
716         while (!res && (num || playh || playa )) {
717                 /* The grammar for Danish numbers is the same as for English except
718                 * for the following:
719                 * - 1 exists in both commune ("en", file "1N") and neuter ("et", file "1")
720                 * - numbers 20 through 99 are said in reverse order, i.e. 21 is
721                 *   "one-and twenty" and 68 is "eight-and sixty".
722                 * - "million" is different in singular and plural form
723                 * - numbers > 1000 with zero as the third digit from last have an
724                 *   "and" before the last two digits, i.e. 2034 is "two thousand and
725                 *   four-and thirty" and 1000012 is "one million and twelve".
726                 */
727                 if (num < 0) {
728                         ast_copy_string(fn, "digits/minus", sizeof(fn));
729                         if ( num > INT_MIN ) {
730                                 num = -num;
731                         } else {
732                                 num = 0;
733                         }       
734                 } else if (playh) {
735                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
736                         playh = 0;
737                 } else if (playa) {
738                         ast_copy_string(fn, "digits/and", sizeof(fn));
739                         playa = 0;
740                 } else if (num == 1 && cn == -1) {
741                         ast_copy_string(fn, "digits/1N", sizeof(fn));
742                         num = 0;
743                 } else if (num < 20) {
744                         snprintf(fn, sizeof(fn), "digits/%d", num);
745                         num = 0;
746                 } else if (num < 100) {
747                         int ones = num % 10;
748                         if (ones) {
749                                 snprintf(fn, sizeof(fn), "digits/%d-and", ones);
750                                 num -= ones;
751                         } else {
752                                 snprintf(fn, sizeof(fn), "digits/%d", num);
753                                 num = 0;
754                         }
755                 } else {
756                         if (num < 1000) {
757                                 int hundreds = num / 100;
758                                 if (hundreds == 1)
759                                         ast_copy_string(fn, "digits/1N", sizeof(fn));
760                                 else
761                                         snprintf(fn, sizeof(fn), "digits/%d", (num / 100));
762
763                                 playh++;
764                                 num -= 100 * hundreds;
765                                 if (num)
766                                         playa++;
767
768                         } else {
769                                 if (num < 1000000) {
770                                         res = ast_say_number_full_da(chan, num / 1000, ints, language, "n", audiofd, ctrlfd);
771                                         if (res)
772                                                 return res;
773                                         num = num % 1000;
774                                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
775                                 } else {
776                                         if (num < 1000000000) {
777                                                 int millions = num / 1000000;
778                                                 res = ast_say_number_full_da(chan, millions, ints, language, "c", audiofd, ctrlfd);
779                                                 if (res)
780                                                         return res;
781                                                 if (millions == 1)
782                                                         ast_copy_string(fn, "digits/million", sizeof(fn));
783                                                 else
784                                                         ast_copy_string(fn, "digits/millions", sizeof(fn));
785                                                 num = num % 1000000;
786                                         } else {
787                                                 ast_debug(1, "Number '%d' is too big for me\n", num);
788                                                 res = -1;
789                                         }
790                                 }
791                                 if (num && num < 100)
792                                         playa++;
793                         }
794                 }
795                 if (!res) {
796                         if (!ast_streamfile(chan, fn, language)) {
797                                 if ((audiofd > -1) && (ctrlfd > -1))
798                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
799                                 else
800                                         res = ast_waitstream(chan, ints);
801                         }
802                         ast_stopstream(chan);
803                 }
804         }
805         return res;
806 }
807
808 /*! \brief  ast_say_number_full_de: German syntax 
809  
810  New files:
811  In addition to English, the following sounds are required:
812  - "millions"
813  - "1-and" through "9-and" 
814  - "1F" (eine)
815  - "1N" (ein)
816  - NB "1" is recorded as 'eins'
817  */
818 static int ast_say_number_full_de(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
819 {
820         int res = 0, t = 0;
821         int mf = 1;                            /* +1 = male and neuter; -1 = female */
822         char fn[256] = "";
823         char fna[256] = "";
824         if (!num) 
825                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
826
827         if (options && (!strncasecmp(options, "f", 1)))
828                 mf = -1;
829
830         while (!res && num) {
831                 /* The grammar for German numbers is the same as for English except
832                 * for the following:
833                 * - numbers 20 through 99 are said in reverse order, i.e. 21 is
834                 *   "one-and twenty" and 68 is "eight-and sixty".
835                 * - "one" varies according to gender
836                 * - 100 is 'hundert', however all other instances are 'ein hundert'
837                 * - 1000 is 'tausend', however all other instances are 'ein tausend'
838                 * - 1000000 is always 'eine million'
839                 * - "million" is different in singular and plural form
840                 */
841                 if (num < 0) {
842                         ast_copy_string(fn, "digits/minus", sizeof(fn));
843                         if ( num > INT_MIN ) {
844                                 num = -num;
845                         } else {
846                                 num = 0;
847                         }       
848                 } else if (num < 100 && t) {
849                         ast_copy_string(fn, "digits/and", sizeof(fn));
850                         t = 0;
851                 } else if (num == 1 && mf == -1) {
852                         snprintf(fn, sizeof(fn), "digits/%dF", num);
853                         num = 0;
854                 } else if (num < 20) {
855                         snprintf(fn, sizeof(fn), "digits/%d", num);
856                         num = 0;
857                 } else if (num < 100) {
858                         int ones = num % 10;
859                         if (ones) {
860                                 snprintf(fn, sizeof(fn), "digits/%d-and", ones);
861                                 num -= ones;
862                         } else {
863                                 snprintf(fn, sizeof(fn), "digits/%d", num);
864                                 num = 0;
865                         }
866                 } else if (num == 100 && t == 0) {
867                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
868                         num = 0;
869                 } else if (num < 1000) {
870                         int hundreds = num / 100;
871                         num = num % 100;
872                         if (hundreds == 1) {
873                                 ast_copy_string(fn, "digits/1N", sizeof(fn));
874                         } else {
875                                 snprintf(fn, sizeof(fn), "digits/%d", hundreds);
876                         }
877                         ast_copy_string(fna, "digits/hundred", sizeof(fna));
878                         t = 1;
879                 } else if (num == 1000 && t == 0) {
880                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
881                         num = 0;
882                 } else  if (num < 1000000) {
883                         int thousands = num / 1000;
884                         num = num % 1000;
885                         t = 1;
886                         if (thousands == 1) {
887                                 ast_copy_string(fn, "digits/1N", sizeof(fn));
888                                 ast_copy_string(fna, "digits/thousand", sizeof(fna));
889                         } else {
890                                 res = ast_say_number_full_de(chan, thousands, ints, language, options, audiofd, ctrlfd);
891                                 if (res)
892                                         return res;
893                                 ast_copy_string(fn, "digits/thousand", sizeof(fn));
894                         }
895                 } else if (num < 1000000000) {
896                         int millions = num / 1000000;
897                         num = num % 1000000;
898                         t = 1;
899                         if (millions == 1) {
900                                 ast_copy_string(fn, "digits/1F", sizeof(fn));
901                                 ast_copy_string(fna, "digits/million", sizeof(fna));
902                         } else {
903                                 res = ast_say_number_full_de(chan, millions, ints, language, options, audiofd, ctrlfd);
904                                 if (res)
905                                         return res;
906                                 ast_copy_string(fn, "digits/millions", sizeof(fn));
907                         }
908                 } else if (num <= INT_MAX) {
909                         int billions = num / 1000000000;
910                         num = num % 1000000000;
911                         t = 1;
912                         if (billions == 1) {
913                                 ast_copy_string(fn, "digits/1F", sizeof(fn));
914                                 ast_copy_string(fna, "digits/milliard", sizeof(fna));
915                         } else {
916                                 res = ast_say_number_full_de(chan, billions, ints, language, options, audiofd, ctrlfd);
917                                 if (res) {
918                                         return res;
919                                 }
920                                 ast_copy_string(fn, "digits/milliards", sizeof(fn));
921                         }
922                 } else {
923                         ast_debug(1, "Number '%d' is too big for me\n", num);
924                         res = -1;
925                 }
926                 if (!res) {
927                         if (!ast_streamfile(chan, fn, language)) {
928                                 if ((audiofd > -1) && (ctrlfd > -1))
929                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
930                                 else
931                                         res = ast_waitstream(chan, ints);
932                         }
933                         ast_stopstream(chan);
934                         if (!res) {
935                                 if (strlen(fna) != 0 && !ast_streamfile(chan, fna, language)) {
936                                         if ((audiofd > -1) && (ctrlfd > -1))
937                                                 res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
938                                         else
939                                                 res = ast_waitstream(chan, ints);
940                                 }
941                                 ast_stopstream(chan);
942                                 strcpy(fna, "");
943                         }
944                 }
945         }
946         return res;
947 }
948
949 /*! \brief  ast_say_number_full_en_GB: British syntax 
950  New files:
951   - In addition to American English, the following sounds are required:  "and"
952  */
953 static int ast_say_number_full_en_GB(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
954 {
955         int res = 0;
956         int playh = 0;
957         int playa = 0;
958         char fn[256] = "";
959         if (!num) 
960                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
961
962         while (!res && (num || playh || playa )) {
963                 if (num < 0) {
964                         ast_copy_string(fn, "digits/minus", sizeof(fn));
965                         if ( num > INT_MIN ) {
966                                 num = -num;
967                         } else {
968                                 num = 0;
969                         }       
970                 } else if (playh) {
971                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
972                         playh = 0;
973                 } else if (playa) {
974                         ast_copy_string(fn, "digits/and", sizeof(fn));
975                         playa = 0;
976                 } else if (num < 20) {
977                         snprintf(fn, sizeof(fn), "digits/%d", num);
978                         num = 0;
979                 } else if (num < 100) {
980                         snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
981                         num %= 10;
982                 } else if (num < 1000) {
983                         int hundreds = num / 100;
984                         snprintf(fn, sizeof(fn), "digits/%d", (num / 100));
985
986                         playh++;
987                         num -= 100 * hundreds;
988                         if (num)
989                                 playa++;
990                 } else if (num < 1000000) {
991                         res = ast_say_number_full_en_GB(chan, num / 1000, ints, language, audiofd, ctrlfd);
992                         if (res)
993                                 return res;
994                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
995                         num %= 1000;
996                         if (num && num < 100)
997                                 playa++;
998                 } else if (num < 1000000000) {
999                                 int millions = num / 1000000;
1000                                 res = ast_say_number_full_en_GB(chan, millions, ints, language, audiofd, ctrlfd);
1001                                 if (res)
1002                                         return res;
1003                                 ast_copy_string(fn, "digits/million", sizeof(fn));
1004                                 num %= 1000000;
1005                                 if (num && num < 100)
1006                                         playa++;
1007                 } else {
1008                                 ast_debug(1, "Number '%d' is too big for me\n", num);
1009                                 res = -1;
1010                 }
1011
1012                 if (!res) {
1013                         if (!ast_streamfile(chan, fn, language)) {
1014                                 if ((audiofd > -1) && (ctrlfd > -1))
1015                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
1016                                 else
1017                                         res = ast_waitstream(chan, ints);
1018                         }
1019                         ast_stopstream(chan);
1020                 }
1021         }
1022         return res;
1023 }
1024
1025 /*! \brief  ast_say_number_full_es: Spanish syntax 
1026
1027  New files:
1028  Requires a few new audios:
1029    1F.gsm: feminine 'una'
1030    21.gsm thru 29.gsm, cien.gsm, mil.gsm, millon.gsm, millones.gsm, 100.gsm, 200.gsm, 300.gsm, 400.gsm, 500.gsm, 600.gsm, 700.gsm, 800.gsm, 900.gsm, y.gsm 
1031  */
1032 static int ast_say_number_full_es(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
1033 {
1034         int res = 0;
1035         int playa = 0;
1036         int mf = 0;                            /* +1 = male; -1 = female */
1037         char fn[256] = "";
1038         if (!num) 
1039                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
1040
1041         if (options) {
1042                 if (!strncasecmp(options, "f", 1))
1043                         mf = -1;
1044                 else if (!strncasecmp(options, "m", 1))
1045                         mf = 1;
1046         }
1047
1048         while (!res && num) {
1049                 if (num < 0) {
1050                         ast_copy_string(fn, "digits/minus", sizeof(fn));
1051                         if ( num > INT_MIN ) {
1052                                 num = -num;
1053                         } else {
1054                                 num = 0;
1055                         }       
1056                 } else if (playa) {
1057                         ast_copy_string(fn, "digits/and", sizeof(fn));
1058                         playa = 0;
1059                 } else if (num == 1) {
1060                         if (mf < 0)
1061                                 snprintf(fn, sizeof(fn), "digits/%dF", num);
1062                         else if (mf > 0)
1063                                 snprintf(fn, sizeof(fn), "digits/%dM", num);
1064                         else 
1065                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1066                         num = 0;
1067                 } else if (num < 31) {
1068                         snprintf(fn, sizeof(fn), "digits/%d", num);
1069                         num = 0;
1070                 } else if (num < 100) {
1071                         snprintf(fn, sizeof(fn), "digits/%d", (num/10)*10);
1072                         num %= 10;
1073                         if (num)
1074                                 playa++;
1075                 } else if (num == 100) {
1076                         ast_copy_string(fn, "digits/100", sizeof(fn));
1077                         num = 0;
1078                 } else if (num < 200) {
1079                         ast_copy_string(fn, "digits/100-and", sizeof(fn));
1080                         num -= 100;
1081                 } else {
1082                         if (num < 1000) {
1083                                 snprintf(fn, sizeof(fn), "digits/%d", (num/100)*100);
1084                                 num %= 100;
1085                         } else if (num < 2000) {
1086                                 num %= 1000;
1087                                 ast_copy_string(fn, "digits/thousand", sizeof(fn));
1088                         } else {
1089                                 if (num < 1000000) {
1090                                         res = ast_say_number_full_es(chan, num / 1000, ints, language, options, audiofd, ctrlfd);
1091                                         if (res)
1092                                                 return res;
1093                                         num %= 1000;
1094                                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
1095                                 } else {
1096                                         if (num < 2147483640) {
1097                                                 if ((num/1000000) == 1) {
1098                                                         res = ast_say_number_full_es(chan, num / 1000000, ints, language, "M", audiofd, ctrlfd);
1099                                                         if (res)
1100                                                                 return res;
1101                                                         ast_copy_string(fn, "digits/million", sizeof(fn));
1102                                                 } else {
1103                                                         res = ast_say_number_full_es(chan, num / 1000000, ints, language, options, audiofd, ctrlfd);
1104                                                         if (res)
1105                                                                 return res;
1106                                                         ast_copy_string(fn, "digits/millions", sizeof(fn));
1107                                                 }
1108                                                 num %= 1000000;
1109                                         } else {
1110                                                 ast_debug(1, "Number '%d' is too big for me\n", num);
1111                                                 res = -1;
1112                                         }
1113                                 }
1114                         }
1115                 }
1116
1117                 if (!res) {
1118                         if (!ast_streamfile(chan, fn, language)) {
1119                                 if ((audiofd > -1) && (ctrlfd > -1))
1120                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
1121                                 else
1122                                         res = ast_waitstream(chan, ints);
1123                         }
1124                         ast_stopstream(chan);
1125
1126                 }
1127
1128         }
1129         return res;
1130 }
1131
1132 /*! \brief  ast_say_number_full_fr: French syntax
1133         Extra sounds needed:
1134         1F: feminin 'une'
1135         et: 'and' */
1136 static int ast_say_number_full_fr(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
1137 {
1138         int res = 0;
1139         int playh = 0;
1140         int playa = 0;
1141         int mf = 1;                            /* +1 = male; -1 = female */
1142         char fn[256] = "";
1143         if (!num) 
1144                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
1145         
1146         if (options && !strncasecmp(options, "f", 1))
1147                 mf = -1;
1148
1149         while (!res && (num || playh || playa)) {
1150                 if (num < 0) {
1151                         ast_copy_string(fn, "digits/minus", sizeof(fn));
1152                         if ( num > INT_MIN ) {
1153                                 num = -num;
1154                         } else {
1155                                 num = 0;
1156                         }       
1157                 } else if (playh) {
1158                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
1159                         playh = 0;
1160                 } else if (playa) {
1161                         ast_copy_string(fn, "digits/et", sizeof(fn));
1162                         playa = 0;
1163                 } else if (num == 1) {
1164                         if (mf < 0)
1165                                 snprintf(fn, sizeof(fn), "digits/%dF", num);
1166                         else
1167                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1168                         num = 0;
1169                 } else if (num < 21) {
1170                         snprintf(fn, sizeof(fn), "digits/%d", num);
1171                         num = 0;
1172                 } else if (num < 70) {
1173                         snprintf(fn, sizeof(fn), "digits/%d", (num/10)*10);
1174                         if ((num % 10) == 1) playa++;
1175                         num = num % 10;
1176                 } else if (num < 80) {
1177                         ast_copy_string(fn, "digits/60", sizeof(fn));
1178                         if ((num % 10) == 1) playa++;
1179                         num -= 60;
1180                 } else if (num < 100) {
1181                         ast_copy_string(fn, "digits/80", sizeof(fn));
1182                         num = num - 80;
1183                 } else if (num < 200) {
1184                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
1185                         num = num - 100;
1186                 } else if (num < 1000) {
1187                         snprintf(fn, sizeof(fn), "digits/%d", (num/100));
1188                         playh++;
1189                         num = num % 100;
1190                 } else if (num < 2000) {
1191                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
1192                         num = num - 1000;
1193                 } else if (num < 1000000) {
1194                         res = ast_say_number_full_fr(chan, num / 1000, ints, language, options, audiofd, ctrlfd);
1195                         if (res)
1196                                 return res;
1197                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
1198                         num = num % 1000;
1199                 } else  if (num < 1000000000) {
1200                         res = ast_say_number_full_fr(chan, num / 1000000, ints, language, options, audiofd, ctrlfd);
1201                         if (res)
1202                                 return res;
1203                         ast_copy_string(fn, "digits/million", sizeof(fn));
1204                         num = num % 1000000;
1205                 } else {
1206                         ast_debug(1, "Number '%d' is too big for me\n", num);
1207                         res = -1;
1208                 }
1209                 if (!res) {
1210                         if (!ast_streamfile(chan, fn, language)) {
1211                                 if ((audiofd > -1) && (ctrlfd > -1))
1212                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
1213                                 else
1214                                         res = ast_waitstream(chan, ints);
1215                         }
1216                         ast_stopstream(chan);
1217                 }
1218         }
1219         return res;
1220 }
1221
1222
1223
1224 /* Hebrew syntax
1225  * Check doc/lang/hebrew-digits.txt for information about the various
1226  * recordings required to make this translation work properly */
1227 #define SAY_NUM_BUF_SIZE 256
1228 static int ast_say_number_full_he(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
1229 {
1230         int res = 0;
1231         int state = 0;                          /* no need to save anything */
1232         int mf = -1;                            /* +1 = Masculin; -1 = Feminin */
1233         int tmpnum = 0;
1234
1235         char fn[SAY_NUM_BUF_SIZE] = "";
1236
1237         ast_verbose(VERBOSE_PREFIX_3 "ast_say_digits_full: started. num: %d, options=\"%s\"\n", num, options);
1238
1239         if (!num) {
1240                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
1241         }
1242         if (options && !strncasecmp(options, "m", 1)) {
1243                 mf = 1;
1244         }
1245         ast_verbose(VERBOSE_PREFIX_3 "ast_say_digits_full: num: %d, state=%d, options=\"%s\", mf=%d\n", num, state, options, mf);
1246
1247         /* Do we have work to do? */
1248         while (!res && (num || (state > 0))) {
1249                 /* first type of work: play a second sound. In this loop
1250                  * we can only play one sound file at a time. Thus playing
1251                  * a second one requires repeating the loop just for the
1252                  * second file. The variable 'state' remembers where we were.
1253                  * state==0 is the normal mode and it means that we continue
1254                  * to check if the number num has yet anything left.
1255                  */
1256                 ast_verbose(VERBOSE_PREFIX_3 "ast_say_digits_full: num: %d, state=%d, options=\"%s\", mf=%d, tmpnum=%d\n", num, state, options, mf, tmpnum);
1257
1258                 if (state == 1) {
1259                         state = 0;
1260                 } else if (state == 2) {
1261                         if ((num >= 11) && (num < 21)) {
1262                                 if (mf < 0) {
1263                                         snprintf(fn, sizeof(fn), "digits/ve");
1264                                 } else {
1265                                         snprintf(fn, sizeof(fn), "digits/uu");
1266                                 }
1267                         } else {
1268                                 switch (num) {
1269                                 case 1:
1270                                         snprintf(fn, sizeof(fn), "digits/ve");
1271                                         break;
1272                                 case 2:
1273                                         snprintf(fn, sizeof(fn), "digits/uu");
1274                                         break;
1275                                 case 3:
1276                                         if (mf < 0) {
1277                                                 snprintf(fn, sizeof(fn), "digits/ve");
1278                                         } else {
1279                                                 snprintf(fn, sizeof(fn), "digits/uu");
1280                                         }
1281                                         break;
1282                                 case 4:
1283                                         snprintf(fn, sizeof(fn), "digits/ve");
1284                                         break;
1285                                 case 5:
1286                                         snprintf(fn, sizeof(fn), "digits/ve");
1287                                         break;
1288                                 case 6:
1289                                         snprintf(fn, sizeof(fn), "digits/ve");
1290                                         break;
1291                                 case 7:
1292                                         snprintf(fn, sizeof(fn), "digits/ve");
1293                                         break;
1294                                 case 8:
1295                                         snprintf(fn, sizeof(fn), "digits/uu");
1296                                         break;
1297                                 case 9:
1298                                         snprintf(fn, sizeof(fn), "digits/ve");
1299                                         break;
1300                                 case 10:
1301                                         snprintf(fn, sizeof(fn), "digits/ve");
1302                                         break;
1303                                 }
1304                         }
1305                         state = 0;
1306                 } else if (state == 3) {
1307                         snprintf(fn, sizeof(fn), "digits/1k");
1308                         state = 0;
1309                 } else if (num < 0) {
1310                         snprintf(fn, sizeof(fn), "digits/minus");
1311                         num = (-1) * num;
1312                 } else if (num < 20) {
1313                         if (mf < 0) {
1314                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1315                         } else {
1316                                 snprintf(fn, sizeof(fn), "digits/%dm", num);
1317                         }
1318                         num = 0;
1319                 } else if ((num < 100) && (num >= 20)) {
1320                         snprintf(fn, sizeof(fn), "digits/%d", (num / 10) * 10);
1321                         num = num % 10;
1322                         if (num > 0) {
1323                                 state = 2;
1324                         }
1325                 } else if ((num >= 100) && (num < 1000)) {
1326                         tmpnum = num / 100;
1327                         snprintf(fn, sizeof(fn), "digits/%d00", tmpnum);
1328                         num = num - (tmpnum * 100);
1329                         if ((num > 0) && (num < 11)) {
1330                                 state = 2;
1331                         }
1332                 } else if ((num >= 1000) && (num < 10000)) {
1333                         tmpnum = num / 1000;
1334                         snprintf(fn, sizeof(fn), "digits/%dk", tmpnum);
1335                         num = num - (tmpnum * 1000);
1336                         if ((num > 0) && (num < 11)) {
1337                                 state = 2;
1338                         }
1339                 } else if (num < 20000) {
1340                         snprintf(fn, sizeof(fn), "digits/%dm", (num / 1000));
1341                         num = num % 1000;
1342                         state = 3;
1343                 } else if (num < 1000000) {
1344                         res = ast_say_number_full_he(chan, num / 1000, ints, language, "m", audiofd, ctrlfd);
1345                         if (res) {
1346                                 return res;
1347                         }
1348                         snprintf(fn, sizeof(fn), "digits/1k");
1349                         num = num % 1000;
1350                         if ((num > 0) && (num < 11)) {
1351                                 state = 2;
1352                         }
1353                 } else if (num < 2000000) {
1354                         snprintf(fn, sizeof(fn), "digits/million");
1355                         num = num % 1000000;
1356                         if ((num > 0) && (num < 11)) {
1357                                 state = 2;
1358                         }
1359                 } else if (num < 3000000) {
1360                         snprintf(fn, sizeof(fn), "digits/twomillion");
1361                         num = num - 2000000;
1362                         if ((num > 0) && (num < 11)) {
1363                                 state = 2;
1364                         }
1365                 } else if (num < 1000000000) {
1366                         res = ast_say_number_full_he(chan, num / 1000000, ints, language, "m", audiofd, ctrlfd);
1367                         if (res) {
1368                                 return res;
1369                         }
1370                         snprintf(fn, sizeof(fn), "digits/million");
1371                         num = num % 1000000;
1372                         if ((num > 0) && (num < 11)) {
1373                                 state = 2;
1374                         }
1375                 } else {
1376                         ast_debug(1, "Number '%d' is too big for me\n", num);
1377                         res = -1;
1378                 }
1379                 tmpnum = 0;
1380                 if (!res) {
1381                         if (!ast_streamfile(chan, fn, language)) {
1382                                 if ((audiofd > -1) && (ctrlfd > -1)) {
1383                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
1384                                 } else {
1385                                         res = ast_waitstream(chan, ints);
1386                                 }
1387                         }
1388                         ast_stopstream(chan);
1389                 }
1390         }
1391         return res;
1392 }
1393
1394 /*! \brief  ast_say_number_full_hu: Hungarian syntax 
1395
1396   Extra sounds needed:
1397         10en: "tizen"
1398         20on: "huszon"
1399 */
1400 static int ast_say_number_full_hu(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
1401 {
1402         int res = 0;
1403         int playh = 0;
1404         char fn[256] = "";
1405         if (!num) 
1406                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
1407
1408         /*
1409         Hungarian support
1410         like english, except numbers up to 29 are from 2 words.
1411         10 and first word of 1[1-9] and 20 and first word of 2[1-9] are different.
1412         */
1413
1414         while(!res && (num || playh)) {
1415                 if (num < 0) {
1416                         ast_copy_string(fn, "digits/minus", sizeof(fn));
1417                         if ( num > INT_MIN ) {
1418                                 num = -num;
1419                         } else {
1420                                 num = 0;
1421                         }       
1422                 } else if (playh) {
1423                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
1424                         playh = 0;
1425                 } else if (num < 11 || num == 20) {
1426                         snprintf(fn, sizeof(fn), "digits/%d", num);
1427                         num = 0;
1428                 } else if (num < 20) {
1429                         ast_copy_string(fn, "digits/10en", sizeof(fn));
1430                         num -= 10;
1431                 } else if (num < 30) {
1432                         ast_copy_string(fn, "digits/20on", sizeof(fn));
1433                         num -= 20;
1434                 } else  if (num < 100) {
1435                         snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
1436                         num %= 10;
1437                 } else {
1438                         if (num < 1000){
1439                                 snprintf(fn, sizeof(fn), "digits/%d", (num/100));
1440                                 playh++;
1441                                 num %= 100;
1442                         } else {
1443                                 if (num < 1000000) { /* 1,000,000 */
1444                                         res = ast_say_number_full_hu(chan, num / 1000, ints, language, audiofd, ctrlfd);
1445                                         if (res)
1446                                                 return res;
1447                                         num %= 1000;
1448                                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
1449                                 } else {
1450                                         if (num < 1000000000) { /* 1,000,000,000 */
1451                                                 res = ast_say_number_full_hu(chan, num / 1000000, ints, language, audiofd, ctrlfd);
1452                                                 if (res)
1453                                                         return res;
1454                                                 num %= 1000000;
1455                                                 ast_copy_string(fn, "digits/million", sizeof(fn));
1456                                         } else {
1457                                                 ast_debug(1, "Number '%d' is too big for me\n", num);
1458                                                 res = -1;
1459                                         }
1460                                 }
1461                         }
1462                 }
1463                 if (!res) {
1464                         if(!ast_streamfile(chan, fn, language)) {
1465                                 if ((audiofd  > -1) && (ctrlfd > -1))
1466                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
1467                                 else
1468                                         res = ast_waitstream(chan, ints);
1469                         }
1470                         ast_stopstream(chan);
1471                 }
1472         }
1473         return res;
1474 }
1475
1476 /*! \brief  ast_say_number_full_it:  Italian */
1477 static int ast_say_number_full_it(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
1478 {
1479         int res = 0;
1480         int playh = 0;
1481         int tempnum = 0;
1482         char fn[256] = "";
1483
1484         if (!num)
1485                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
1486
1487                 /*
1488                 Italian support
1489
1490                 Like english, numbers up to 20 are a single 'word', and others
1491                 compound, but with exceptions.
1492                 For example 21 is not twenty-one, but there is a single word in 'it'.
1493                 Idem for 28 (ie when a the 2nd part of a compund number
1494                 starts with a vowel)
1495
1496                 There are exceptions also for hundred, thousand and million.
1497                 In english 100 = one hundred, 200 is two hundred.
1498                 In italian 100 = cento , like to say hundred (without one),
1499                 200 and more are like english.
1500                 
1501                 Same applies for thousand:
1502                 1000 is one thousand in en, 2000 is two thousand.
1503                 In it we have 1000 = mille , 2000 = 2 mila 
1504
1505                 For million(s) we use the plural, if more than one
1506                 Also, one million is abbreviated in it, like on-million,
1507                 or 'un milione', not 'uno milione'.
1508                 So the right file is provided.
1509                 */
1510
1511         while (!res && (num || playh)) {
1512                         if (num < 0) {
1513                                 ast_copy_string(fn, "digits/minus", sizeof(fn));
1514                                 if ( num > INT_MIN ) {
1515                                         num = -num;
1516                                 } else {
1517                                         num = 0;
1518                                 }       
1519                         } else if (playh) {
1520                                 ast_copy_string(fn, "digits/hundred", sizeof(fn));
1521                                 playh = 0;
1522                         } else if (num < 20) {
1523                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1524                                 num = 0;
1525                         } else if (num == 21) {
1526                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1527                                 num = 0;
1528                         } else if (num == 28) {
1529                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1530                                 num = 0;
1531                         } else if (num == 31) {
1532                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1533                                 num = 0;
1534                         } else if (num == 38) {
1535                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1536                                 num = 0;
1537                         } else if (num == 41) {
1538                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1539                                 num = 0;
1540                         } else if (num == 48) {
1541                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1542                                 num = 0;
1543                         } else if (num == 51) {
1544                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1545                                 num = 0;
1546                         } else if (num == 58) {
1547                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1548                                 num = 0;
1549                         } else if (num == 61) {
1550                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1551                                 num = 0;
1552                         } else if (num == 68) {
1553                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1554                                 num = 0;
1555                         } else if (num == 71) {
1556                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1557                                 num = 0;
1558                         } else if (num == 78) {
1559                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1560                                 num = 0;
1561                         } else if (num == 81) {
1562                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1563                                 num = 0;
1564                         } else if (num == 88) {
1565                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1566                                 num = 0;
1567                         } else if (num == 91) {
1568                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1569                                 num = 0;
1570                         } else if (num == 98) {
1571                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1572                                 num = 0;
1573                         } else if (num < 100) {
1574                                 snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
1575                                 num %= 10;
1576                         } else {
1577                                 if (num < 1000) {
1578                                         if ((num / 100) > 1) {
1579                                                 snprintf(fn, sizeof(fn), "digits/%d", (num/100));
1580                                                 playh++;
1581                                         } else {
1582                                                 ast_copy_string(fn, "digits/hundred", sizeof(fn));
1583                                         }
1584                                         num %= 100;
1585                                 } else {
1586                                         if (num < 1000000) { /* 1,000,000 */
1587                                                 if ((num/1000) > 1)
1588                                                         res = ast_say_number_full_it(chan, num / 1000, ints, language, audiofd, ctrlfd);
1589                                                 if (res)
1590                                                         return res;
1591                                                 tempnum = num;
1592                                                 num %= 1000;
1593                                                 if ((tempnum / 1000) < 2)
1594                                                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
1595                                                 else /* for 1000 it says mille, for >1000 (eg 2000) says mila */
1596                                                         ast_copy_string(fn, "digits/thousands", sizeof(fn));
1597                                         } else {
1598                                                 if (num < 1000000000) { /* 1,000,000,000 */
1599                                                         if ((num / 1000000) > 1)
1600                                                                 res = ast_say_number_full_it(chan, num / 1000000, ints, language, audiofd, ctrlfd);
1601                                                         if (res)
1602                                                                 return res;
1603                                                         tempnum = num;
1604                                                         num %= 1000000;
1605                                                         if ((tempnum / 1000000) < 2)
1606                                                                 ast_copy_string(fn, "digits/million", sizeof(fn));
1607                                                         else
1608                                                                 ast_copy_string(fn, "digits/millions", sizeof(fn));
1609                                                 } else {
1610                                                         ast_debug(1, "Number '%d' is too big for me\n", num);
1611                                                         res = -1;
1612                                                 }
1613                                         }
1614                                 }
1615                         }
1616                         if (!res) {
1617                                 if (!ast_streamfile(chan, fn, language)) {
1618                                         if ((audiofd > -1) && (ctrlfd > -1))
1619                                                 res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
1620                                         else
1621                                                 res = ast_waitstream(chan, ints);
1622                                 }
1623                                 ast_stopstream(chan);
1624                         }
1625                 }
1626         return res;
1627 }
1628
1629 /*! \brief  ast_say_number_full_nl: dutch syntax 
1630  * New files: digits/nl-en
1631  */
1632 static int ast_say_number_full_nl(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
1633 {
1634         int res = 0;
1635         int playh = 0;
1636         int units = 0;
1637         char fn[256] = "";
1638         if (!num) 
1639                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
1640         while (!res && (num || playh )) {
1641                 if (num < 0) {
1642                         ast_copy_string(fn, "digits/minus", sizeof(fn));
1643                         if ( num > INT_MIN ) {
1644                                 num = -num;
1645                         } else {
1646                                 num = 0;
1647                         }       
1648                 } else if (playh) {
1649                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
1650                         playh = 0;
1651                 } else if (num < 20) {
1652                         snprintf(fn, sizeof(fn), "digits/%d", num);
1653                         num = 0;
1654                 } else if (num < 100) {
1655                         units = num % 10;
1656                         if (units > 0) {
1657                                 res = ast_say_number_full_nl(chan, units, ints, language, audiofd, ctrlfd);
1658                                 if (res)
1659                                         return res;
1660                                 num = num - units;
1661                                 ast_copy_string(fn, "digits/nl-en", sizeof(fn));
1662                         } else {
1663                                 snprintf(fn, sizeof(fn), "digits/%d", num - units);
1664                                 num = 0;
1665                         }
1666                 } else if (num < 200) {
1667                         /* hundred, not one-hundred */
1668                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
1669                         num %= 100;
1670                 } else if (num < 1000) {
1671                         snprintf(fn, sizeof(fn), "digits/%d", num / 100);
1672                         playh++;
1673                         num %= 100;
1674                 } else {
1675                         if (num < 1100) {
1676                                 /* thousand, not one-thousand */
1677                                 num %= 1000;
1678                                 ast_copy_string(fn, "digits/thousand", sizeof(fn));
1679                         } else if (num < 10000) { /* 1,100 to 9,9999 */
1680                                 res = ast_say_number_full_nl(chan, num / 100, ints, language, audiofd, ctrlfd);
1681                                 if (res)
1682                                         return res;
1683                                 num %= 100;
1684                                 ast_copy_string(fn, "digits/hundred", sizeof(fn));
1685                         } else {
1686                                 if (num < 1000000) { /* 1,000,000 */
1687                                         res = ast_say_number_full_nl(chan, num / 1000, ints, language, audiofd, ctrlfd);
1688                                         if (res)
1689                                                 return res;
1690                                         num %= 1000;
1691                                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
1692                                 } else {
1693                                         if (num < 1000000000) { /* 1,000,000,000 */
1694                                                 res = ast_say_number_full_nl(chan, num / 1000000, ints, language, audiofd, ctrlfd);
1695                                                 if (res)
1696                                                         return res;
1697                                                 num %= 1000000;
1698                                                 ast_copy_string(fn, "digits/million", sizeof(fn));
1699                                         } else {
1700                                                 ast_debug(1, "Number '%d' is too big for me\n", num);
1701                                                 res = -1;
1702                                         }
1703                                 }
1704                         }
1705                 }
1706
1707                 if (!res) {
1708                         if (!ast_streamfile(chan, fn, language)) {
1709                                 if ((audiofd > -1) && (ctrlfd > -1))
1710                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
1711                                 else
1712                                         res = ast_waitstream(chan, ints);
1713                         }
1714                         ast_stopstream(chan);
1715                 }
1716         }
1717         return res;
1718 }
1719
1720 /*! \brief  ast_say_number_full_no: Norwegian syntax 
1721  * New files:
1722  * In addition to American English, the following sounds are required:  "and", "1N"
1723  *
1724  * The grammar for Norwegian numbers is the same as for English except
1725  * for the following:
1726  * - 1 exists in both commune ("en", file "1") and neuter ("ett", file "1N")
1727  *   "and" before the last two digits, i.e. 2034 is "two thousand and
1728  *   thirty-four" and 1000012 is "one million and twelve".
1729  */
1730 static int ast_say_number_full_no(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
1731 {
1732         int res = 0;
1733         int playh = 0;
1734         int playa = 0;
1735         int cn = 1;             /* +1 = commune; -1 = neuter */
1736         char fn[256] = "";
1737         
1738         if (!num) 
1739                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
1740         
1741         if (options && !strncasecmp(options, "n", 1)) cn = -1;
1742
1743         while (!res && (num || playh || playa )) {
1744                 if (num < 0) {
1745                         ast_copy_string(fn, "digits/minus", sizeof(fn));
1746                         if ( num > INT_MIN ) {
1747                                 num = -num;
1748                         } else {
1749                                 num = 0;
1750                         }       
1751                 } else if (playh) {
1752                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
1753                         playh = 0;
1754                 } else if (playa) {
1755                         ast_copy_string(fn, "digits/and", sizeof(fn));
1756                         playa = 0;
1757                 } else if (num == 1 && cn == -1) {
1758                         ast_copy_string(fn, "digits/1N", sizeof(fn));
1759                         num = 0;
1760                 } else if (num < 20) {
1761                         snprintf(fn, sizeof(fn), "digits/%d", num);
1762                         num = 0;
1763                 } else if (num < 100) {
1764                         snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
1765                         num %= 10;
1766                 } else if (num < 1000) {
1767                         int hundreds = num / 100;
1768                         if (hundreds == 1)
1769                                 ast_copy_string(fn, "digits/1N", sizeof(fn));
1770                         else
1771                                 snprintf(fn, sizeof(fn), "digits/%d", (num / 100));
1772
1773                         playh++;
1774                         num -= 100 * hundreds;
1775                         if (num)
1776                                 playa++;
1777                 } else if (num < 1000000) {
1778                         res = ast_say_number_full_no(chan, num / 1000, ints, language, "n", audiofd, ctrlfd);
1779                         if (res)
1780                                 return res;
1781                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
1782                         num %= 1000;
1783                         if (num && num < 100)
1784                                 playa++;
1785                 } else if (num < 1000000000) {
1786                                 int millions = num / 1000000;
1787                                 res = ast_say_number_full_no(chan, millions, ints, language, "c", audiofd, ctrlfd);
1788                                 if (res)
1789                                         return res;
1790                                 ast_copy_string(fn, "digits/million", sizeof(fn));
1791                                 num %= 1000000;
1792                                 if (num && num < 100)
1793                                         playa++;
1794                 } else {
1795                                 ast_debug(1, "Number '%d' is too big for me\n", num);
1796                                 res = -1;
1797                 }
1798
1799                 if (!res) {
1800                         if (!ast_streamfile(chan, fn, language)) {
1801                                 if ((audiofd > -1) && (ctrlfd > -1))
1802                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
1803                                 else
1804                                         res = ast_waitstream(chan, ints);
1805                         }
1806                         ast_stopstream(chan);
1807                 }
1808         }
1809         return res;
1810 }
1811
1812 typedef struct {  
1813         char *separator_dziesiatek;
1814         char *cyfry[10];
1815         char *cyfry2[10];
1816         char *setki[10];
1817         char *dziesiatki[10];
1818         char *nastki[10];  
1819         char *rzedy[3][3];
1820 } odmiana;
1821
1822 static char *pl_rzad_na_tekst(odmiana *odm, int i, int rzad)
1823 {
1824         if (rzad==0)
1825                 return "";
1826  
1827         if (i==1)
1828                 return odm->rzedy[rzad - 1][0];
1829         if ((i > 21 || i < 11) &&  i%10 > 1 && i%10 < 5)
1830                 return odm->rzedy[rzad - 1][1];
1831         else
1832                 return odm->rzedy[rzad - 1][2];
1833 }
1834
1835 static char* pl_append(char* buffer, char* str)
1836 {
1837         strcpy(buffer, str);
1838         buffer += strlen(str);
1839         return buffer;
1840 }
1841
1842 static void pl_odtworz_plik(struct ast_channel *chan, const char *language, int audiofd, int ctrlfd, const char *ints, char *fn)
1843 {
1844         char file_name[255] = "digits/";
1845         strcat(file_name, fn);
1846         ast_debug(1, "Trying to play: %s\n", file_name);
1847         if (!ast_streamfile(chan, file_name, language)) {
1848                 if ((audiofd > -1) && (ctrlfd > -1))
1849                         ast_waitstream_full(chan, ints, audiofd, ctrlfd);
1850                 else
1851                         ast_waitstream(chan, ints);
1852         }
1853         ast_stopstream(chan);
1854 }
1855
1856 static void powiedz(struct ast_channel *chan, const char *language, int audiofd, int ctrlfd, const char *ints, odmiana *odm, int rzad, int i)
1857 {
1858         /* Initialise variables to allow compilation on Debian-stable, etc */
1859         int m1000E6 = 0;
1860         int i1000E6 = 0;
1861         int m1000E3 = 0;
1862         int i1000E3 = 0;
1863         int m1000 = 0;
1864         int i1000 = 0;
1865         int m100 = 0;
1866         int i100 = 0;
1867         
1868         if (i == 0 && rzad > 0) { 
1869                 return;
1870         }
1871         if (i == 0) {
1872                 pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->cyfry[0]);
1873                 return;
1874         }
1875
1876         m1000E6 = i % 1000000000;
1877         i1000E6 = i / 1000000000;
1878
1879         powiedz(chan, language, audiofd, ctrlfd, ints, odm, rzad+3, i1000E6);
1880
1881         m1000E3 = m1000E6 % 1000000;
1882         i1000E3 = m1000E6 / 1000000;
1883
1884         powiedz(chan, language, audiofd, ctrlfd, ints, odm, rzad+2, i1000E3);
1885
1886         m1000 = m1000E3 % 1000;
1887         i1000 = m1000E3 / 1000;
1888
1889         powiedz(chan, language, audiofd, ctrlfd, ints, odm, rzad+1, i1000);
1890
1891         m100 = m1000 % 100;
1892         i100 = m1000 / 100;
1893         
1894         if (i100>0)
1895                 pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->setki[i100]);
1896
1897         if ( m100 > 0 && m100 <=9 ) {
1898                 if (m1000>0)
1899                         pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->cyfry2[m100]);
1900                 else
1901                         pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->cyfry[m100]);
1902         } else if (m100 % 10 == 0) {
1903                 pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->dziesiatki[m100 / 10]);
1904         } else if (m100 <= 19 ) {
1905                 pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->nastki[m100 % 10]);
1906         } else if (m100 != 0) {
1907                 if (odm->separator_dziesiatek[0]==' ') {
1908                         pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->dziesiatki[m100 / 10]);
1909                         pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->cyfry2[m100 % 10]);
1910                 } else {
1911                         char buf[10];
1912                         char *b = buf;
1913                         b = pl_append(b, odm->dziesiatki[m100 / 10]);  
1914                         b = pl_append(b, odm->separator_dziesiatek);  
1915                         b = pl_append(b, odm->cyfry2[m100 % 10]); 
1916                         pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, buf);
1917                 }
1918         } 
1919
1920         if (rzad > 0) {
1921                 pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, pl_rzad_na_tekst(odm, i, rzad));
1922         }
1923 }
1924
1925 /* ast_say_number_full_pl: Polish syntax 
1926
1927 Sounds needed:
1928 0               zero
1929 1               jeden
1930 10              dziesiec
1931 100             sto
1932 1000            tysiac
1933 1000000         milion
1934 1000000000      miliard
1935 1000000000.2    miliardy
1936 1000000000.5    miliardow
1937 1000000.2       miliony
1938 1000000.5       milionow
1939 1000.2          tysiace
1940 1000.5          tysiecy
1941 100m            stu
1942 10m             dziesieciu
1943 11              jedenascie
1944 11m             jedenastu
1945 12              dwanascie
1946 12m             dwunastu
1947 13              trzynascie
1948 13m             trzynastu
1949 14              czternascie
1950 14m             czternastu
1951 15              pietnascie
1952 15m             pietnastu
1953 16              szesnascie
1954 16m             szesnastu
1955 17              siedemnascie
1956 17m             siedemnastu
1957 18              osiemnascie
1958 18m             osiemnastu
1959 19              dziewietnascie
1960 19m             dziewietnastu
1961 1z              jedna
1962 2               dwa
1963 20              dwadziescia
1964 200             dwiescie
1965 200m            dwustu
1966 20m             dwudziestu
1967 2-1m            dwaj
1968 2-2m            dwoch
1969 2z              dwie
1970 3               trzy
1971 30              trzydziesci
1972 300             trzysta
1973 300m            trzystu
1974 30m             trzydziestu
1975 3-1m            trzej
1976 3-2m            trzech
1977 4               cztery
1978 40              czterdziesci
1979 400             czterysta
1980 400m            czterystu
1981 40m             czterdziestu
1982 4-1m            czterej
1983 4-2m            czterech
1984 5               piec
1985 50              piecdziesiat
1986 500             piecset
1987 500m            pieciuset
1988 50m             piedziesieciu
1989 5m              pieciu
1990 6               szesc
1991 60              szescdziesiat
1992 600             szescset
1993 600m            szesciuset
1994 60m             szescdziesieciu
1995 6m              szesciu
1996 7               siedem
1997 70              siedemdziesiat
1998 700             siedemset
1999 700m            siedmiuset
2000 70m             siedemdziesieciu
2001 7m              siedmiu
2002 8               osiem
2003 80              osiemdziesiat
2004 800             osiemset
2005 800m            osmiuset
2006 80m             osiemdziesieciu
2007 8m              osmiu
2008 9               dziewiec
2009 90              dziewiecdziesiat
2010 900             dziewiecset
2011 900m            dziewieciuset
2012 90m             dziewiedziesieciu
2013 9m              dziewieciu
2014 and combinations of eg.: 20_1, 30m_3m, etc...
2015
2016 */
2017 static int ast_say_number_full_pl(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
2018 {
2019         char *zenski_cyfry[] = {"0", "1z", "2z", "3", "4", "5", "6", "7", "8", "9"};
2020
2021         char *zenski_cyfry2[] = {"0", "1", "2z", "3", "4", "5", "6", "7", "8", "9"};
2022
2023         char *meski_cyfry[] = {"0", "1", "2-1m", "3-1m", "4-1m", "5m",  /*"2-1mdwaj"*/ "6m", "7m", "8m", "9m"};
2024
2025         char *meski_cyfry2[] = {"0", "1", "2-2m", "3-2m", "4-2m", "5m", "6m", "7m", "8m", "9m"};
2026
2027         char *meski_setki[] = {"", "100m", "200m", "300m", "400m", "500m", "600m", "700m", "800m", "900m"};
2028
2029         char *meski_dziesiatki[] = {"", "10m", "20m", "30m", "40m", "50m", "60m", "70m", "80m", "90m"};
2030
2031         char *meski_nastki[] = {"", "11m", "12m", "13m", "14m", "15m", "16m", "17m", "18m", "19m"};
2032
2033         char *nijaki_cyfry[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
2034
2035         char *nijaki_cyfry2[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
2036
2037         char *nijaki_setki[] = {"", "100", "200", "300", "400", "500", "600", "700", "800", "900"};
2038
2039         char *nijaki_dziesiatki[] = {"", "10", "20", "30", "40", "50", "60", "70", "80", "90"};
2040
2041         char *nijaki_nastki[] = {"", "11", "12", "13", "14", "15", "16", "17", "18", "19"};
2042
2043         char *rzedy[][3] = { {"1000", "1000.2", "1000.5"}, {"1000000", "1000000.2", "1000000.5"}, {"1000000000", "1000000000.2", "1000000000.5"}}; 
2044
2045         /* Initialise variables to allow compilation on Debian-stable, etc */
2046         odmiana *o;
2047
2048         static odmiana *odmiana_nieosobowa = NULL; 
2049         static odmiana *odmiana_meska = NULL; 
2050         static odmiana *odmiana_zenska = NULL; 
2051
2052         if (odmiana_nieosobowa == NULL) {
2053                 odmiana_nieosobowa = ast_malloc(sizeof(*odmiana_nieosobowa));
2054
2055                 odmiana_nieosobowa->separator_dziesiatek = " ";
2056
2057                 memcpy(odmiana_nieosobowa->cyfry, nijaki_cyfry, sizeof(odmiana_nieosobowa->cyfry));
2058                 memcpy(odmiana_nieosobowa->cyfry2, nijaki_cyfry2, sizeof(odmiana_nieosobowa->cyfry));
2059                 memcpy(odmiana_nieosobowa->setki, nijaki_setki, sizeof(odmiana_nieosobowa->setki));
2060                 memcpy(odmiana_nieosobowa->dziesiatki, nijaki_dziesiatki, sizeof(odmiana_nieosobowa->dziesiatki));
2061                 memcpy(odmiana_nieosobowa->nastki, nijaki_nastki, sizeof(odmiana_nieosobowa->nastki));
2062                 memcpy(odmiana_nieosobowa->rzedy, rzedy, sizeof(odmiana_nieosobowa->rzedy));
2063         }
2064
2065         if (odmiana_zenska == NULL) {
2066                 odmiana_zenska = ast_malloc(sizeof(*odmiana_zenska));
2067
2068                 odmiana_zenska->separator_dziesiatek = " ";
2069
2070                 memcpy(odmiana_zenska->cyfry, zenski_cyfry, sizeof(odmiana_zenska->cyfry));
2071                 memcpy(odmiana_zenska->cyfry2, zenski_cyfry2, sizeof(odmiana_zenska->cyfry));
2072                 memcpy(odmiana_zenska->setki, nijaki_setki, sizeof(odmiana_zenska->setki));
2073                 memcpy(odmiana_zenska->dziesiatki, nijaki_dziesiatki, sizeof(odmiana_zenska->dziesiatki));
2074                 memcpy(odmiana_zenska->nastki, nijaki_nastki, sizeof(odmiana_zenska->nastki));
2075                 memcpy(odmiana_zenska->rzedy, rzedy, sizeof(odmiana_zenska->rzedy));
2076         }
2077
2078         if (odmiana_meska == NULL) {
2079                 odmiana_meska = ast_malloc(sizeof(*odmiana_meska));
2080
2081                 odmiana_meska->separator_dziesiatek = " ";
2082
2083                 memcpy(odmiana_meska->cyfry, meski_cyfry, sizeof(odmiana_meska->cyfry));
2084                 memcpy(odmiana_meska->cyfry2, meski_cyfry2, sizeof(odmiana_meska->cyfry));
2085                 memcpy(odmiana_meska->setki, meski_setki, sizeof(odmiana_meska->setki));
2086                 memcpy(odmiana_meska->dziesiatki, meski_dziesiatki, sizeof(odmiana_meska->dziesiatki));
2087                 memcpy(odmiana_meska->nastki, meski_nastki, sizeof(odmiana_meska->nastki));
2088                 memcpy(odmiana_meska->rzedy, rzedy, sizeof(odmiana_meska->rzedy));
2089         }
2090
2091         if (options) {
2092                 if (strncasecmp(options, "f", 1) == 0)
2093                         o = odmiana_zenska;
2094                 else if (strncasecmp(options, "m", 1) == 0)
2095                         o = odmiana_meska;
2096                 else
2097                         o = odmiana_nieosobowa;
2098         } else
2099                 o = odmiana_nieosobowa;
2100
2101         powiedz(chan, language, audiofd, ctrlfd, ints, o, 0, num);
2102         return 0;
2103 }
2104
2105 /* ast_say_number_full_pt: Portuguese syntax 
2106
2107  *      Extra sounds needed:
2108  *      For feminin all sound files ends with F
2109  *      100E for 100+ something
2110  *      1000000S for plural
2111  *      pt-e for 'and' 
2112  */
2113 static int ast_say_number_full_pt(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
2114 {
2115         int res = 0;
2116         int playh = 0;
2117         int mf = 1;                            /* +1 = male; -1 = female */
2118         char fn[256] = "";
2119
2120         if (!num) 
2121                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
2122
2123         if (options && !strncasecmp(options, "f", 1))
2124                 mf = -1;
2125
2126         while (!res && num ) {
2127                 if (num < 0) {
2128                         ast_copy_string(fn, "digits/minus", sizeof(fn));
2129                         if ( num > INT_MIN ) {
2130                                 num = -num;
2131                         } else {
2132                                 num = 0;
2133                         }       
2134                 } else if (num < 20) {
2135                         if ((num == 1 || num == 2) && (mf < 0))
2136                                 snprintf(fn, sizeof(fn), "digits/%dF", num);
2137                         else
2138                                 snprintf(fn, sizeof(fn), "digits/%d", num);
2139                         num = 0;
2140                 } else if (num < 100) {
2141                         snprintf(fn, sizeof(fn), "digits/%d", (num / 10) * 10);
2142                         if (num % 10)
2143                                 playh = 1;
2144                         num = num % 10;
2145                 } else if (num < 1000) {
2146                         if (num == 100)
2147                                 ast_copy_string(fn, "digits/100", sizeof(fn));
2148                         else if (num < 200)
2149                                 ast_copy_string(fn, "digits/100E", sizeof(fn));
2150                         else {
2151                                 if (mf < 0 && num > 199)
2152                                         snprintf(fn, sizeof(fn), "digits/%dF", (num / 100) * 100);
2153                                 else
2154                                         snprintf(fn, sizeof(fn), "digits/%d", (num / 100) * 100);
2155                                 if (num % 100)
2156                                         playh = 1;
2157                         }
2158                         num = num % 100;
2159                 } else if (num < 1000000) {
2160                         if (num > 1999) {
2161                                 res = ast_say_number_full_pt(chan, (num / 1000) * mf, ints, language, options, audiofd, ctrlfd);
2162                                 if (res)
2163                                         return res;
2164                         }
2165                         ast_copy_string(fn, "digits/1000", sizeof(fn));
2166                         if ((num % 1000) && ((num % 1000) < 100  || !(num % 100)))
2167                                 playh = 1;
2168                         num = num % 1000;
2169                 } else if (num < 1000000000) {
2170                         res = ast_say_number_full_pt(chan, (num / 1000000), ints, language, options, audiofd, ctrlfd );
2171                         if (res)
2172                                 return res;
2173                         if (num < 2000000)
2174                                 ast_copy_string(fn, "digits/1000000", sizeof(fn));
2175                         else
2176                                 ast_copy_string(fn, "digits/1000000S", sizeof(fn));
2177  
2178                         if ((num % 1000000) &&
2179                                 /* no thousands */
2180                                 ((!((num / 1000) % 1000) && ((num % 1000) < 100 || !(num % 100))) ||
2181                                 /* no hundreds and below */
2182                                 (!(num % 1000) && (((num / 1000) % 1000) < 100 || !((num / 1000) % 100))) ) )
2183                                 playh = 1;
2184                         num = num % 1000000;
2185                 } else {
2186                         /* number is too big */
2187                         ast_log(LOG_WARNING, "Number '%d' is too big to say.", num);
2188                         res = -1;
2189                 }
2190                 if (!res) {
2191                         if (!ast_streamfile(chan, fn, language)) {
2192                                 if ((audiofd > -1) && (ctrlfd > -1))
2193                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd); 
2194                                 else
2195                                         res = ast_waitstream(chan, ints);
2196                         }
2197                         ast_stopstream(chan);
2198                 }
2199                 if (!res && playh) {
2200                         res = wait_file(chan, ints, "digits/pt-e", language);
2201                         ast_stopstream(chan);
2202                         playh = 0;
2203                 }
2204         }
2205         return res;
2206 }
2207
2208 /*! \brief  ast_say_number_full_se: Swedish syntax 
2209
2210  Sound files needed
2211  - 1N
2212 */
2213 static int ast_say_number_full_se(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
2214 {
2215         int playh = 0;
2216         int start = 1;
2217         char fn[256] = "";
2218         int cn = 1;             /* +1 = commune; -1 = neuter */
2219         int res = 0;
2220
2221         if (!num) {
2222                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
2223         }
2224         if (options && !strncasecmp(options, "n", 1)) cn = -1;
2225
2226         while (num || playh) {
2227                 if (num < 0) {
2228                         ast_copy_string(fn, "digits/minus", sizeof(fn));
2229                         if ( num > INT_MIN ) {
2230                                 num = -num;
2231                         } else {
2232                                 num = 0;
2233                         }
2234                 } else if (playh) {
2235                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
2236                         playh = 0;
2237                 } else if (start  && num < 200 && num > 99 && cn == -1) {
2238                         /* Don't say "en hundra" just say "hundra". */
2239                         snprintf(fn, sizeof(fn), "digits/hundred");
2240                         num -= 100;
2241                 } else if (num == 1 && cn == -1) {      /* En eller ett? */
2242                         ast_copy_string(fn, "digits/1N", sizeof(fn));
2243                         num = 0;
2244                 } else if (num < 20) {
2245                         snprintf(fn, sizeof(fn), "digits/%d", num);
2246                         num = 0;
2247                 } else if (num < 100) { /* Below hundreds - teens and tens */
2248                         snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
2249                         num %= 10;
2250                 } else if (num < 1000) {
2251                         /* Hundreds */
2252                         snprintf(fn, sizeof(fn), "digits/%d", (num/100));
2253                         playh++;
2254                         num %= 100;
2255                 } else if (num < 1000000) { /* 1,000,000 */
2256                         /* Always say "ett hundra tusen", not "en hundra tusen" */
2257                         res = ast_say_number_full_se(chan, num / 1000, ints, language, "c", audiofd, ctrlfd);
2258                         if (res) {
2259                                 return res;
2260                         }
2261                         num %= 1000;
2262                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
2263                 } else if (num < 1000000000) {  /* 1,000,000,000 */
2264                         /* Always say "en miljon", not "ett miljon" */
2265                         res = ast_say_number_full_se(chan, num / 1000000, ints, language, "n", audiofd, ctrlfd);
2266                         if (res) {
2267                                 return res;
2268                         }
2269                         num %= 1000000;
2270                         ast_copy_string(fn, "digits/million", sizeof(fn));
2271                 } else {        /* Miljarder - Billions */
2272                         ast_debug(1, "Number '%d' is too big for me\n", num);
2273                         return -1;
2274                 }
2275
2276                 if (!ast_streamfile(chan, fn, language)) {
2277                         if ((audiofd > -1) && (ctrlfd > -1)) {
2278                                 res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
2279                         } else {
2280                                 res = ast_waitstream(chan, ints);
2281                         }
2282                         ast_stopstream(chan);
2283                         if (res) {
2284                                 return res;
2285                         }
2286                 }
2287                 start = 0;
2288         }
2289         return 0;
2290 }
2291
2292 /*! \brief  ast_say_number_full_zh: Taiwanese / Chinese syntax */
2293 static int ast_say_number_full_zh(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
2294 {
2295         int res = 0;
2296         int playh = 0;
2297         int playt = 0;
2298         int playz = 0;
2299         int last_length = 0;
2300         char buf[20] = "";
2301         char fn[256] = "";
2302         if (!num)
2303                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
2304
2305         while (!res && (num || playh || playt || playz)) {
2306                         if (num < 0) {
2307                                 ast_copy_string(fn, "digits/minus", sizeof(fn));
2308                                 if ( num > INT_MIN ) {
2309                                         num = -num;
2310                                 } else {
2311                                         num = 0;
2312                                 }       
2313                         } else if (playz) {
2314                                 snprintf(fn, sizeof(fn), "digits/0");
2315                                 last_length = 0;
2316                                 playz = 0;
2317                         } else if (playh) {
2318                                 ast_copy_string(fn, "digits/hundred", sizeof(fn));
2319                                 playh = 0;
2320                         } else if (playt) {
2321                                 snprintf(fn, sizeof(fn), "digits/thousand");
2322                                 playt = 0;
2323                         } else  if (num < 10) {
2324                                 snprintf(buf, 10, "%d", num);
2325                                 if (last_length - strlen(buf) > 1 && last_length != 0) {
2326                                         last_length = strlen(buf);
2327                                         playz++;
2328                                         continue;
2329                                 }
2330                                 snprintf(fn, sizeof(fn), "digits/%d", num);
2331                                 num = 0;
2332                         } else  if (num < 100) {
2333                                 snprintf(buf, 10, "%d", num);
2334                                 if (last_length - strlen(buf) > 1 && last_length != 0) {
2335                                         last_length = strlen(buf);
2336                                         playz++;
2337                                         continue;
2338                                 }
2339                                 last_length = strlen(buf);
2340                                 snprintf(fn, sizeof(fn), "digits/%d", (num / 10) * 10);
2341                                 num %= 10;
2342                         } else {
2343                                 if (num < 1000){
2344                                         snprintf(buf, 10, "%d", num);
2345                                         if (last_length - strlen(buf) > 1 && last_length != 0) {
2346                                                 last_length = strlen(buf);
2347                                                 playz++;
2348                                                 continue;
2349                                         }
2350                                         snprintf(fn, sizeof(fn), "digits/%d", (num / 100));
2351                                         playh++;
2352                                         snprintf(buf, 10, "%d", num);
2353                                         ast_debug(1, "Number '%d' %d %d\n", num, (int)strlen(buf), last_length);
2354                                         last_length = strlen(buf);
2355                                         num -= ((num / 100) * 100);
2356                                 } else if (num < 10000){
2357                                         snprintf(buf, 10, "%d", num);
2358                                         snprintf(fn, sizeof(fn), "digits/%d", (num / 1000));
2359                                         playt++;
2360                                         snprintf(buf, 10, "%d", num);
2361                                         ast_debug(1, "Number '%d' %d %d\n", num, (int)strlen(buf), last_length);
2362                                         last_length = strlen(buf);
2363                                         num -= ((num / 1000) * 1000);
2364                                 } else if (num < 100000000) { /* 100,000,000 */
2365                                                 res = ast_say_number_full_zh(chan, num / 10000, ints, language, audiofd, ctrlfd);
2366                                                 if (res)
2367                                                         return res;
2368                                                 snprintf(buf, 10, "%d", num);
2369                                                 ast_debug(1, "Number '%d' %d %d\n", num, (int)strlen(buf), last_length);
2370                                                 num -= ((num / 10000) * 10000);
2371                                                 last_length = strlen(buf);
2372                                                 snprintf(fn, sizeof(fn), "digits/wan");
2373                                 } else {
2374                                         if (num < 1000000000) { /* 1,000,000,000 */
2375                                                 res = ast_say_number_full_zh(chan, num / 100000000, ints, language, audiofd, ctrlfd);
2376                                                 if (res)
2377                                                         return res;
2378                                                 snprintf(buf, 10, "%d", num);
2379                                                 ast_debug(1, "Number '%d' %d %d\n", num, (int)strlen(buf), last_length);
2380                                                 last_length = strlen(buf);
2381                                                 num -= ((num / 100000000) * 100000000);
2382                                                 snprintf(fn, sizeof(fn), "digits/yi");
2383                                         } else {
2384                                                 ast_debug(1, "Number '%d' is too big for me\n", num);
2385                                                 res = -1;
2386                                         }
2387                                 }
2388                         }
2389                         if (!res) {
2390                                 if (!ast_streamfile(chan, fn, language)) {
2391                                         if ((audiofd > -1) && (ctrlfd > -1))
2392                                                 res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
2393                                         else
2394                                                 res = ast_waitstream(chan, ints);
2395                                 }
2396                                 ast_stopstream(chan);
2397                         }
2398         }
2399         return res;
2400 }
2401
2402 /*!\internal
2403  * \brief Counting in Urdu, the national language of Pakistan
2404  * \since 1.8
2405  */
2406 static int ast_say_number_full_ur(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
2407 {
2408         int res = 0;
2409         int playh = 0;
2410         char fn[256] = "";
2411
2412         if (!num) {
2413                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
2414         }
2415
2416         while (!res && (num || playh)) {
2417                 if (playh) {
2418                         snprintf(fn, sizeof(fn), "digits/hundred");
2419                         playh = 0;
2420                 } else if (num < 100) {
2421                         snprintf(fn, sizeof(fn), "digits/%d", num);
2422                         num = 0;
2423                 } else if (num < 1000) {
2424                         snprintf(fn, sizeof(fn), "digits/%d", (num / 100));
2425                         playh++;
2426                         num -= ((num / 100) * 100);
2427                 } else if (num < 100000) { /* 1,00,000 */
2428                         if ((res = ast_say_number_full_ur(chan, num / 1000, ints, language, options, audiofd, ctrlfd))) {
2429                                 return res;
2430                         }
2431                         num = num % 1000;
2432                         snprintf(fn, sizeof(fn), "digits/thousand");
2433                 } else if (num < 10000000) { /* 1,00,00,000 */
2434                         if ((res = ast_say_number_full_ur(chan, num / 100000, ints, language, options, audiofd, ctrlfd))) {
2435                                 return res;
2436                         }
2437                         num = num % 100000;
2438                         snprintf(fn, sizeof(fn), "digits/lac");
2439                 } else if (num < 1000000000) { /* 1,00,00,00,000 */
2440                         if ((res = ast_say_number_full_ur(chan, num / 10000000, ints, language, options, audiofd, ctrlfd))) {
2441                                 return res;
2442                         }
2443                         num = num % 10000000;
2444                         snprintf(fn, sizeof(fn), "digits/crore");
2445                 } else {
2446                         ast_debug(1, "Number '%d' is too big for me\n", num);
2447                         res = -1;
2448                 }
2449
2450                 if (!res) {
2451                         if (!ast_streamfile(chan, fn, language)) {
2452                                 if ((audiofd > -1) && (ctrlfd > -1)) {
2453                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
2454                                 } else {
2455                                         res = ast_waitstream(chan, ints);
2456                                 }
2457                         }
2458                         ast_stopstream(chan);
2459                 }
2460         }
2461         return res;
2462 }
2463
2464 /*! \brief  determine last digits for thousands/millions (ru) */
2465 static int get_lastdigits_ru(int num) {
2466         if (num < 20) {
2467                 return num;
2468         } else if (num < 100) {
2469                 return get_lastdigits_ru(num % 10);
2470         } else if (num < 1000) {
2471                 return get_lastdigits_ru(num % 100);
2472         }
2473         return 0;       /* number too big */
2474 }
2475
2476
2477 /*! \brief  ast_say_number_full_ru: Russian syntax 
2478
2479  additional files:
2480         n00.gsm                 (one hundred, two hundred, ...)
2481         thousand.gsm
2482         million.gsm
2483         thousands-i.gsm         (tisyachi)
2484         million-a.gsm           (milliona)
2485         thousands.gsm
2486         millions.gsm
2487         1f.gsm                  (odna)
2488         2f.gsm                  (dve)
2489
2490         where 'n' from 1 to 9
2491 */
2492 static int ast_say_number_full_ru(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
2493 {
2494         int res = 0;
2495         int lastdigits = 0;
2496         char fn[256] = "";
2497         if (!num) 
2498                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
2499
2500         while (!res && (num)) {
2501                 if (num < 0) {
2502                         ast_copy_string(fn, "digits/minus", sizeof(fn));
2503                         if ( num > INT_MIN ) {
2504                                 num = -num;
2505                         } else {
2506                                 num = 0;
2507                         }       
2508                 } else  if (num < 20) {
2509                         if (options && strlen(options) == 1 && num < 3) {
2510                             snprintf(fn, sizeof(fn), "digits/%d%s", num, options);
2511                         } else {
2512                                 snprintf(fn, sizeof(fn), "digits/%d", num);
2513                         }
2514                         num = 0;
2515                 } else if (num < 100) {
2516                         snprintf(fn, sizeof(fn), "digits/%d", num - (num % 10));
2517                         num %= 10;
2518                 } else if (num < 1000){
2519                         snprintf(fn, sizeof(fn), "digits/%d", num - (num % 100));
2520                         num %= 100;
2521                 } else if (num < 1000000) { /* 1,000,000 */
2522                         lastdigits = get_lastdigits_ru(num / 1000);
2523                         /* say thousands */
2524                         if (lastdigits < 3) {
2525                                 res = ast_say_number_full_ru(chan, num / 1000, ints, language, "f", audiofd, ctrlfd);
2526                         } else {
2527                                 res = ast_say_number_full_ru(chan, num / 1000, ints, language, NULL, audiofd, ctrlfd);
2528                         }
2529                         if (res)
2530                                 return res;
2531                         if (lastdigits == 1) {
2532                                 ast_copy_string(fn, "digits/thousand", sizeof(fn));
2533                         } else if (lastdigits > 1 && lastdigits < 5) {
2534                                 ast_copy_string(fn, "digits/thousands-i", sizeof(fn));
2535                         } else {
2536                                 ast_copy_string(fn, "digits/thousands", sizeof(fn));
2537                         }
2538                         num %= 1000;
2539                 } else if (num < 1000000000) {  /* 1,000,000,000 */
2540                         lastdigits = get_lastdigits_ru(num / 1000000);
2541                         /* say millions */
2542                         res = ast_say_number_full_ru(chan, num / 1000000, ints, language, NULL, audiofd, ctrlfd);
2543                         if (res)
2544                                 return res;
2545                         if (lastdigits == 1) {
2546                                 ast_copy_string(fn, "digits/million", sizeof(fn));
2547                         } else if (lastdigits > 1 && lastdigits < 5) {
2548                                 ast_copy_string(fn, "digits/million-a", sizeof(fn));
2549                         } else {
2550                                 ast_copy_string(fn, "digits/millions", sizeof(fn));
2551                         }
2552                         num %= 1000000;
2553                 } else {
2554                         ast_debug(1, "Number '%d' is too big for me\n", num);
2555                         res = -1;
2556                 }
2557                 if (!res) {
2558                         if (!ast_streamfile(chan, fn, language)) {
2559                                 if ((audiofd  > -1) && (ctrlfd > -1))
2560                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
2561                                 else
2562                                         res = ast_waitstream(chan, ints);
2563                         }
2564                         ast_stopstream(chan);
2565                 }
2566         }
2567         return res;
2568 }
2569
2570 /*! \brief Thai syntax */
2571 static int ast_say_number_full_th(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
2572 {
2573         int res = 0;
2574         int playh = 0;
2575         char fn[256] = "";
2576         if (!num) 
2577                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
2578
2579         while(!res && (num || playh)) {
2580                 if (num < 0) {
2581                         ast_copy_string(fn, "digits/lop", sizeof(fn));
2582                         if ( num > INT_MIN ) {
2583                                 num = -num;
2584                         } else {
2585                                 num = 0;
2586                         }       
2587                 } else if (playh) {
2588                         ast_copy_string(fn, "digits/roi", sizeof(fn));
2589                         playh = 0;
2590                 } else if (num < 100) {
2591                         if ((num <= 20) || ((num % 10) == 1)) {
2592                                 snprintf(fn, sizeof(fn), "digits/%d", num);
2593                                 num = 0;
2594                         } else {
2595                                 snprintf(fn, sizeof(fn), "digits/%d", (num / 10) * 10);
2596                                 num %= 10;
2597                         }
2598                 } else if (num < 1000) {
2599                         snprintf(fn, sizeof(fn), "digits/%d", (num/100));
2600                         playh++;
2601                         num %= 100;
2602                 } else if (num < 10000) { /* 10,000 */
2603                         res = ast_say_number_full_th(chan, num / 1000, ints, language, audiofd, ctrlfd);
2604                         if (res)
2605                                 return res;
2606                         num %= 1000;
2607                         ast_copy_string(fn, "digits/pan", sizeof(fn));
2608                 } else if (num < 100000) { /* 100,000 */
2609                         res = ast_say_number_full_th(chan, num / 10000, ints, language, audiofd, ctrlfd);
2610                         if (res)
2611                                 return res;
2612                         num %= 10000;
2613                         ast_copy_string(fn, "digits/muan", sizeof(fn));
2614                 } else if (num < 1000000) { /* 1,000,000 */
2615                         res = ast_say_number_full_th(chan, num / 100000, ints, language, audiofd, ctrlfd);
2616                         if (res)
2617                                 return res;
2618                         num %= 100000;
2619                         ast_copy_string(fn, "digits/san", sizeof(fn));
2620                 } else {
2621                         res = ast_say_number_full_th(chan, num / 1000000, ints, language, audiofd, ctrlfd);
2622                         if (res)
2623                                 return res;
2624                         num %= 1000000;
2625                         ast_copy_string(fn, "digits/larn", sizeof(fn));
2626                 }
2627                 if (!res) {
2628                         if(!ast_streamfile(chan, fn, language)) {
2629                                 if ((audiofd  > -1) && (ctrlfd > -1))
2630                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
2631                                 else
2632                                         res = ast_waitstream(chan, ints);
2633                         }
2634                         ast_stopstream(chan);
2635                 }
2636         }
2637         return res;
2638 }
2639
2640 /*! \brief  ast_say_number_full_vi: Vietnamese syntax */
2641 static int ast_say_number_full_vi(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
2642 {
2643         int res = 0;
2644         int playh = 0;
2645         int playoh = 0;
2646         int playohz = 0;
2647         int playz = 0;
2648         int playl = 0;
2649         char fn[256] = "";
2650         if (!num) 
2651                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
2652         while (!res && (num || playh)) {
2653                 if (num < 0) {
2654                         ast_copy_string(fn, "digits/minus", sizeof(fn));
2655                         if ( num > INT_MIN ) {
2656                                 num = -num;
2657                         } else {
2658                                 num = 0;
2659                         }       
2660                 } else if (playl) {
2661                         snprintf(fn, sizeof(fn), "digits/%da", num);
2662                         playl = 0;
2663                         num = 0;
2664                 } else if (playh) {
2665                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
2666                         playh = 0;
2667                 } else if (playz) {
2668                         ast_copy_string(fn, "digits/odd", sizeof(fn));
2669                         playz = 0;                      
2670                 } else if (playoh) {
2671                         ast_copy_string(fn, "digits/0-hundred", sizeof(fn));
2672                         playoh = 0;
2673                 } else if (playohz) {
2674                         ast_copy_string(fn, "digits/0-hundred-odd", sizeof(fn));
2675                         playohz = 0;
2676                 } else  if (num < 20) {
2677                         snprintf(fn, sizeof(fn), "digits/%d", num);
2678                         num = 0;
2679                 } else  if (num < 100) {
2680                         snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
2681                         num %= 10;
2682                         if ((num == 5) || (num == 4) || (num == 1)) playl++;
2683                 } else {
2684                         if (num < 1000) {
2685                                 snprintf(fn, sizeof(fn), "digits/%d", (num/100));                               
2686                                 num %= 100;
2687                                 if (num && (num < 10)) {
2688                                         playz++;
2689                                         playh++;
2690                                 } else {
2691                                         playh++;
2692                                 }
2693                         } else {
2694                                 if (num < 1000000) { /* 1,000,000 */
2695                                         res = ast_say_number_full_vi(chan, num / 1000, ints, language, audiofd, ctrlfd);
2696                                         if (res)
2697                                                 return res;
2698                                         num %= 1000;
2699                                         snprintf(fn, sizeof(fn), "digits/thousand");
2700                                         if (num && (num < 10)) {
2701                                                 playohz++;
2702                                         } else if (num && (num < 100)){
2703                                                 playoh++;
2704                                         } else {
2705                                                 playh = 0;
2706                                                 playohz = 0;
2707                                                 playoh = 0;
2708                                         }
2709                                 } else {
2710                                         if (num < 1000000000) { /* 1,000,000,000 */
2711                                                 res = ast_say_number_full_vi(chan, num / 1000000, ints, language, audiofd, ctrlfd);
2712                                                 if (res)
2713                                                         return res;
2714                                                 num %= 1000000;
2715                                                 ast_copy_string(fn, "digits/million", sizeof(fn));
2716                                         } else {
2717                                                 res = -1;
2718                                         }
2719                                 }
2720                         }
2721                 }
2722                 if (!res) {
2723                         if (!ast_streamfile(chan, fn, language)) {
2724                                 if ((audiofd  > -1) && (ctrlfd > -1))
2725                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
2726                                 else
2727                                         res = ast_waitstream(chan, ints);
2728                         }
2729                         ast_stopstream(chan);
2730                 }
2731         }
2732         return res;
2733 }
2734
2735 /*! \brief  ast_say_enumeration_full: call language-specific functions 
2736  * \note Called from AGI */
2737 static int say_enumeration_full(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
2738 {
2739         if (!strncasecmp(language, "en", 2)) {        /* English syntax */
2740            return ast_say_enumeration_full_en(chan, num, ints, language, audiofd, ctrlfd);
2741         } else if (!strncasecmp(language, "da", 2)) { /* Danish syntax */
2742            return ast_say_enumeration_full_da(chan, num, ints, language, options, audiofd, ctrlfd);
2743         } else if (!strncasecmp(language, "de", 2)) { /* German syntax */
2744            return ast_say_enumeration_full_de(chan, num, ints, language, options, audiofd, ctrlfd);
2745         } else if (!strncasecmp(language, "he", 2)) { /* Hebrew syntax */
2746                 return ast_say_enumeration_full_he(chan, num, ints, language, options, audiofd, ctrlfd);
2747         } else if (!strncasecmp(language, "vi", 2)) { /* Vietnamese syntax */
2748                 return ast_say_enumeration_full_vi(chan, num, ints, language, audiofd, ctrlfd);
2749         }
2750
2751         /* Default to english */
2752         return ast_say_enumeration_full_en(chan, num, ints, language, audiofd, ctrlfd);
2753 }
2754
2755 /*! \brief  ast_say_enumeration_full_en: English syntax 
2756  \note This is the default syntax, if no other syntax defined in this file is used */
2757 static int ast_say_enumeration_full_en(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
2758 {
2759         int res = 0, t = 0;
2760         char fn[256] = "";
2761         
2762         while (!res && num) {
2763                 if (num < 0) {
2764                         ast_copy_string(fn, "digits/minus", sizeof(fn)); /* kind of senseless for enumerations, but our best effort for error checking */
2765                         if ( num > INT_MIN ) {
2766                                 num = -num;
2767                         } else {
2768                                 num = 0;
2769                         }       
2770                 } else if (num < 20) {
2771                         snprintf(fn, sizeof(fn), "digits/h-%d", num);
2772                         num = 0;
2773                 } else if (num < 100) { 
2774                         int tens = num / 10;
2775                         num = num % 10;
2776                         if (num == 0) {
2777                                 snprintf(fn, sizeof(fn), "digits/h-%d", (tens * 10));
2778                         } else {
2779                                 snprintf(fn, sizeof(fn), "digits/%d", (tens * 10));
2780                         }
2781                 } else if (num < 1000) {
2782                         int hundreds = num / 100;
2783                         num = num % 100;
2784                         if (hundreds > 1 || t == 1) {
2785                                 res = ast_say_number_full_en(chan, hundreds, ints, language, audiofd, ctrlfd);
2786                         }                       
2787                         if (res)
2788                                 return res;
2789                         if (num) {
2790                                 ast_copy_string(fn, "digits/hundred", sizeof(fn));
2791                         } else {
2792                                 ast_copy_string(fn, "digits/h-hundred", sizeof(fn));
2793                         }
2794                 } else if (num < 1000000) {
2795                         int thousands = num / 1000;
2796                         num = num % 1000;
2797                         if (thousands > 1 || t == 1) {
2798                                 res = ast_say_number_full_en(chan, thousands, ints, language, audiofd, ctrlfd);
2799                         }
2800                         if (res)
2801                                 return res;
2802                         if (num) {                                      
2803                                 ast_copy_string(fn, "digits/thousand", sizeof(fn));
2804                         } else {
2805                                 ast_copy_string(fn, "digits/h-thousand", sizeof(fn));
2806                         }
2807                         t = 1;
2808                 } else if (num < 1000000000) {
2809                         int millions = num / 1000000;
2810                         num = num % 1000000;
2811                         t = 1;
2812                         res = ast_say_number_full_en(chan, millions, ints, language, audiofd, ctrlfd);
2813                         if (res)
2814                                 return res;
2815                         if (num) {                                      
2816                                 ast_copy_string(fn, "digits/million", sizeof(fn));
2817                         } else {
2818                                 ast_copy_string(fn, "digits/h-million", sizeof(fn));
2819                         }
2820                 } else if (num < INT_MAX) {
2821                         int billions = num / 1000000000;
2822                         num = num % 1000000000;
2823                         t = 1;
2824                         res = ast_say_number_full_en(chan, billions, ints, language, audiofd, ctrlfd);
2825                         if (res)
2826                                 return res;
2827                         if (num) {
2828                                 ast_copy_string(fn, "digits/billion", sizeof(fn));
2829                         } else {
2830                                 ast_copy_string(fn, "digits/h-billion", sizeof(fn));
2831                         }
2832                 } else if (num == INT_MAX) {
2833                         ast_copy_string(fn, "digits/h-last", sizeof(fn));
2834                         num = 0;
2835                 } else {
2836                         ast_debug(1, "Number '%d' is too big for me\n", num);
2837                         res = -1;
2838                 }
2839
2840                 if (!res) {
2841                         if (!ast_streamfile(chan, fn, language)) {
2842                                 if ((audiofd > -1) && (ctrlfd > -1)) {
2843                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
2844                                 } else {
2845                                         res = ast_waitstream(chan, ints);
2846                                 }
2847                         }
2848                         ast_stopstream(chan);
2849                 }
2850         }
2851         return res;
2852 }
2853
2854 static int ast_say_enumeration_full_vi(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
2855 {
2856         int res = 0;
2857         char fn[256] = "";
2858         ast_copy_string(fn, "digits/h", sizeof(fn));
2859         if (!res) {
2860                 if (!ast_streamfile(chan, fn, language)) {
2861                         if ((audiofd > -1) && (ctrlfd > -1)) {
2862                                 res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
2863                         } else {
2864                                 res = ast_waitstream(chan, ints);
2865                         }
2866                 }
2867                 ast_stopstream(chan);
2868         }
2869
2870         return ast_say_number_full_vi(chan, num, ints, language, audiofd, ctrlfd);
2871 }
2872
2873 /*! \brief  ast_say_enumeration_full_da: Danish syntax */
2874 static int ast_say_enumeration_full_da(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
2875 {
2876         /* options can be: '' or 'm' male gender; 'f' female gender; 'n' neuter gender; 'p' plural */
2877         int res = 0, t = 0;
2878         char fn[256] = "", fna[256] = "";
2879         char *gender;
2880
2881         if (options && !strncasecmp(options, "f", 1)) {
2882                 gender = "F";
2883         } else if (options && !strncasecmp(options, "n", 1)) {
2884                 gender = "N";
2885         } else {
2886                 gender = "";
2887         }
2888
2889         if (!num) 
2890                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
2891
2892         while (!res && num) {
2893                 if (num < 0) {
2894                         ast_copy_string(fn, "digits/minus", sizeof(fn)); /* kind of senseless for enumerations, but our best effort for error checking */
2895                         if ( num > INT_MIN ) {
2896                                 num = -num;
2897                         } else {
2898                                 num = 0;
2899                         }       
2900                 } else if (num < 100 && t) {
2901                         ast_copy_string(fn, "digits/and", sizeof(fn));
2902                         t = 0;
2903                 } else if (num < 20) {
2904                         snprintf(fn, sizeof(fn), "digits/h-%d%s", num, gender);
2905                         num = 0;
2906                 } else if (num < 100) {
2907                         int ones = num % 10;
2908                         if (ones) {
2909                                 snprintf(fn, sizeof(fn), "digits/%d-and", ones);
2910                                 num -= ones;
2911                         } else {
2912                                 snprintf(fn, sizeof(fn), "digits/h-%d%s", num, gender);
2913                                 num = 0;
2914                         }
2915                 } else if (num == 100 && t == 0) {
2916                         snprintf(fn, sizeof(fn), "digits/h-hundred%s", gender);
2917                         num = 0;
2918                 } else if (num < 1000) {
2919                         int hundreds = num / 100;
2920                         num = num % 100;
2921                         if (hundreds == 1) {
2922                                 ast_copy_string(fn, "digits/1N", sizeof(fn));
2923                         } else {
2924                                 snprintf(fn, sizeof(fn), "digits/%d", hundreds);
2925                         }
2926                         if (num) {                                      
2927                                 ast_copy_string(fna, "digits/hundred", sizeof(fna));
2928                         } else {
2929                                 snprintf(fna, sizeof(fna), "digits/h-hundred%s", gender);
2930                         }
2931                         t = 1;
2932                 } else  if (num < 1000000) {
2933                         int thousands = num / 1000;
2934                         num = num % 1000;
2935                         if (thousands == 1) {
2936                                 if (num) {                                      
2937                                         ast_copy_string(fn, "digits/1N", sizeof(fn));
2938                                         ast_copy_string(fna, "digits/thousand", sizeof(fna));
2939                                 } else {
2940                                         if (t) {
2941                                                 ast_copy_string(fn, "digits/1N", sizeof(fn));
2942                                                 snprintf(fna, sizeof(fna), "digits/h-thousand%s", gender);
2943                                         } else {
2944                                                 snprintf(fn, sizeof(fn), "digits/h-thousand%s", gender);
2945                                         }
2946                                 }
2947                         } else {
2948                                 res = ast_say_number_full_de(chan, thousands, ints, language, options, audiofd, ctrlfd);
2949                                 if (res) {
2950                                         return res;
2951                                 }
2952                                 if (num) {                                      
2953                                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
2954                                 } else {
2955                                         snprintf(fn, sizeof(fn), "digits/h-thousand%s", gender);
2956                                 }
2957                         }
2958                         t = 1;
2959                 } else if (num < 1000000000) {
2960                         int millions = num / 1000000;
2961                         num = num % 1000000;
2962                         if (millions == 1) {
2963                                 if (num) {                                      
2964                                         ast_copy_string(fn, "digits/1F", sizeof(fn));
2965                                         ast_copy_string(fna, "digits/million", sizeof(fna));
2966                                 } else {
2967                                         ast_copy_string(fn, "digits/1N", sizeof(fn));
2968                                         snprintf(fna, sizeof(fna), "digits/h-million%s", gender);
2969                                 }
2970                         } else {
2971                                 res = ast_say_number_full_de(chan, millions, ints, language, options, audiofd, ctrlfd);
2972                                 if (res) {
2973                                         return res;
2974                                 }
2975                                 if (num) {                                      
2976                                         ast_copy_string(fn, "digits/millions", sizeof(fn));
2977                                 } else {
2978                                         snprintf(fn, sizeof(fn), "digits/h-million%s", gender);
2979                                 }
2980                         }
2981                         t = 1;
2982                 } else if (num < INT_MAX) {
2983                         int billions = num / 1000000000;
2984                         num = num % 1000000000;
2985                         if (billions == 1) {
2986                                 if (num) {                                      
2987                                         ast_copy_string(fn, "digits/1F", sizeof(fn));
2988                                         ast_copy_string(fna, "digits/milliard", sizeof(fna));
2989                                 } else {
2990                                         ast_copy_string(fn, "digits/1N", sizeof(fn));
2991                                         snprintf(fna, sizeof(fna), "digits/h-milliard%s", gender);
2992                                 }
2993                         } else {
2994                                 res = ast_say_number_full_de(chan, billions, ints, language, options, audiofd, ctrlfd);
2995                                 if (res)
2996                                         return res;
2997                                 if (num) {
2998                                         ast_copy_string(fn, "digits/milliards", sizeof(fna));
2999                                 } else {
3000                                         snprintf(fn, sizeof(fna), "digits/h-milliard%s", gender);
3001                                 }
3002                         }
3003                         t = 1;
3004                 } else if (num == INT_MAX) {
3005                         snprintf(fn, sizeof(fn), "digits/h-last%s", gender);
3006                         num = 0;
3007                 } else {
3008                         ast_debug(1, "Number '%d' is too big for me\n", num);
3009                         res = -1;
3010                 }
3011
3012                 if (!res) {
3013                         if (!ast_streamfile(chan, fn, language)) {
3014                                 if ((audiofd > -1) && (ctrlfd > -1))
3015                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
3016                                 else
3017                                         res = ast_waitstream(chan, ints);
3018                         }
3019                         ast_stopstream(chan);
3020                         if (!res) {
3021                                 if (strlen(fna) != 0 && !ast_streamfile(chan, fna, language)) {
3022                                         if ((audiofd > -1) && (ctrlfd > -1)) {
3023                                                 res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
3024                                         } else {
3025                                                 res = ast_waitstream(chan, ints);
3026                                         }
3027                                 }
3028                                 ast_stopstream(chan);
3029                                 strcpy(fna, "");
3030                         }
3031                 }
3032         }
3033         return res;
3034 }
3035
3036 /*! \brief  ast_say_enumeration_full_de: German syntax */
3037 static int ast_say_enumeration_full_de(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
3038 {
3039         /* options can be: '' or 'm' male gender; 'f' female gender; 'n' neuter gender; 'p' plural */
3040         int res = 0, t = 0;
3041         char fn[256] = "", fna[256] = "";
3042         char *gender;
3043
3044         if (options && !strncasecmp(options, "f", 1)) {
3045                 gender = "F";
3046         } else if (options && !strncasecmp(options, "n", 1)) {
3047                 gender = "N";
3048         } else {
3049                 gender = "";
3050         }
3051
3052         if (!num) 
3053                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
3054
3055         while (!res && num) {
3056                 if (num < 0) {
3057                         ast_copy_string(fn, "digits/minus", sizeof(fn)); /* kind of senseless for enumerations, but our best effort for error checking */
3058                         if ( num > INT_MIN ) {
3059                                 num = -num;
3060                         } else {
3061                                 num = 0;
3062                         }       
3063                 } else if (num < 100 && t) {
3064                         ast_copy_string(fn, "digits/and", sizeof(fn));
3065                         t = 0;
3066                 } else if (num < 20) {
3067                         snprintf(fn, sizeof(fn), "digits/h-%d%s", num, gender);
3068                         num = 0;
3069                 } else if (num < 100) {
3070                         int ones = num % 10;
3071                         if (ones) {
3072                                 snprintf(fn, sizeof(fn), "digits/%d-and", ones);
3073                                 num -= ones;
3074                         } else {
3075                                 snprintf(fn, sizeof(fn), "digits/h-%d%s", num, gender);
3076                                 num = 0;
3077                         }
3078                 } else if (num == 100 && t == 0) {
3079                         snprintf(fn, sizeof(fn), "digits/h-hundred%s", gender);
3080                         num = 0;
3081                 } else if (num < 1000) {
3082                         int hundreds = num / 100;
3083                         num = num % 100;
3084                         if (hundreds == 1) {
3085                                 ast_copy_string(fn, "digits/1N", sizeof(fn));
3086                         } else {
3087                                 snprintf(fn, sizeof(fn), "digits/%d", hundreds);
3088                         }
3089                         if (num) {                                      
3090                                 ast_copy_string(fna, "digits/hundred", sizeof(fna));
3091                         } else {
3092                                 snprintf(fna, sizeof(fna), "digits/h-hundred%s", gender);
3093                         }
3094                         t = 1;
3095                 } else  if (num < 1000000) {
3096                         int thousands = num / 1000;
3097                         num = num % 1000;
3098                         if (thousands == 1) {
3099                                 if (num) {                                      
3100                                         ast_copy_string(fn, "digits/1N", sizeof(fn));
3101                                         ast_copy_string(fna, "digits/thousand", sizeof(fna));