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