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