Merged revisions 339353 via svnmerge from
[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                 * - 'and' should not go between a hundreds place value and any
841                 *   tens/ones place values that follows it. i.e 136 is ein hundert
842                 *   sechs und dreizig, not ein hundert und sechs und dreizig.
843                 */
844                 if (num < 0) {
845                         ast_copy_string(fn, "digits/minus", sizeof(fn));
846                         if ( num > INT_MIN ) {
847                                 num = -num;
848                         } else {
849                                 num = 0;
850                         }
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                 } else if (num == 1000 && t == 0) {
879                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
880                         num = 0;
881                 } else  if (num < 1000000) {
882                         int thousands = num / 1000;
883                         num = num % 1000;
884                         t = 1;
885                         if (thousands == 1) {
886                                 ast_copy_string(fn, "digits/1N", sizeof(fn));
887                                 ast_copy_string(fna, "digits/thousand", sizeof(fna));
888                         } else {
889                                 res = ast_say_number_full_de(chan, thousands, ints, language, options, audiofd, ctrlfd);
890                                 if (res)
891                                         return res;
892                                 ast_copy_string(fn, "digits/thousand", sizeof(fn));
893                         }
894                 } else if (num < 1000000000) {
895                         int millions = num / 1000000;
896                         num = num % 1000000;
897                         t = 1;
898                         if (millions == 1) {
899                                 ast_copy_string(fn, "digits/1F", sizeof(fn));
900                                 ast_copy_string(fna, "digits/million", sizeof(fna));
901                         } else {
902                                 res = ast_say_number_full_de(chan, millions, ints, language, options, audiofd, ctrlfd);
903                                 if (res)
904                                         return res;
905                                 ast_copy_string(fn, "digits/millions", sizeof(fn));
906                         }
907                 } else if (num <= INT_MAX) {
908                         int billions = num / 1000000000;
909                         num = num % 1000000000;
910                         t = 1;
911                         if (billions == 1) {
912                                 ast_copy_string(fn, "digits/1F", sizeof(fn));
913                                 ast_copy_string(fna, "digits/milliard", sizeof(fna));
914                         } else {
915                                 res = ast_say_number_full_de(chan, billions, ints, language, options, audiofd, ctrlfd);
916                                 if (res) {
917                                         return res;
918                                 }
919                                 ast_copy_string(fn, "digits/milliards", sizeof(fn));
920                         }
921                 } else {
922                         ast_debug(1, "Number '%d' is too big for me\n", num);
923                         res = -1;
924                 }
925                 if (!res) {
926                         if (!ast_streamfile(chan, fn, language)) {
927                                 if ((audiofd > -1) && (ctrlfd > -1))
928                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
929                                 else
930                                         res = ast_waitstream(chan, ints);
931                         }
932                         ast_stopstream(chan);
933                         if (!res) {
934                                 if (strlen(fna) != 0 && !ast_streamfile(chan, fna, language)) {
935                                         if ((audiofd > -1) && (ctrlfd > -1))
936                                                 res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
937                                         else
938                                                 res = ast_waitstream(chan, ints);
939                                 }
940                                 ast_stopstream(chan);
941                                 strcpy(fna, "");
942                         }
943                 }
944         }
945         return res;
946 }
947
948 /*! \brief  ast_say_number_full_en_GB: British syntax 
949  New files:
950   - In addition to American English, the following sounds are required:  "and"
951  */
952 static int ast_say_number_full_en_GB(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
953 {
954         int res = 0;
955         int playh = 0;
956         int playa = 0;
957         char fn[256] = "";
958         if (!num) 
959                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
960
961         while (!res && (num || playh || playa )) {
962                 if (num < 0) {
963                         ast_copy_string(fn, "digits/minus", sizeof(fn));
964                         if ( num > INT_MIN ) {
965                                 num = -num;
966                         } else {
967                                 num = 0;
968                         }       
969                 } else if (playh) {
970                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
971                         playh = 0;
972                 } else if (playa) {
973                         ast_copy_string(fn, "digits/and", sizeof(fn));
974                         playa = 0;
975                 } else if (num < 20) {
976                         snprintf(fn, sizeof(fn), "digits/%d", num);
977                         num = 0;
978                 } else if (num < 100) {
979                         snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
980                         num %= 10;
981                 } else if (num < 1000) {
982                         int hundreds = num / 100;
983                         snprintf(fn, sizeof(fn), "digits/%d", (num / 100));
984
985                         playh++;
986                         num -= 100 * hundreds;
987                         if (num)
988                                 playa++;
989                 } else if (num < 1000000) {
990                         res = ast_say_number_full_en_GB(chan, num / 1000, ints, language, audiofd, ctrlfd);
991                         if (res)
992                                 return res;
993                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
994                         num %= 1000;
995                         if (num && num < 100)
996                                 playa++;
997                 } else if (num < 1000000000) {
998                                 int millions = num / 1000000;
999                                 res = ast_say_number_full_en_GB(chan, millions, ints, language, audiofd, ctrlfd);
1000                                 if (res)
1001                                         return res;
1002                                 ast_copy_string(fn, "digits/million", sizeof(fn));
1003                                 num %= 1000000;
1004                                 if (num && num < 100)
1005                                         playa++;
1006                 } else {
1007                                 ast_debug(1, "Number '%d' is too big for me\n", num);
1008                                 res = -1;
1009                 }
1010
1011                 if (!res) {
1012                         if (!ast_streamfile(chan, fn, language)) {
1013                                 if ((audiofd > -1) && (ctrlfd > -1))
1014                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
1015                                 else
1016                                         res = ast_waitstream(chan, ints);
1017                         }
1018                         ast_stopstream(chan);
1019                 }
1020         }
1021         return res;
1022 }
1023
1024 /*! \brief  ast_say_number_full_es: Spanish syntax 
1025
1026  New files:
1027  Requires a few new audios:
1028    1F.gsm: feminine 'una'
1029    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 
1030  */
1031 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)
1032 {
1033         int res = 0;
1034         int playa = 0;
1035         int mf = 0;                            /* +1 = male; -1 = female */
1036         char fn[256] = "";
1037         if (!num) 
1038                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
1039
1040         if (options) {
1041                 if (!strncasecmp(options, "f", 1))
1042                         mf = -1;
1043                 else if (!strncasecmp(options, "m", 1))
1044                         mf = 1;
1045         }
1046
1047         while (!res && num) {
1048                 if (num < 0) {
1049                         ast_copy_string(fn, "digits/minus", sizeof(fn));
1050                         if ( num > INT_MIN ) {
1051                                 num = -num;
1052                         } else {
1053                                 num = 0;
1054                         }       
1055                 } else if (playa) {
1056                         ast_copy_string(fn, "digits/and", sizeof(fn));
1057                         playa = 0;
1058                 } else if (num == 1) {
1059                         if (mf < 0)
1060                                 snprintf(fn, sizeof(fn), "digits/%dF", num);
1061                         else if (mf > 0)
1062                                 snprintf(fn, sizeof(fn), "digits/%dM", num);
1063                         else 
1064                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1065                         num = 0;
1066                 } else if (num < 31) {
1067                         snprintf(fn, sizeof(fn), "digits/%d", num);
1068                         num = 0;
1069                 } else if (num < 100) {
1070                         snprintf(fn, sizeof(fn), "digits/%d", (num/10)*10);
1071                         num %= 10;
1072                         if (num)
1073                                 playa++;
1074                 } else if (num == 100) {
1075                         ast_copy_string(fn, "digits/100", sizeof(fn));
1076                         num = 0;
1077                 } else if (num < 200) {
1078                         ast_copy_string(fn, "digits/100-and", sizeof(fn));
1079                         num -= 100;
1080                 } else {
1081                         if (num < 1000) {
1082                                 snprintf(fn, sizeof(fn), "digits/%d", (num/100)*100);
1083                                 num %= 100;
1084                         } else if (num < 2000) {
1085                                 num %= 1000;
1086                                 ast_copy_string(fn, "digits/thousand", sizeof(fn));
1087                         } else {
1088                                 if (num < 1000000) {
1089                                         res = ast_say_number_full_es(chan, num / 1000, ints, language, options, audiofd, ctrlfd);
1090                                         if (res)
1091                                                 return res;
1092                                         num %= 1000;
1093                                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
1094                                 } else {
1095                                         if (num < 2147483640) {
1096                                                 if ((num/1000000) == 1) {
1097                                                         res = ast_say_number_full_es(chan, num / 1000000, ints, language, "M", audiofd, ctrlfd);
1098                                                         if (res)
1099                                                                 return res;
1100                                                         ast_copy_string(fn, "digits/million", sizeof(fn));
1101                                                 } else {
1102                                                         res = ast_say_number_full_es(chan, num / 1000000, ints, language, options, audiofd, ctrlfd);
1103                                                         if (res)
1104                                                                 return res;
1105                                                         ast_copy_string(fn, "digits/millions", sizeof(fn));
1106                                                 }
1107                                                 num %= 1000000;
1108                                         } else {
1109                                                 ast_debug(1, "Number '%d' is too big for me\n", num);
1110                                                 res = -1;
1111                                         }
1112                                 }
1113                         }
1114                 }
1115
1116                 if (!res) {
1117                         if (!ast_streamfile(chan, fn, language)) {
1118                                 if ((audiofd > -1) && (ctrlfd > -1))
1119                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
1120                                 else
1121                                         res = ast_waitstream(chan, ints);
1122                         }
1123                         ast_stopstream(chan);
1124
1125                 }
1126
1127         }
1128         return res;
1129 }
1130
1131 /*! \brief  ast_say_number_full_fr: French syntax
1132         Extra sounds needed:
1133         1F: feminin 'une'
1134         et: 'and' */
1135 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)
1136 {
1137         int res = 0;
1138         int playh = 0;
1139         int playa = 0;
1140         int mf = 1;                            /* +1 = male; -1 = female */
1141         char fn[256] = "";
1142         if (!num) 
1143                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
1144         
1145         if (options && !strncasecmp(options, "f", 1))
1146                 mf = -1;
1147
1148         while (!res && (num || playh || playa)) {
1149                 if (num < 0) {
1150                         ast_copy_string(fn, "digits/minus", sizeof(fn));
1151                         if ( num > INT_MIN ) {
1152                                 num = -num;
1153                         } else {
1154                                 num = 0;
1155                         }       
1156                 } else if (playh) {
1157                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
1158                         playh = 0;
1159                 } else if (playa) {
1160                         ast_copy_string(fn, "digits/et", sizeof(fn));
1161                         playa = 0;
1162                 } else if (num == 1) {
1163                         if (mf < 0)
1164                                 snprintf(fn, sizeof(fn), "digits/%dF", num);
1165                         else
1166                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1167                         num = 0;
1168                 } else if (num < 21) {
1169                         snprintf(fn, sizeof(fn), "digits/%d", num);
1170                         num = 0;
1171                 } else if (num < 70) {
1172                         snprintf(fn, sizeof(fn), "digits/%d", (num/10)*10);
1173                         if ((num % 10) == 1) playa++;
1174                         num = num % 10;
1175                 } else if (num < 80) {
1176                         ast_copy_string(fn, "digits/60", sizeof(fn));
1177                         if ((num % 10) == 1) playa++;
1178                         num -= 60;
1179                 } else if (num < 100) {
1180                         ast_copy_string(fn, "digits/80", sizeof(fn));
1181                         num = num - 80;
1182                 } else if (num < 200) {
1183                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
1184                         num = num - 100;
1185                 } else if (num < 1000) {
1186                         snprintf(fn, sizeof(fn), "digits/%d", (num/100));
1187                         playh++;
1188                         num = num % 100;
1189                 } else if (num < 2000) {
1190                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
1191                         num = num - 1000;
1192                 } else if (num < 1000000) {
1193                         res = ast_say_number_full_fr(chan, num / 1000, ints, language, options, audiofd, ctrlfd);
1194                         if (res)
1195                                 return res;
1196                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
1197                         num = num % 1000;
1198                 } else  if (num < 1000000000) {
1199                         res = ast_say_number_full_fr(chan, num / 1000000, ints, language, options, audiofd, ctrlfd);
1200                         if (res)
1201                                 return res;
1202                         ast_copy_string(fn, "digits/million", sizeof(fn));
1203                         num = num % 1000000;
1204                 } else {
1205                         ast_debug(1, "Number '%d' is too big for me\n", num);
1206                         res = -1;
1207                 }
1208                 if (!res) {
1209                         if (!ast_streamfile(chan, fn, language)) {
1210                                 if ((audiofd > -1) && (ctrlfd > -1))
1211                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
1212                                 else
1213                                         res = ast_waitstream(chan, ints);
1214                         }
1215                         ast_stopstream(chan);
1216                 }
1217         }
1218         return res;
1219 }
1220
1221
1222
1223 /* Hebrew syntax
1224  * Check doc/lang/hebrew-digits.txt for information about the various
1225  * recordings required to make this translation work properly */
1226 #define SAY_NUM_BUF_SIZE 256
1227 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)
1228 {
1229         int res = 0;
1230         int state = 0;                          /* no need to save anything */
1231         int mf = -1;                            /* +1 = Masculin; -1 = Feminin */
1232         int tmpnum = 0;
1233
1234         char fn[SAY_NUM_BUF_SIZE] = "";
1235
1236         ast_verbose(VERBOSE_PREFIX_3 "ast_say_digits_full: started. num: %d, options=\"%s\"\n", num, options);
1237
1238         if (!num) {
1239                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
1240         }
1241         if (options && !strncasecmp(options, "m", 1)) {
1242                 mf = 1;
1243         }
1244         ast_verbose(VERBOSE_PREFIX_3 "ast_say_digits_full: num: %d, state=%d, options=\"%s\", mf=%d\n", num, state, options, mf);
1245
1246         /* Do we have work to do? */
1247         while (!res && (num || (state > 0))) {
1248                 /* first type of work: play a second sound. In this loop
1249                  * we can only play one sound file at a time. Thus playing
1250                  * a second one requires repeating the loop just for the
1251                  * second file. The variable 'state' remembers where we were.
1252                  * state==0 is the normal mode and it means that we continue
1253                  * to check if the number num has yet anything left.
1254                  */
1255                 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);
1256
1257                 if (state == 1) {
1258                         state = 0;
1259                 } else if (state == 2) {
1260                         if ((num >= 11) && (num < 21)) {
1261                                 if (mf < 0) {
1262                                         snprintf(fn, sizeof(fn), "digits/ve");
1263                                 } else {
1264                                         snprintf(fn, sizeof(fn), "digits/uu");
1265                                 }
1266                         } else {
1267                                 switch (num) {
1268                                 case 1:
1269                                         snprintf(fn, sizeof(fn), "digits/ve");
1270                                         break;
1271                                 case 2:
1272                                         snprintf(fn, sizeof(fn), "digits/uu");
1273                                         break;
1274                                 case 3:
1275                                         if (mf < 0) {
1276                                                 snprintf(fn, sizeof(fn), "digits/ve");
1277                                         } else {
1278                                                 snprintf(fn, sizeof(fn), "digits/uu");
1279                                         }
1280                                         break;
1281                                 case 4:
1282                                         snprintf(fn, sizeof(fn), "digits/ve");
1283                                         break;
1284                                 case 5:
1285                                         snprintf(fn, sizeof(fn), "digits/ve");
1286                                         break;
1287                                 case 6:
1288                                         snprintf(fn, sizeof(fn), "digits/ve");
1289                                         break;
1290                                 case 7:
1291                                         snprintf(fn, sizeof(fn), "digits/ve");
1292                                         break;
1293                                 case 8:
1294                                         snprintf(fn, sizeof(fn), "digits/uu");
1295                                         break;
1296                                 case 9:
1297                                         snprintf(fn, sizeof(fn), "digits/ve");
1298                                         break;
1299                                 case 10:
1300                                         snprintf(fn, sizeof(fn), "digits/ve");
1301                                         break;
1302                                 }
1303                         }
1304                         state = 0;
1305                 } else if (state == 3) {
1306                         snprintf(fn, sizeof(fn), "digits/1k");
1307                         state = 0;
1308                 } else if (num < 0) {
1309                         snprintf(fn, sizeof(fn), "digits/minus");
1310                         num = (-1) * num;
1311                 } else if (num < 20) {
1312                         if (mf < 0) {
1313                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1314                         } else {
1315                                 snprintf(fn, sizeof(fn), "digits/%dm", num);
1316                         }
1317                         num = 0;
1318                 } else if ((num < 100) && (num >= 20)) {
1319                         snprintf(fn, sizeof(fn), "digits/%d", (num / 10) * 10);
1320                         num = num % 10;
1321                         if (num > 0) {
1322                                 state = 2;
1323                         }
1324                 } else if ((num >= 100) && (num < 1000)) {
1325                         tmpnum = num / 100;
1326                         snprintf(fn, sizeof(fn), "digits/%d00", tmpnum);
1327                         num = num - (tmpnum * 100);
1328                         if ((num > 0) && (num < 11)) {
1329                                 state = 2;
1330                         }
1331                 } else if ((num >= 1000) && (num < 10000)) {
1332                         tmpnum = num / 1000;
1333                         snprintf(fn, sizeof(fn), "digits/%dk", tmpnum);
1334                         num = num - (tmpnum * 1000);
1335                         if ((num > 0) && (num < 11)) {
1336                                 state = 2;
1337                         }
1338                 } else if (num < 20000) {
1339                         snprintf(fn, sizeof(fn), "digits/%dm", (num / 1000));
1340                         num = num % 1000;
1341                         state = 3;
1342                 } else if (num < 1000000) {
1343                         res = ast_say_number_full_he(chan, num / 1000, ints, language, "m", audiofd, ctrlfd);
1344                         if (res) {
1345                                 return res;
1346                         }
1347                         snprintf(fn, sizeof(fn), "digits/1k");
1348                         num = num % 1000;
1349                         if ((num > 0) && (num < 11)) {
1350                                 state = 2;
1351                         }
1352                 } else if (num < 2000000) {
1353                         snprintf(fn, sizeof(fn), "digits/million");
1354                         num = num % 1000000;
1355                         if ((num > 0) && (num < 11)) {
1356                                 state = 2;
1357                         }
1358                 } else if (num < 3000000) {
1359                         snprintf(fn, sizeof(fn), "digits/twomillion");
1360                         num = num - 2000000;
1361                         if ((num > 0) && (num < 11)) {
1362                                 state = 2;
1363                         }
1364                 } else if (num < 1000000000) {
1365                         res = ast_say_number_full_he(chan, num / 1000000, ints, language, "m", audiofd, ctrlfd);
1366                         if (res) {
1367                                 return res;
1368                         }
1369                         snprintf(fn, sizeof(fn), "digits/million");
1370                         num = num % 1000000;
1371                         if ((num > 0) && (num < 11)) {
1372                                 state = 2;
1373                         }
1374                 } else {
1375                         ast_debug(1, "Number '%d' is too big for me\n", num);
1376                         res = -1;
1377                 }
1378                 tmpnum = 0;
1379                 if (!res) {
1380                         if (!ast_streamfile(chan, fn, language)) {
1381                                 if ((audiofd > -1) && (ctrlfd > -1)) {
1382                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
1383                                 } else {
1384                                         res = ast_waitstream(chan, ints);
1385                                 }
1386                         }
1387                         ast_stopstream(chan);
1388                 }
1389         }
1390         return res;
1391 }
1392
1393 /*! \brief  ast_say_number_full_hu: Hungarian syntax 
1394
1395   Extra sounds needed:
1396         10en: "tizen"
1397         20on: "huszon"
1398 */
1399 static int ast_say_number_full_hu(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
1400 {
1401         int res = 0;
1402         int playh = 0;
1403         char fn[256] = "";
1404         if (!num) 
1405                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
1406
1407         /*
1408         Hungarian support
1409         like english, except numbers up to 29 are from 2 words.
1410         10 and first word of 1[1-9] and 20 and first word of 2[1-9] are different.
1411         */
1412
1413         while(!res && (num || playh)) {
1414                 if (num < 0) {
1415                         ast_copy_string(fn, "digits/minus", sizeof(fn));
1416                         if ( num > INT_MIN ) {
1417                                 num = -num;
1418                         } else {
1419                                 num = 0;
1420                         }       
1421                 } else if (playh) {
1422                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
1423                         playh = 0;
1424                 } else if (num < 11 || num == 20) {
1425                         snprintf(fn, sizeof(fn), "digits/%d", num);
1426                         num = 0;
1427                 } else if (num < 20) {
1428                         ast_copy_string(fn, "digits/10en", sizeof(fn));
1429                         num -= 10;
1430                 } else if (num < 30) {
1431                         ast_copy_string(fn, "digits/20on", sizeof(fn));
1432                         num -= 20;
1433                 } else  if (num < 100) {
1434                         snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
1435                         num %= 10;
1436                 } else {
1437                         if (num < 1000){
1438                                 snprintf(fn, sizeof(fn), "digits/%d", (num/100));
1439                                 playh++;
1440                                 num %= 100;
1441                         } else {
1442                                 if (num < 1000000) { /* 1,000,000 */
1443                                         res = ast_say_number_full_hu(chan, num / 1000, ints, language, audiofd, ctrlfd);
1444                                         if (res)
1445                                                 return res;
1446                                         num %= 1000;
1447                                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
1448                                 } else {
1449                                         if (num < 1000000000) { /* 1,000,000,000 */
1450                                                 res = ast_say_number_full_hu(chan, num / 1000000, ints, language, audiofd, ctrlfd);
1451                                                 if (res)
1452                                                         return res;
1453                                                 num %= 1000000;
1454                                                 ast_copy_string(fn, "digits/million", sizeof(fn));
1455                                         } else {
1456                                                 ast_debug(1, "Number '%d' is too big for me\n", num);
1457                                                 res = -1;
1458                                         }
1459                                 }
1460                         }
1461                 }
1462                 if (!res) {
1463                         if(!ast_streamfile(chan, fn, language)) {
1464                                 if ((audiofd  > -1) && (ctrlfd > -1))
1465                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
1466                                 else
1467                                         res = ast_waitstream(chan, ints);
1468                         }
1469                         ast_stopstream(chan);
1470                 }
1471         }
1472         return res;
1473 }
1474
1475 /*! \brief  ast_say_number_full_it:  Italian */
1476 static int ast_say_number_full_it(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
1477 {
1478         int res = 0;
1479         int playh = 0;
1480         int tempnum = 0;
1481         char fn[256] = "";
1482
1483         if (!num)
1484                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
1485
1486                 /*
1487                 Italian support
1488
1489                 Like english, numbers up to 20 are a single 'word', and others
1490                 compound, but with exceptions.
1491                 For example 21 is not twenty-one, but there is a single word in 'it'.
1492                 Idem for 28 (ie when a the 2nd part of a compund number
1493                 starts with a vowel)
1494
1495                 There are exceptions also for hundred, thousand and million.
1496                 In english 100 = one hundred, 200 is two hundred.
1497                 In italian 100 = cento , like to say hundred (without one),
1498                 200 and more are like english.
1499                 
1500                 Same applies for thousand:
1501                 1000 is one thousand in en, 2000 is two thousand.
1502                 In it we have 1000 = mille , 2000 = 2 mila 
1503
1504                 For million(s) we use the plural, if more than one
1505                 Also, one million is abbreviated in it, like on-million,
1506                 or 'un milione', not 'uno milione'.
1507                 So the right file is provided.
1508                 */
1509
1510         while (!res && (num || playh)) {
1511                         if (num < 0) {
1512                                 ast_copy_string(fn, "digits/minus", sizeof(fn));
1513                                 if ( num > INT_MIN ) {
1514                                         num = -num;
1515                                 } else {
1516                                         num = 0;
1517                                 }       
1518                         } else if (playh) {
1519                                 ast_copy_string(fn, "digits/hundred", sizeof(fn));
1520                                 playh = 0;
1521                         } else if (num < 20) {
1522                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1523                                 num = 0;
1524                         } else if (num == 21) {
1525                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1526                                 num = 0;
1527                         } else if (num == 28) {
1528                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1529                                 num = 0;
1530                         } else if (num == 31) {
1531                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1532                                 num = 0;
1533                         } else if (num == 38) {
1534                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1535                                 num = 0;
1536                         } else if (num == 41) {
1537                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1538                                 num = 0;
1539                         } else if (num == 48) {
1540                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1541                                 num = 0;
1542                         } else if (num == 51) {
1543                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1544                                 num = 0;
1545                         } else if (num == 58) {
1546                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1547                                 num = 0;
1548                         } else if (num == 61) {
1549                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1550                                 num = 0;
1551                         } else if (num == 68) {
1552                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1553                                 num = 0;
1554                         } else if (num == 71) {
1555                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1556                                 num = 0;
1557                         } else if (num == 78) {
1558                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1559                                 num = 0;
1560                         } else if (num == 81) {
1561                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1562                                 num = 0;
1563                         } else if (num == 88) {
1564                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1565                                 num = 0;
1566                         } else if (num == 91) {
1567                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1568                                 num = 0;
1569                         } else if (num == 98) {
1570                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1571                                 num = 0;
1572                         } else if (num < 100) {
1573                                 snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
1574                                 num %= 10;
1575                         } else {
1576                                 if (num < 1000) {
1577                                         if ((num / 100) > 1) {
1578                                                 snprintf(fn, sizeof(fn), "digits/%d", (num/100));
1579                                                 playh++;
1580                                         } else {
1581                                                 ast_copy_string(fn, "digits/hundred", sizeof(fn));
1582                                         }
1583                                         num %= 100;
1584                                 } else {
1585                                         if (num < 1000000) { /* 1,000,000 */
1586                                                 if ((num/1000) > 1)
1587                                                         res = ast_say_number_full_it(chan, num / 1000, ints, language, audiofd, ctrlfd);
1588                                                 if (res)
1589                                                         return res;
1590                                                 tempnum = num;
1591                                                 num %= 1000;
1592                                                 if ((tempnum / 1000) < 2)
1593                                                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
1594                                                 else /* for 1000 it says mille, for >1000 (eg 2000) says mila */
1595                                                         ast_copy_string(fn, "digits/thousands", sizeof(fn));
1596                                         } else {
1597                                                 if (num < 1000000000) { /* 1,000,000,000 */
1598                                                         if ((num / 1000000) > 1)
1599                                                                 res = ast_say_number_full_it(chan, num / 1000000, ints, language, audiofd, ctrlfd);
1600                                                         if (res)
1601                                                                 return res;
1602                                                         tempnum = num;
1603                                                         num %= 1000000;
1604                                                         if ((tempnum / 1000000) < 2)
1605                                                                 ast_copy_string(fn, "digits/million", sizeof(fn));
1606                                                         else
1607                                                                 ast_copy_string(fn, "digits/millions", sizeof(fn));
1608                                                 } else {
1609                                                         ast_debug(1, "Number '%d' is too big for me\n", num);
1610                                                         res = -1;
1611                                                 }
1612                                         }
1613                                 }
1614                         }
1615                         if (!res) {
1616                                 if (!ast_streamfile(chan, fn, language)) {
1617                                         if ((audiofd > -1) && (ctrlfd > -1))
1618                                                 res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
1619                                         else
1620                                                 res = ast_waitstream(chan, ints);
1621                                 }
1622                                 ast_stopstream(chan);
1623                         }
1624                 }
1625         return res;
1626 }
1627
1628 /*! \brief  ast_say_number_full_nl: dutch syntax 
1629  * New files: digits/nl-en
1630  */
1631 static int ast_say_number_full_nl(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
1632 {
1633         int res = 0;
1634         int playh = 0;
1635         int units = 0;
1636         char fn[256] = "";
1637         if (!num) 
1638                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
1639         while (!res && (num || playh )) {
1640                 if (num < 0) {
1641                         ast_copy_string(fn, "digits/minus", sizeof(fn));
1642                         if ( num > INT_MIN ) {
1643                                 num = -num;
1644                         } else {
1645                                 num = 0;
1646                         }       
1647                 } else if (playh) {
1648                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
1649                         playh = 0;
1650                 } else if (num < 20) {
1651                         snprintf(fn, sizeof(fn), "digits/%d", num);
1652                         num = 0;
1653                 } else if (num < 100) {
1654                         units = num % 10;
1655                         if (units > 0) {
1656                                 res = ast_say_number_full_nl(chan, units, ints, language, audiofd, ctrlfd);
1657                                 if (res)
1658                                         return res;
1659                                 num = num - units;
1660                                 ast_copy_string(fn, "digits/nl-en", sizeof(fn));
1661                         } else {
1662                                 snprintf(fn, sizeof(fn), "digits/%d", num - units);
1663                                 num = 0;
1664                         }
1665                 } else if (num < 200) {
1666                         /* hundred, not one-hundred */
1667                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
1668                         num %= 100;
1669                 } else if (num < 1000) {
1670                         snprintf(fn, sizeof(fn), "digits/%d", num / 100);
1671                         playh++;
1672                         num %= 100;
1673                 } else {
1674                         if (num < 1100) {
1675                                 /* thousand, not one-thousand */
1676                                 num %= 1000;
1677                                 ast_copy_string(fn, "digits/thousand", sizeof(fn));
1678                         } else if (num < 10000) { /* 1,100 to 9,9999 */
1679                                 res = ast_say_number_full_nl(chan, num / 100, ints, language, audiofd, ctrlfd);
1680                                 if (res)
1681                                         return res;
1682                                 num %= 100;
1683                                 ast_copy_string(fn, "digits/hundred", sizeof(fn));
1684                         } else {
1685                                 if (num < 1000000) { /* 1,000,000 */
1686                                         res = ast_say_number_full_nl(chan, num / 1000, ints, language, audiofd, ctrlfd);
1687                                         if (res)
1688                                                 return res;
1689                                         num %= 1000;
1690                                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
1691                                 } else {
1692                                         if (num < 1000000000) { /* 1,000,000,000 */
1693                                                 res = ast_say_number_full_nl(chan, num / 1000000, ints, language, audiofd, ctrlfd);
1694                                                 if (res)
1695                                                         return res;
1696                                                 num %= 1000000;
1697                                                 ast_copy_string(fn, "digits/million", sizeof(fn));
1698                                         } else {
1699                                                 ast_debug(1, "Number '%d' is too big for me\n", num);
1700                                                 res = -1;
1701                                         }
1702                                 }
1703                         }
1704                 }
1705
1706                 if (!res) {
1707                         if (!ast_streamfile(chan, fn, language)) {
1708                                 if ((audiofd > -1) && (ctrlfd > -1))
1709                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
1710                                 else
1711                                         res = ast_waitstream(chan, ints);
1712                         }
1713                         ast_stopstream(chan);
1714                 }
1715         }
1716         return res;
1717 }
1718
1719 /*! \brief  ast_say_number_full_no: Norwegian syntax 
1720  * New files:
1721  * In addition to American English, the following sounds are required:  "and", "1N"
1722  *
1723  * The grammar for Norwegian numbers is the same as for English except
1724  * for the following:
1725  * - 1 exists in both commune ("en", file "1") and neuter ("ett", file "1N")
1726  *   "and" before the last two digits, i.e. 2034 is "two thousand and
1727  *   thirty-four" and 1000012 is "one million and twelve".
1728  */
1729 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)
1730 {
1731         int res = 0;
1732         int playh = 0;
1733         int playa = 0;
1734         int cn = 1;             /* +1 = commune; -1 = neuter */
1735         char fn[256] = "";
1736         
1737         if (!num) 
1738                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
1739         
1740         if (options && !strncasecmp(options, "n", 1)) cn = -1;
1741
1742         while (!res && (num || playh || playa )) {
1743                 if (num < 0) {
1744                         ast_copy_string(fn, "digits/minus", sizeof(fn));
1745                         if ( num > INT_MIN ) {
1746                                 num = -num;
1747                         } else {
1748                                 num = 0;
1749                         }       
1750                 } else if (playh) {
1751                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
1752                         playh = 0;
1753                 } else if (playa) {
1754                         ast_copy_string(fn, "digits/and", sizeof(fn));
1755                         playa = 0;
1756                 } else if (num == 1 && cn == -1) {
1757                         ast_copy_string(fn, "digits/1N", sizeof(fn));
1758                         num = 0;
1759                 } else if (num < 20) {
1760                         snprintf(fn, sizeof(fn), "digits/%d", num);
1761                         num = 0;
1762                 } else if (num < 100) {
1763                         snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
1764                         num %= 10;
1765                 } else if (num < 1000) {
1766                         int hundreds = num / 100;
1767                         if (hundreds == 1)
1768                                 ast_copy_string(fn, "digits/1N", sizeof(fn));
1769                         else
1770                                 snprintf(fn, sizeof(fn), "digits/%d", (num / 100));
1771
1772                         playh++;
1773                         num -= 100 * hundreds;
1774                         if (num)
1775                                 playa++;
1776                 } else if (num < 1000000) {
1777                         res = ast_say_number_full_no(chan, num / 1000, ints, language, "n", audiofd, ctrlfd);
1778                         if (res)
1779                                 return res;
1780                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
1781                         num %= 1000;
1782                         if (num && num < 100)
1783                                 playa++;
1784                 } else if (num < 1000000000) {
1785                                 int millions = num / 1000000;
1786                                 res = ast_say_number_full_no(chan, millions, ints, language, "c", audiofd, ctrlfd);
1787                                 if (res)
1788                                         return res;
1789                                 ast_copy_string(fn, "digits/million", sizeof(fn));
1790                                 num %= 1000000;
1791                                 if (num && num < 100)
1792                                         playa++;
1793                 } else {
1794                                 ast_debug(1, "Number '%d' is too big for me\n", num);
1795                                 res = -1;
1796                 }
1797
1798                 if (!res) {
1799                         if (!ast_streamfile(chan, fn, language)) {
1800                                 if ((audiofd > -1) && (ctrlfd > -1))
1801                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
1802                                 else
1803                                         res = ast_waitstream(chan, ints);
1804                         }
1805                         ast_stopstream(chan);
1806                 }
1807         }
1808         return res;
1809 }
1810
1811 typedef struct {  
1812         char *separator_dziesiatek;
1813         char *cyfry[10];
1814         char *cyfry2[10];
1815         char *setki[10];
1816         char *dziesiatki[10];
1817         char *nastki[10];  
1818         char *rzedy[3][3];
1819 } odmiana;
1820
1821 static char *pl_rzad_na_tekst(odmiana *odm, int i, int rzad)
1822 {
1823         if (rzad==0)
1824                 return "";
1825  
1826         if (i==1)
1827                 return odm->rzedy[rzad - 1][0];
1828         if ((i > 21 || i < 11) &&  i%10 > 1 && i%10 < 5)
1829                 return odm->rzedy[rzad - 1][1];
1830         else
1831                 return odm->rzedy[rzad - 1][2];
1832 }
1833
1834 static char* pl_append(char* buffer, char* str)
1835 {
1836         strcpy(buffer, str);
1837         buffer += strlen(str);
1838         return buffer;
1839 }
1840
1841 static void pl_odtworz_plik(struct ast_channel *chan, const char *language, int audiofd, int ctrlfd, const char *ints, char *fn)
1842 {
1843         char file_name[255] = "digits/";
1844         strcat(file_name, fn);
1845         ast_debug(1, "Trying to play: %s\n", file_name);
1846         if (!ast_streamfile(chan, file_name, language)) {
1847                 if ((audiofd > -1) && (ctrlfd > -1))
1848                         ast_waitstream_full(chan, ints, audiofd, ctrlfd);
1849                 else
1850                         ast_waitstream(chan, ints);
1851         }
1852         ast_stopstream(chan);
1853 }
1854
1855 static void powiedz(struct ast_channel *chan, const char *language, int audiofd, int ctrlfd, const char *ints, odmiana *odm, int rzad, int i)
1856 {
1857         /* Initialise variables to allow compilation on Debian-stable, etc */
1858         int m1000E6 = 0;
1859         int i1000E6 = 0;
1860         int m1000E3 = 0;
1861         int i1000E3 = 0;
1862         int m1000 = 0;
1863         int i1000 = 0;
1864         int m100 = 0;
1865         int i100 = 0;
1866         
1867         if (i == 0 && rzad > 0) { 
1868                 return;
1869         }
1870         if (i == 0) {
1871                 pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->cyfry[0]);
1872                 return;
1873         }
1874
1875         m1000E6 = i % 1000000000;
1876         i1000E6 = i / 1000000000;
1877
1878         powiedz(chan, language, audiofd, ctrlfd, ints, odm, rzad+3, i1000E6);
1879
1880         m1000E3 = m1000E6 % 1000000;
1881         i1000E3 = m1000E6 / 1000000;
1882
1883         powiedz(chan, language, audiofd, ctrlfd, ints, odm, rzad+2, i1000E3);
1884
1885         m1000 = m1000E3 % 1000;
1886         i1000 = m1000E3 / 1000;
1887
1888         powiedz(chan, language, audiofd, ctrlfd, ints, odm, rzad+1, i1000);
1889
1890         m100 = m1000 % 100;
1891         i100 = m1000 / 100;
1892         
1893         if (i100>0)
1894                 pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->setki[i100]);
1895
1896         if ( m100 > 0 && m100 <=9 ) {
1897                 if (m1000>0)
1898                         pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->cyfry2[m100]);
1899                 else
1900                         pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->cyfry[m100]);
1901         } else if (m100 % 10 == 0) {
1902                 pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->dziesiatki[m100 / 10]);
1903         } else if (m100 <= 19 ) {
1904                 pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->nastki[m100 % 10]);
1905         } else if (m100 != 0) {
1906                 if (odm->separator_dziesiatek[0]==' ') {
1907                         pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->dziesiatki[m100 / 10]);
1908                         pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->cyfry2[m100 % 10]);
1909                 } else {
1910                         char buf[10];
1911                         char *b = buf;
1912                         b = pl_append(b, odm->dziesiatki[m100 / 10]);  
1913                         b = pl_append(b, odm->separator_dziesiatek);  
1914                         b = pl_append(b, odm->cyfry2[m100 % 10]); 
1915                         pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, buf);
1916                 }
1917         } 
1918
1919         if (rzad > 0) {
1920                 pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, pl_rzad_na_tekst(odm, i, rzad));
1921         }
1922 }
1923
1924 /* ast_say_number_full_pl: Polish syntax 
1925
1926 Sounds needed:
1927 0               zero
1928 1               jeden
1929 10              dziesiec
1930 100             sto
1931 1000            tysiac
1932 1000000         milion
1933 1000000000      miliard
1934 1000000000.2    miliardy
1935 1000000000.5    miliardow
1936 1000000.2       miliony
1937 1000000.5       milionow
1938 1000.2          tysiace
1939 1000.5          tysiecy
1940 100m            stu
1941 10m             dziesieciu
1942 11              jedenascie
1943 11m             jedenastu
1944 12              dwanascie
1945 12m             dwunastu
1946 13              trzynascie
1947 13m             trzynastu
1948 14              czternascie
1949 14m             czternastu
1950 15              pietnascie
1951 15m             pietnastu
1952 16              szesnascie
1953 16m             szesnastu
1954 17              siedemnascie
1955 17m             siedemnastu
1956 18              osiemnascie
1957 18m             osiemnastu
1958 19              dziewietnascie
1959 19m             dziewietnastu
1960 1z              jedna
1961 2               dwa
1962 20              dwadziescia
1963 200             dwiescie
1964 200m            dwustu
1965 20m             dwudziestu
1966 2-1m            dwaj
1967 2-2m            dwoch
1968 2z              dwie
1969 3               trzy
1970 30              trzydziesci
1971 300             trzysta
1972 300m            trzystu
1973 30m             trzydziestu
1974 3-1m            trzej
1975 3-2m            trzech
1976 4               cztery
1977 40              czterdziesci
1978 400             czterysta
1979 400m            czterystu
1980 40m             czterdziestu
1981 4-1m            czterej
1982 4-2m            czterech
1983 5               piec
1984 50              piecdziesiat
1985 500             piecset
1986 500m            pieciuset
1987 50m             piedziesieciu
1988 5m              pieciu
1989 6               szesc
1990 60              szescdziesiat
1991 600             szescset
1992 600m            szesciuset
1993 60m             szescdziesieciu
1994 6m              szesciu
1995 7               siedem
1996 70              siedemdziesiat
1997 700             siedemset
1998 700m            siedmiuset
1999 70m             siedemdziesieciu
2000 7m              siedmiu
2001 8               osiem
2002 80              osiemdziesiat
2003 800             osiemset
2004 800m            osmiuset
2005 80m             osiemdziesieciu
2006 8m              osmiu
2007 9               dziewiec
2008 90              dziewiecdziesiat
2009 900             dziewiecset
2010 900m            dziewieciuset
2011 90m             dziewiedziesieciu
2012 9m              dziewieciu
2013 and combinations of eg.: 20_1, 30m_3m, etc...
2014
2015 */
2016 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)
2017 {
2018         char *zenski_cyfry[] = {"0", "1z", "2z", "3", "4", "5", "6", "7", "8", "9"};
2019
2020         char *zenski_cyfry2[] = {"0", "1", "2z", "3", "4", "5", "6", "7", "8", "9"};
2021
2022         char *meski_cyfry[] = {"0", "1", "2-1m", "3-1m", "4-1m", "5m",  /*"2-1mdwaj"*/ "6m", "7m", "8m", "9m"};
2023
2024         char *meski_cyfry2[] = {"0", "1", "2-2m", "3-2m", "4-2m", "5m", "6m", "7m", "8m", "9m"};
2025
2026         char *meski_setki[] = {"", "100m", "200m", "300m", "400m", "500m", "600m", "700m", "800m", "900m"};
2027
2028         char *meski_dziesiatki[] = {"", "10m", "20m", "30m", "40m", "50m", "60m", "70m", "80m", "90m"};
2029
2030         char *meski_nastki[] = {"", "11m", "12m", "13m", "14m", "15m", "16m", "17m", "18m", "19m"};
2031
2032         char *nijaki_cyfry[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
2033
2034         char *nijaki_cyfry2[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
2035
2036         char *nijaki_setki[] = {"", "100", "200", "300", "400", "500", "600", "700", "800", "900"};
2037
2038         char *nijaki_dziesiatki[] = {"", "10", "20", "30", "40", "50", "60", "70", "80", "90"};
2039
2040         char *nijaki_nastki[] = {"", "11", "12", "13", "14", "15", "16", "17", "18", "19"};
2041
2042         char *rzedy[][3] = { {"1000", "1000.2", "1000.5"}, {"1000000", "1000000.2", "1000000.5"}, {"1000000000", "1000000000.2", "1000000000.5"}}; 
2043
2044         /* Initialise variables to allow compilation on Debian-stable, etc */
2045         odmiana *o;
2046
2047         static odmiana *odmiana_nieosobowa = NULL; 
2048         static odmiana *odmiana_meska = NULL; 
2049         static odmiana *odmiana_zenska = NULL; 
2050
2051         if (odmiana_nieosobowa == NULL) {
2052                 odmiana_nieosobowa = ast_malloc(sizeof(*odmiana_nieosobowa));
2053
2054                 odmiana_nieosobowa->separator_dziesiatek = " ";
2055
2056                 memcpy(odmiana_nieosobowa->cyfry, nijaki_cyfry, sizeof(odmiana_nieosobowa->cyfry));
2057                 memcpy(odmiana_nieosobowa->cyfry2, nijaki_cyfry2, sizeof(odmiana_nieosobowa->cyfry));
2058                 memcpy(odmiana_nieosobowa->setki, nijaki_setki, sizeof(odmiana_nieosobowa->setki));
2059                 memcpy(odmiana_nieosobowa->dziesiatki, nijaki_dziesiatki, sizeof(odmiana_nieosobowa->dziesiatki));
2060                 memcpy(odmiana_nieosobowa->nastki, nijaki_nastki, sizeof(odmiana_nieosobowa->nastki));
2061                 memcpy(odmiana_nieosobowa->rzedy, rzedy, sizeof(odmiana_nieosobowa->rzedy));
2062         }
2063
2064         if (odmiana_zenska == NULL) {
2065                 odmiana_zenska = ast_malloc(sizeof(*odmiana_zenska));
2066
2067                 odmiana_zenska->separator_dziesiatek = " ";
2068
2069                 memcpy(odmiana_zenska->cyfry, zenski_cyfry, sizeof(odmiana_zenska->cyfry));
2070                 memcpy(odmiana_zenska->cyfry2, zenski_cyfry2, sizeof(odmiana_zenska->cyfry));
2071                 memcpy(odmiana_zenska->setki, nijaki_setki, sizeof(odmiana_zenska->setki));
2072                 memcpy(odmiana_zenska->dziesiatki, nijaki_dziesiatki, sizeof(odmiana_zenska->dziesiatki));
2073                 memcpy(odmiana_zenska->nastki, nijaki_nastki, sizeof(odmiana_zenska->nastki));
2074                 memcpy(odmiana_zenska->rzedy, rzedy, sizeof(odmiana_zenska->rzedy));
2075         }
2076
2077         if (odmiana_meska == NULL) {
2078                 odmiana_meska = ast_malloc(sizeof(*odmiana_meska));
2079
2080                 odmiana_meska->separator_dziesiatek = " ";
2081
2082                 memcpy(odmiana_meska->cyfry, meski_cyfry, sizeof(odmiana_meska->cyfry));
2083                 memcpy(odmiana_meska->cyfry2, meski_cyfry2, sizeof(odmiana_meska->cyfry));
2084                 memcpy(odmiana_meska->setki, meski_setki, sizeof(odmiana_meska->setki));
2085                 memcpy(odmiana_meska->dziesiatki, meski_dziesiatki, sizeof(odmiana_meska->dziesiatki));
2086                 memcpy(odmiana_meska->nastki, meski_nastki, sizeof(odmiana_meska->nastki));
2087                 memcpy(odmiana_meska->rzedy, rzedy, sizeof(odmiana_meska->rzedy));
2088         }
2089
2090         if (options) {
2091                 if (strncasecmp(options, "f", 1) == 0)
2092                         o = odmiana_zenska;
2093                 else if (strncasecmp(options, "m", 1) == 0)
2094                         o = odmiana_meska;
2095                 else
2096                         o = odmiana_nieosobowa;
2097         } else
2098                 o = odmiana_nieosobowa;
2099
2100         powiedz(chan, language, audiofd, ctrlfd, ints, o, 0, num);
2101         return 0;
2102 }
2103
2104 /* ast_say_number_full_pt: Portuguese syntax 
2105
2106  *      Extra sounds needed:
2107  *      For feminin all sound files ends with F
2108  *      100E for 100+ something
2109  *      1000000S for plural
2110  *      pt-e for 'and' 
2111  */
2112 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)
2113 {
2114         int res = 0;
2115         int playh = 0;
2116         int mf = 1;                            /* +1 = male; -1 = female */
2117         char fn[256] = "";
2118
2119         if (!num) 
2120                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
2121
2122         if (options && !strncasecmp(options, "f", 1))
2123                 mf = -1;
2124
2125         while (!res && num ) {
2126                 if (num < 0) {
2127                         ast_copy_string(fn, "digits/minus", sizeof(fn));
2128                         if ( num > INT_MIN ) {
2129                                 num = -num;
2130                         } else {
2131                                 num = 0;
2132                         }       
2133                 } else if (num < 20) {
2134                         if ((num == 1 || num == 2) && (mf < 0))
2135                                 snprintf(fn, sizeof(fn), "digits/%dF", num);
2136                         else
2137                                 snprintf(fn, sizeof(fn), "digits/%d", num);
2138                         num = 0;
2139                 } else if (num < 100) {
2140                         snprintf(fn, sizeof(fn), "digits/%d", (num / 10) * 10);
2141                         if (num % 10)
2142                                 playh = 1;
2143                         num = num % 10;
2144                 } else if (num < 1000) {
2145                         if (num == 100)
2146                                 ast_copy_string(fn, "digits/100", sizeof(fn));
2147                         else if (num < 200)
2148                                 ast_copy_string(fn, "digits/100E", sizeof(fn));
2149                         else {
2150                                 if (mf < 0 && num > 199)
2151                                         snprintf(fn, sizeof(fn), "digits/%dF", (num / 100) * 100);
2152                                 else
2153                                         snprintf(fn, sizeof(fn), "digits/%d", (num / 100) * 100);
2154                                 if (num % 100)
2155                                         playh = 1;
2156                         }
2157                         num = num % 100;
2158                 } else if (num < 1000000) {
2159                         if (num > 1999) {
2160                                 res = ast_say_number_full_pt(chan, (num / 1000) * mf, ints, language, options, audiofd, ctrlfd);
2161                                 if (res)
2162                                         return res;
2163                         }
2164                         ast_copy_string(fn, "digits/1000", sizeof(fn));
2165                         if ((num % 1000) && ((num % 1000) < 100  || !(num % 100)))
2166                                 playh = 1;
2167                         num = num % 1000;
2168                 } else if (num < 1000000000) {
2169                         res = ast_say_number_full_pt(chan, (num / 1000000), ints, language, options, audiofd, ctrlfd );
2170                         if (res)
2171                                 return res;
2172                         if (num < 2000000)
2173                                 ast_copy_string(fn, "digits/1000000", sizeof(fn));
2174                         else
2175                                 ast_copy_string(fn, "digits/1000000S", sizeof(fn));
2176  
2177                         if ((num % 1000000) &&
2178                                 /* no thousands */
2179                                 ((!((num / 1000) % 1000) && ((num % 1000) < 100 || !(num % 100))) ||
2180                                 /* no hundreds and below */
2181                                 (!(num % 1000) && (((num / 1000) % 1000) < 100 || !((num / 1000) % 100))) ) )
2182                                 playh = 1;
2183                         num = num % 1000000;
2184                 } else {
2185                         /* number is too big */
2186                         ast_log(LOG_WARNING, "Number '%d' is too big to say.", num);
2187                         res = -1;
2188                 }
2189                 if (!res) {
2190                         if (!ast_streamfile(chan, fn, language)) {
2191                                 if ((audiofd > -1) && (ctrlfd > -1))
2192                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd); 
2193                                 else
2194                                         res = ast_waitstream(chan, ints);
2195                         }
2196                         ast_stopstream(chan);
2197                 }
2198                 if (!res && playh) {
2199                         res = wait_file(chan, ints, "digits/pt-e", language);
2200                         ast_stopstream(chan);
2201                         playh = 0;
2202                 }
2203         }
2204         return res;
2205 }
2206
2207 /*! \brief  ast_say_number_full_se: Swedish syntax 
2208
2209  Sound files needed
2210  - 1N
2211 */
2212 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)
2213 {
2214         int playh = 0;
2215         int start = 1;
2216         char fn[256] = "";
2217         int cn = 1;             /* +1 = commune; -1 = neuter */
2218         int res = 0;
2219
2220         if (!num) {
2221                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
2222         }
2223         if (options && !strncasecmp(options, "n", 1)) cn = -1;
2224
2225         while (num || playh) {
2226                 if (num < 0) {
2227                         ast_copy_string(fn, "digits/minus", sizeof(fn));
2228                         if ( num > INT_MIN ) {
2229                                 num = -num;
2230                         } else {
2231                                 num = 0;
2232                         }
2233                 } else if (playh) {
2234                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
2235                         playh = 0;
2236                 } else if (start  && num < 200 && num > 99 && cn == -1) {
2237                         /* Don't say "en hundra" just say "hundra". */
2238                         snprintf(fn, sizeof(fn), "digits/hundred");
2239                         num -= 100;
2240                 } else if (num == 1 && cn == -1) {      /* En eller ett? */
2241                         ast_copy_string(fn, "digits/1N", sizeof(fn));
2242                         num = 0;
2243                 } else if (num < 20) {
2244                         snprintf(fn, sizeof(fn), "digits/%d", num);
2245                         num = 0;
2246                 } else if (num < 100) { /* Below hundreds - teens and tens */
2247                         snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
2248                         num %= 10;
2249                 } else if (num < 1000) {
2250                         /* Hundreds */
2251                         snprintf(fn, sizeof(fn), "digits/%d", (num/100));
2252                         playh++;
2253                         num %= 100;
2254                 } else if (num < 1000000) { /* 1,000,000 */
2255                         /* Always say "ett hundra tusen", not "en hundra tusen" */
2256                         res = ast_say_number_full_se(chan, num / 1000, ints, language, "c", audiofd, ctrlfd);
2257                         if (res) {
2258                                 return res;
2259                         }
2260                         num %= 1000;
2261                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
2262                 } else if (num < 1000000000) {  /* 1,000,000,000 */
2263                         /* Always say "en miljon", not "ett miljon" */
2264                         res = ast_say_number_full_se(chan, num / 1000000, ints, language, "n", audiofd, ctrlfd);
2265                         if (res) {
2266                                 return res;
2267                         }
2268                         num %= 1000000;
2269                         ast_copy_string(fn, "digits/million", sizeof(fn));
2270                 } else {        /* Miljarder - Billions */
2271                         ast_debug(1, "Number '%d' is too big for me\n", num);
2272                         return -1;
2273                 }
2274
2275                 if (!ast_streamfile(chan, fn, language)) {
2276                         if ((audiofd > -1) && (ctrlfd > -1)) {
2277                                 res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
2278                         } else {
2279                                 res = ast_waitstream(chan, ints);
2280                         }
2281                         ast_stopstream(chan);
2282                         if (res) {
2283                                 return res;
2284                         }
2285                 }
2286                 start = 0;
2287         }
2288         return 0;
2289 }
2290
2291 /*! \brief  ast_say_number_full_zh: Taiwanese / Chinese syntax */
2292 static int ast_say_number_full_zh(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
2293 {
2294         int res = 0;
2295         int playh = 0;
2296         int playt = 0;
2297         int playz = 0;
2298         int last_length = 0;
2299         char buf[20] = "";
2300         char fn[256] = "";
2301         if (!num)
2302                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
2303
2304         while (!res && (num || playh || playt || playz)) {
2305                         if (num < 0) {
2306                                 ast_copy_string(fn, "digits/minus", sizeof(fn));
2307                                 if ( num > INT_MIN ) {
2308                                         num = -num;
2309                                 } else {
2310                                         num = 0;
2311                                 }       
2312                         } else if (playz) {
2313                                 snprintf(fn, sizeof(fn), "digits/0");
2314                                 last_length = 0;
2315                                 playz = 0;
2316                         } else if (playh) {
2317                                 ast_copy_string(fn, "digits/hundred", sizeof(fn));
2318                                 playh = 0;
2319                         } else if (playt) {
2320                                 snprintf(fn, sizeof(fn), "digits/thousand");
2321                                 playt = 0;
2322                         } else  if (num < 10) {
2323                                 snprintf(buf, 10, "%d", num);
2324                                 if (last_length - strlen(buf) > 1 && last_length != 0) {
2325                                         last_length = strlen(buf);
2326                                         playz++;
2327                                         continue;
2328                                 }
2329                                 snprintf(fn, sizeof(fn), "digits/%d", num);
2330                                 num = 0;
2331                         } else  if (num < 100) {
2332                                 snprintf(buf, 10, "%d", num);
2333                                 if (last_length - strlen(buf) > 1 && last_length != 0) {
2334                                         last_length = strlen(buf);
2335                                         playz++;
2336                                         continue;
2337                                 }
2338                                 last_length = strlen(buf);
2339                                 snprintf(fn, sizeof(fn), "digits/%d", (num / 10) * 10);
2340                                 num %= 10;
2341                         } else {
2342                                 if (num < 1000){
2343                                         snprintf(buf, 10, "%d", num);
2344                                         if (last_length - strlen(buf) > 1 && last_length != 0) {
2345                                                 last_length = strlen(buf);
2346                                                 playz++;
2347                                                 continue;
2348                                         }
2349                                         snprintf(fn, sizeof(fn), "digits/%d", (num / 100));
2350                                         playh++;
2351                                         snprintf(buf, 10, "%d", num);
2352                                         ast_debug(1, "Number '%d' %d %d\n", num, (int)strlen(buf), last_length);
2353                                         last_length = strlen(buf);
2354                                         num -= ((num / 100) * 100);
2355                                 } else if (num < 10000){
2356                                         snprintf(buf, 10, "%d", num);
2357                                         snprintf(fn, sizeof(fn), "digits/%d", (num / 1000));
2358                                         playt++;
2359                                         snprintf(buf, 10, "%d", num);
2360                                         ast_debug(1, "Number '%d' %d %d\n", num, (int)strlen(buf), last_length);
2361                                         last_length = strlen(buf);
2362                                         num -= ((num / 1000) * 1000);
2363                                 } else if (num < 100000000) { /* 100,000,000 */
2364                                                 res = ast_say_number_full_zh(chan, num / 10000, ints, language, audiofd, ctrlfd);
2365                                                 if (res)
2366                                                         return res;
2367                                                 snprintf(buf, 10, "%d", num);
2368                                                 ast_debug(1, "Number '%d' %d %d\n", num, (int)strlen(buf), last_length);
2369                                                 num -= ((num / 10000) * 10000);
2370                                                 last_length = strlen(buf);
2371                                                 snprintf(fn, sizeof(fn), "digits/wan");
2372                                 } else {
2373                                         if (num < 1000000000) { /* 1,000,000,000 */
2374                                                 res = ast_say_number_full_zh(chan, num / 100000000, ints, language, audiofd, ctrlfd);
2375                                                 if (res)
2376                                                         return res;
2377                                                 snprintf(buf, 10, "%d", num);
2378                                                 ast_debug(1, "Number '%d' %d %d\n", num, (int)strlen(buf), last_length);
2379                                                 last_length = strlen(buf);
2380                                                 num -= ((num / 100000000) * 100000000);
2381                                                 snprintf(fn, sizeof(fn), "digits/yi");
2382                                         } else {
2383                                                 ast_debug(1, "Number '%d' is too big for me\n", num);
2384                                                 res = -1;
2385                                         }
2386                                 }
2387                         }
2388                         if (!res) {
2389                                 if (!ast_streamfile(chan, fn, language)) {
2390                                         if ((audiofd > -1) && (ctrlfd > -1))
2391                                                 res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
2392                                         else
2393                                                 res = ast_waitstream(chan, ints);
2394                                 }
2395                                 ast_stopstream(chan);
2396                         }
2397         }
2398         return res;
2399 }
2400
2401 /*!\internal
2402  * \brief Counting in Urdu, the national language of Pakistan
2403  * \since 1.8
2404  */
2405 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)
2406 {
2407         int res = 0;
2408         int playh = 0;
2409         char fn[256] = "";
2410
2411         if (!num) {
2412                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
2413         }
2414
2415         while (!res && (num || playh)) {
2416                 if (playh) {
2417                         snprintf(fn, sizeof(fn), "digits/hundred");
2418                         playh = 0;
2419                 } else if (num < 100) {
2420                         snprintf(fn, sizeof(fn), "digits/%d", num);
2421                         num = 0;
2422                 } else if (num < 1000) {
2423                         snprintf(fn, sizeof(fn), "digits/%d", (num / 100));
2424                         playh++;
2425                         num -= ((num / 100) * 100);
2426                 } else if (num < 100000) { /* 1,00,000 */
2427                         if ((res = ast_say_number_full_ur(chan, num / 1000, ints, language, options, audiofd, ctrlfd))) {
2428                                 return res;
2429                         }
2430                         num = num % 1000;
2431                         snprintf(fn, sizeof(fn), "digits/thousand");
2432                 } else if (num < 10000000) { /* 1,00,00,000 */
2433                         if ((res = ast_say_number_full_ur(chan, num / 100000, ints, language, options, audiofd, ctrlfd))) {
2434                                 return res;
2435                         }
2436                         num = num % 100000;
2437                         snprintf(fn, sizeof(fn), "digits/lac");
2438                 } else if (num < 1000000000) { /* 1,00,00,00,000 */
2439                         if ((res = ast_say_number_full_ur(chan, num / 10000000, ints, language, options, audiofd, ctrlfd))) {
2440                                 return res;
2441                         }
2442                         num = num % 10000000;
2443                         snprintf(fn, sizeof(fn), "digits/crore");
2444                 } else {
2445                         ast_debug(1, "Number '%d' is too big for me\n", num);
2446                         res = -1;
2447                 }
2448
2449                 if (!res) {
2450                         if (!ast_streamfile(chan, fn, language)) {
2451                                 if ((audiofd > -1) && (ctrlfd > -1)) {
2452                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
2453                                 } else {
2454                                         res = ast_waitstream(chan, ints);
2455                                 }
2456                         }
2457                         ast_stopstream(chan);
2458                 }
2459         }
2460         return res;
2461 }
2462
2463 /*! \brief  determine last digits for thousands/millions (ru) */
2464 static int get_lastdigits_ru(int num) {
2465         if (num < 20) {
2466                 return num;
2467         } else if (num < 100) {
2468                 return get_lastdigits_ru(num % 10);
2469         } else if (num < 1000) {
2470                 return get_lastdigits_ru(num % 100);
2471         }
2472         return 0;       /* number too big */
2473 }
2474
2475
2476 /*! \brief  ast_say_number_full_ru: Russian syntax 
2477
2478  additional files:
2479         n00.gsm                 (one hundred, two hundred, ...)
2480         thousand.gsm
2481         million.gsm
2482         thousands-i.gsm         (tisyachi)
2483         million-a.gsm           (milliona)
2484         thousands.gsm
2485         millions.gsm
2486         1f.gsm                  (odna)
2487         2f.gsm                  (dve)
2488
2489         where 'n' from 1 to 9
2490 */
2491 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)
2492 {
2493         int res = 0;
2494         int lastdigits = 0;
2495         char fn[256] = "";
2496         if (!num) 
2497                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
2498
2499         while (!res && (num)) {
2500                 if (num < 0) {
2501                         ast_copy_string(fn, "digits/minus", sizeof(fn));
2502                         if ( num > INT_MIN ) {
2503                                 num = -num;
2504                         } else {
2505                                 num = 0;
2506                         }       
2507                 } else  if (num < 20) {
2508                         if (options && strlen(options) == 1 && num < 3) {
2509                             snprintf(fn, sizeof(fn), "digits/%d%s", num, options);
2510                         } else {
2511                                 snprintf(fn, sizeof(fn), "digits/%d", num);
2512                         }
2513                         num = 0;
2514                 } else if (num < 100) {
2515                         snprintf(fn, sizeof(fn), "digits/%d", num - (num % 10));
2516                         num %= 10;
2517                 } else if (num < 1000){
2518                         snprintf(fn, sizeof(fn), "digits/%d", num - (num % 100));
2519                         num %= 100;
2520                 } else if (num < 1000000) { /* 1,000,000 */
2521                         lastdigits = get_lastdigits_ru(num / 1000);
2522                         /* say thousands */
2523                         if (lastdigits < 3) {
2524                                 res = ast_say_number_full_ru(chan, num / 1000, ints, language, "f", audiofd, ctrlfd);
2525                         } else {
2526                                 res = ast_say_number_full_ru(chan, num / 1000, ints, language, NULL, audiofd, ctrlfd);
2527                         }
2528                         if (res)
2529                                 return res;
2530                         if (lastdigits == 1) {
2531                                 ast_copy_string(fn, "digits/thousand", sizeof(fn));
2532                         } else if (lastdigits > 1 && lastdigits < 5) {
2533                                 ast_copy_string(fn, "digits/thousands-i", sizeof(fn));
2534                         } else {
2535                                 ast_copy_string(fn, "digits/thousands", sizeof(fn));
2536                         }
2537                         num %= 1000;
2538                 } else if (num < 1000000000) {  /* 1,000,000,000 */
2539                         lastdigits = get_lastdigits_ru(num / 1000000);
2540                         /* say millions */
2541                         res = ast_say_number_full_ru(chan, num / 1000000, ints, language, NULL, audiofd, ctrlfd);
2542                         if (res)
2543                                 return res;
2544                         if (lastdigits == 1) {
2545                                 ast_copy_string(fn, "digits/million", sizeof(fn));
2546                         } else if (lastdigits > 1 && lastdigits < 5) {
2547                                 ast_copy_string(fn, "digits/million-a", sizeof(fn));
2548                         } else {
2549                                 ast_copy_string(fn, "digits/millions", sizeof(fn));
2550                         }
2551                         num %= 1000000;
2552                 } else {
2553                         ast_debug(1, "Number '%d' is too big for me\n", num);
2554                         res = -1;
2555                 }
2556                 if (!res) {
2557                         if (!ast_streamfile(chan, fn, language)) {
2558                                 if ((audiofd  > -1) && (ctrlfd > -1))
2559                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
2560                                 else
2561                                         res = ast_waitstream(chan, ints);
2562                         }
2563                         ast_stopstream(chan);
2564                 }
2565         }
2566         return res;
2567 }
2568
2569 /*! \brief Thai syntax */
2570 static int ast_say_number_full_th(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
2571 {
2572         int res = 0;
2573         int playh = 0;
2574         char fn[256] = "";
2575         if (!num) 
2576                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
2577
2578         while(!res && (num || playh)) {
2579                 if (num < 0) {
2580                         ast_copy_string(fn, "digits/lop", sizeof(fn));
2581                         if ( num > INT_MIN ) {
2582                                 num = -num;
2583                         } else {
2584                                 num = 0;
2585                         }       
2586                 } else if (playh) {
2587                         ast_copy_string(fn, "digits/roi", sizeof(fn));
2588                         playh = 0;
2589                 } else if (num < 100) {
2590                         if ((num <= 20) || ((num % 10) == 1)) {
2591                                 snprintf(fn, sizeof(fn), "digits/%d", num);
2592                                 num = 0;
2593                         } else {
2594                                 snprintf(fn, sizeof(fn), "digits/%d", (num / 10) * 10);
2595                                 num %= 10;
2596                         }
2597                 } else if (num < 1000) {
2598                         snprintf(fn, sizeof(fn), "digits/%d", (num/100));
2599                         playh++;
2600                         num %= 100;
2601                 } else if (num < 10000) { /* 10,000 */
2602                         res = ast_say_number_full_th(chan, num / 1000, ints, language, audiofd, ctrlfd);
2603                         if (res)
2604                                 return res;
2605                         num %= 1000;
2606                         ast_copy_string(fn, "digits/pan", sizeof(fn));
2607                 } else if (num < 100000) { /* 100,000 */
2608                         res = ast_say_number_full_th(chan, num / 10000, ints, language, audiofd, ctrlfd);
2609                         if (res)
2610                                 return res;
2611                         num %= 10000;
2612                         ast_copy_string(fn, "digits/muan", sizeof(fn));
2613                 } else if (num < 1000000) { /* 1,000,000 */
2614                         res = ast_say_number_full_th(chan, num / 100000, ints, language, audiofd, ctrlfd);
2615                         if (res)
2616                                 return res;
2617                         num %= 100000;
2618                         ast_copy_string(fn, "digits/san", sizeof(fn));
2619                 } else {
2620                         res = ast_say_number_full_th(chan, num / 1000000, ints, language, audiofd, ctrlfd);
2621                         if (res)
2622                                 return res;
2623                         num %= 1000000;
2624                         ast_copy_string(fn, "digits/larn", sizeof(fn));
2625                 }
2626                 if (!res) {
2627                         if(!ast_streamfile(chan, fn, language)) {
2628                                 if ((audiofd  > -1) && (ctrlfd > -1))
2629                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
2630                                 else
2631                                         res = ast_waitstream(chan, ints);
2632                         }
2633                         ast_stopstream(chan);
2634                 }
2635         }
2636         return res;
2637 }
2638
2639 /*! \brief  ast_say_number_full_vi: Vietnamese syntax */
2640 static int ast_say_number_full_vi(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
2641 {
2642         int res = 0;
2643         int playh = 0;
2644         int playoh = 0;
2645         int playohz = 0;
2646         int playz = 0;
2647         int playl = 0;
2648         char fn[256] = "";
2649         if (!num) 
2650                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
2651         while (!res && (num || playh)) {
2652                 if (num < 0) {
2653                         ast_copy_string(fn, "digits/minus", sizeof(fn));
2654                         if ( num > INT_MIN ) {
2655                                 num = -num;
2656                         } else {
2657                                 num = 0;
2658                         }       
2659                 } else if (playl) {
2660                         snprintf(fn, sizeof(fn), "digits/%da", num);
2661                         playl = 0;
2662                         num = 0;
2663                 } else if (playh) {
2664                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
2665                         playh = 0;
2666                 } else if (playz) {
2667                         ast_copy_string(fn, "digits/odd", sizeof(fn));
2668                         playz = 0;                      
2669                 } else if (playoh) {
2670                         ast_copy_string(fn, "digits/0-hundred", sizeof(fn));
2671                         playoh = 0;
2672                 } else if (playohz) {
2673                         ast_copy_string(fn, "digits/0-hundred-odd", sizeof(fn));
2674                         playohz = 0;
2675                 } else  if (num < 20) {
2676                         snprintf(fn, sizeof(fn), "digits/%d", num);
2677                         num = 0;
2678                 } else  if (num < 100) {
2679                         snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
2680                         num %= 10;
2681                         if ((num == 5) || (num == 4) || (num == 1)) playl++;
2682                 } else {
2683                         if (num < 1000) {
2684                                 snprintf(fn, sizeof(fn), "digits/%d", (num/100));                               
2685                                 num %= 100;
2686                                 if (num && (num < 10)) {
2687                                         playz++;
2688                                         playh++;
2689                                 } else {
2690                                         playh++;
2691                                 }
2692                         } else {
2693                                 if (num < 1000000) { /* 1,000,000 */
2694                                         res = ast_say_number_full_vi(chan, num / 1000, ints, language, audiofd, ctrlfd);
2695                                         if (res)
2696                                                 return res;
2697                                         num %= 1000;
2698                                         snprintf(fn, sizeof(fn), "digits/thousand");
2699                                         if (num && (num < 10)) {
2700                                                 playohz++;
2701                                         } else if (num && (num < 100)){
2702                                                 playoh++;
2703                                         } else {
2704                                                 playh = 0;
2705                                                 playohz = 0;
2706                                                 playoh = 0;
2707                                         }
2708                                 } else {
2709                                         if (num < 1000000000) { /* 1,000,000,000 */
2710                                                 res = ast_say_number_full_vi(chan, num / 1000000, ints, language, audiofd, ctrlfd);
2711                                                 if (res)
2712                                                         return res;
2713                                                 num %= 1000000;
2714                                                 ast_copy_string(fn, "digits/million", sizeof(fn));
2715                                         } else {
2716                                                 res = -1;
2717                                         }
2718                                 }
2719                         }
2720                 }
2721                 if (!res) {
2722                         if (!ast_streamfile(chan, fn, language)) {
2723                                 if ((audiofd  > -1) && (ctrlfd > -1))
2724                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
2725                                 else
2726                                         res = ast_waitstream(chan, ints);
2727                         }
2728                         ast_stopstream(chan);
2729                 }
2730         }
2731         return res;
2732 }
2733
2734 /*! \brief  ast_say_enumeration_full: call language-specific functions 
2735  * \note Called from AGI */
2736 static int say_enumeration_full(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
2737 {
2738         if (!strncasecmp(language, "en", 2)) {        /* English syntax */
2739            return ast_say_enumeration_full_en(chan, num, ints, language, audiofd, ctrlfd);
2740         } else if (!strncasecmp(language, "da", 2)) { /* Danish syntax */
2741            return ast_say_enumeration_full_da(chan, num, ints, language, options, audiofd, ctrlfd);
2742         } else if (!strncasecmp(language, "de", 2)) { /* German syntax */
2743            return ast_say_enumeration_full_de(chan, num, ints, language, options, audiofd, ctrlfd);
2744         } else if (!strncasecmp(language, "he", 2)) { /* Hebrew syntax */
2745                 return ast_say_enumeration_full_he(chan, num, ints, language, options, audiofd, ctrlfd);
2746         } else if (!strncasecmp(language, "vi", 2)) { /* Vietnamese syntax */
2747                 return ast_say_enumeration_full_vi(chan, num, ints, language, audiofd, ctrlfd);
2748         }
2749
2750         /* Default to english */
2751         return ast_say_enumeration_full_en(chan, num, ints, language, audiofd, ctrlfd);
2752 }
2753
2754 /*! \brief  ast_say_enumeration_full_en: English syntax 
2755  \note This is the default syntax, if no other syntax defined in this file is used */
2756 static int ast_say_enumeration_full_en(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
2757 {
2758         int res = 0, t = 0;
2759         char fn[256] = "";
2760         
2761         while (!res && num) {
2762                 if (num < 0) {