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