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