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