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