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