Asterisk - The Open Source Telephony Project  GIT-master-a24979a
Data Structures | Macros | Functions
say.c File Reference

Say numbers and dates (maybe words one day too) More...

#include "asterisk.h"
#include <netinet/in.h>
#include <time.h>
#include <ctype.h>
#include <math.h>
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/say.h"
#include "asterisk/lock.h"
#include "asterisk/localtime.h"
#include "asterisk/utils.h"
#include "asterisk/app.h"
#include "asterisk/test.h"
Include dependency graph for say.c:

Go to the source code of this file.

Data Structures

struct  odmiana
 

Macros

#define IL_DATE_STR   "AdBY"
 
#define IL_DATE_STR_FULL   IL_DATE_STR " 'digits/at' " IL_TIME_STR
 
#define IL_TIME_STR   "HM" /* NOTE: In Hebrew we do not support 12 hours, only 24. No AM or PM exists in the Hebrew language */
 
#define SAY_NUM_BUF_SIZE   256
 

Functions

static void __say_init (void)
 remap the 'say' functions to use those in this file More...
 
struct ast_strast_get_character_str (const char *str, const char *lang, enum ast_say_case_sensitivity sensitivity)
 Returns an ast_str of files for SayAlpha playback. More...
 
struct ast_strast_get_digit_str (const char *str, const char *lang)
 Returns an ast_str of files for SayDigits playback. More...
 
static struct ast_strast_get_money_en_dollars_str (const char *str, const char *lang)
 
struct ast_strast_get_money_str (const char *str, const char *lang)
 ast_get_money_str: call language-specific functions More...
 
struct ast_strast_get_number_str (int num, const char *lang)
 ast_get_number_str: call language-specific functions More...
 
struct ast_strast_get_ordinal_str (int num, const char *lang)
 ast_get_ordinal_str: call language-specific functions More...
 
struct ast_strast_get_phonetic_str (const char *str, const char *lang)
 Returns an ast_str of files for SayPhonetic playback. More...
 
int ast_say_counted_adjective (struct ast_channel *chan, int num, const char adjective[], const char gender[])
 
int ast_say_counted_noun (struct ast_channel *chan, int num, const char noun[])
 
static int ast_say_date_da (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 Danish syntax. More...
 
static int ast_say_date_de (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 German syntax. More...
 
static int ast_say_date_en (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 English syntax. More...
 
static int ast_say_date_fr (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 French syntax. More...
 
static int ast_say_date_gr (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 Greek support. More...
 
static int ast_say_date_he (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 Hebrew syntax. More...
 
static int ast_say_date_hu (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 Hungarian syntax. More...
 
static int ast_say_date_is (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 
static int ast_say_date_ja (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 
static int ast_say_date_ka (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 Georgian syntax. e.g. "oriatas xuti tslis 5 noemberi". More...
 
static int ast_say_date_nl (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 Dutch syntax. More...
 
static int ast_say_date_pt (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 Portuguese syntax. More...
 
static int ast_say_date_th (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 Thai syntax. More...
 
static int ast_say_date_with_format_da (struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
 Danish syntax. More...
 
static int ast_say_date_with_format_de (struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
 German syntax. More...
 
static int ast_say_date_with_format_en (struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
 English syntax. More...
 
static int ast_say_date_with_format_es (struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
 Spanish syntax. More...
 
static int ast_say_date_with_format_fr (struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
 French syntax oclock = heure. More...
 
static int ast_say_date_with_format_gr (struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
 Greek support. More...
 
static int ast_say_date_with_format_he (struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
 ast_say_date_with_format_he Say formatted date in Hebrew More...
 
static int ast_say_date_with_format_is (struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
 
static int ast_say_date_with_format_it (struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
 Italian syntax. More...
 
static int ast_say_date_with_format_ja (struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
 
static int ast_say_date_with_format_nl (struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
 Dutch syntax. More...
 
static int ast_say_date_with_format_pl (struct ast_channel *chan, time_t thetime, const char *ints, const char *lang, const char *format, const char *tzone)
 Polish syntax. More...
 
static int ast_say_date_with_format_pt (struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
 Portuguese syntax. More...
 
static int ast_say_date_with_format_th (struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
 Thai syntax. More...
 
static int ast_say_date_with_format_vi (struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
 Vietnamese syntax. More...
 
static int ast_say_date_with_format_zh (struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
 Taiwanese / Chinese syntax. More...
 
static int ast_say_datetime_de (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 German syntax. More...
 
static int ast_say_datetime_en (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 English syntax. More...
 
static int ast_say_datetime_fr (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 French syntax. More...
 
static int ast_say_datetime_from_now_en (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 English syntax. More...
 
static int ast_say_datetime_from_now_fr (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 French syntax. More...
 
static int ast_say_datetime_from_now_he (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 Hebrew syntax. More...
 
static int ast_say_datetime_from_now_ka (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 Georgian syntax. More...
 
static int ast_say_datetime_from_now_pt (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 Portuguese syntax. More...
 
static int ast_say_datetime_gr (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 Greek support. More...
 
static int ast_say_datetime_he (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 Hebrew syntax. More...
 
static int ast_say_datetime_hu (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 Hungarian syntax. More...
 
static int ast_say_datetime_ja (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 
static int ast_say_datetime_ka (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 Georgian syntax. Say date, then say time. More...
 
static int ast_say_datetime_nl (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 Dutch syntax. More...
 
static int ast_say_datetime_pt (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 Portuguese syntax. More...
 
static int ast_say_datetime_pt_BR (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 Brazilian Portuguese syntax. More...
 
static int ast_say_datetime_th (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 Thai syntax. More...
 
static int ast_say_datetime_zh (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 Taiwanese / Chinese syntax. More...
 
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)
 ast_say_enumeration_full_da: Danish syntax More...
 
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)
 ast_say_enumeration_full_de: German syntax More...
 
static int ast_say_enumeration_full_en (struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
 ast_say_enumeration_full_en: English syntax More...
 
static int ast_say_enumeration_full_he (struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
 
static int ast_say_enumeration_full_is (struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
 ast_say_enumeration_full_is: Icelandic syntax More...
 
static int ast_say_enumeration_full_vi (struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
 
static int ast_say_number_full_cs (struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
 ast_say_number_full_cs: Czech syntax More...
 
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)
 ast_say_number_full_da: Danish syntax New files: More...
 
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)
 ast_say_number_full_de: German syntax More...
 
static int ast_say_number_full_en (struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
 ast_say_number_full_en: English syntax More...
 
static int ast_say_number_full_en_GB (struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
 ast_say_number_full_en_GB: British syntax New files: More...
 
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)
 ast_say_number_full_es: Spanish syntax More...
 
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)
 ast_say_number_full_fr: French syntax Extra sounds needed: 1F: feminin 'une' et: 'and' More...
 
static int ast_say_number_full_gr (struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
 Greek support A list of the files that you need to create -> digits/xilia = "xilia" -> digits/myrio = "ekatomyrio" -> digits/thousands = "xiliades" -> digits/millions = "ektatomyria" -> digits/[1..12] :: A pronunciation of th digits form 1 to 12 e.g. "tria" -> digits/[10..100] :: A pronunciation of the tens from 10 to 90 e.g. 80 = "ogdonta" Here we must note that we use digits/tens/100 to utter "ekato" and digits/hundred-100 to utter "ekaton" -> digits/hundred-[100...1000] :: A pronunciation of hundreds from 100 to 1000 e.g 400 = "terakosia". Here again we use hundreds/1000 for "xilia" and digits/thousands for "xiliades". More...
 
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)
 
static int ast_say_number_full_hu (struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
 ast_say_number_full_hu: Hungarian syntax More...
 
static int ast_say_number_full_is (struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
 ast_say_number_full_is: Icelandic syntax More...
 
static int ast_say_number_full_it (struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
 ast_say_number_full_it: Italian More...
 
static int ast_say_number_full_ja (struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
 
static int ast_say_number_full_ka (struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
 ast_say_number_full_ka: Georgian syntax More...
 
static int ast_say_number_full_nl (struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
 ast_say_number_full_nl: dutch syntax New files: digits/nl-en More...
 
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)
 ast_say_number_full_no: Norwegian syntax New files: In addition to American English, the following sounds are required: "and", "1N" More...
 
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)
 
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)
 
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)
 ast_say_number_full_ru: Russian syntax More...
 
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)
 ast_say_number_full_se: Swedish syntax More...
 
static int ast_say_number_full_th (struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
 Thai syntax. More...
 
static int ast_say_number_full_ur (struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
 
static int ast_say_number_full_vi (struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
 ast_say_number_full_vi: Vietnamese syntax More...
 
static int ast_say_number_full_zh (struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
 ast_say_number_full_zh: Taiwanese / Chinese syntax More...
 
static int ast_say_time_de (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 German syntax. More...
 
static int ast_say_time_en (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 English syntax. More...
 
static int ast_say_time_fr (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 French syntax. More...
 
static int ast_say_time_gr (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 Greek support. More...
 
static int ast_say_time_he (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 Hebrew syntax. More...
 
static int ast_say_time_hu (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 Hungarian syntax. More...
 
static int ast_say_time_ja (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 
static int ast_say_time_ka (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 Georgian syntax. e.g. "otxi saati da eqvsi tsuti". More...
 
static int ast_say_time_nl (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 Dutch syntax. More...
 
static int ast_say_time_pt (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 Portuguese syntax. More...
 
static int ast_say_time_pt_BR (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 Brazilian Portuguese syntax. More...
 
static int ast_say_time_th (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 Thai syntax. More...
 
static int ast_say_time_zh (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 Taiwanese / Chinese syntax. More...
 
static char * ast_translate_number_ka (int num, char *res, int res_len)
 Georgian support. More...
 
static const char * counted_adjective_ending_ru (int num, const char gender[])
 In slavic languages such as Russian and Ukrainian the rules for declining adjectives are simpler than those for nouns. When counting we use only the singular (to which we give no suffix) and the genative plural (which we represent by adding an "x"). Oh, an in the singular gender matters so we append the supplied gender suffix ("m", "f", "n"). More...
 
static const char * counted_noun_ending_en (int num)
 In English, we use the plural for everything but one. For example: More...
 
static const char * counted_noun_ending_slavic (int num)
 Counting of objects in slavic languages such as Russian and Ukrainian the rules are more complicated. There are two plural forms used in counting. They are the genative singular which we represent with the suffix "x1" and the genative plural which we represent with the suffix "x2". The base names of the soundfiles remain in English. For example: More...
 
static int exp10_int (int power)
 
static int get_lastdigits_ru (int num)
 determine last digits for thousands/millions (ru) More...
 
static struct ast_strget_number_str_en (int num, const char *lang)
 
static struct ast_strget_ordinal_str_en (int num, const char *lang)
 
static int gr_say_number_female (int num, struct ast_channel *chan, const char *ints, const char *lang)
 Greek digits/female-[1..4] : "Mia, dyo , treis, tessereis". More...
 
static char next_item (const char *format)
 
static char * pl_append (char *buffer, char *str)
 
static void pl_odtworz_plik (struct ast_channel *chan, const char *language, int audiofd, int ctrlfd, const char *ints, char *fn)
 
static char * pl_rzad_na_tekst (odmiana *odm, int i, int rzad)
 
static void powiedz (struct ast_channel *chan, const char *language, int audiofd, int ctrlfd, const char *ints, odmiana *odm, int rzad, int i)
 
static int say_character_str_full (struct ast_channel *chan, const char *str, const char *ints, const char *lang, enum ast_say_case_sensitivity sensitivity, int audiofd, int ctrlfd)
 
static int say_date (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 
static int say_date_with_format (struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
 
static int say_datetime (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 
static int say_datetime_from_now (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 
static int say_digit_str_full (struct ast_channel *chan, const char *str, const char *ints, const char *lang, int audiofd, int ctrlfd)
 
static int say_enumeration_full (struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
 ast_say_enumeration_full: call language-specific functions More...
 
static int say_filenames (struct ast_channel *chan, const char *ints, const char *lang, int audiofd, int ctrlfd, struct ast_str *filenames)
 
static int say_money_str_full (struct ast_channel *chan, const char *str, const char *ints, const char *lang, int audiofd, int ctrlfd)
 
static int say_number_full (struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
 ast_say_number_full: call language-specific functions More...
 
static int say_ordinal_full (struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
 say_ordinal_full More...
 
static int say_phonetic_str_full (struct ast_channel *chan, const char *str, const char *ints, const char *lang, int audiofd, int ctrlfd)
 
static int say_time (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
 
static int wait_file (struct ast_channel *chan, const char *ints, const char *file, const char *lang)
 

Detailed Description

Say numbers and dates (maybe words one day too)

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m
Note
12-16-2004 : Support for Greek added by InAccess Networks (work funded by HOL, www.hol.gr) George Konstantoulakis gkon@.nosp@m.inac.nosp@m.cessn.nosp@m.etwo.nosp@m.rks.c.nosp@m.om
2007-02-08 : Support for Georgian added by Alexander Shaduri ashad.nosp@m.uri@.nosp@m.gmail.nosp@m..com, Next Generation Networks (NGN).
2007-03-20 : Support for Thai added by Dome C. dome@.nosp@m.tel..nosp@m.co.th, IP Crossing Co., Ltd.
2021-07-26 : Refactoring to separate string buildup and playback by Naveen Albert aster.nosp@m.isk@.nosp@m.phrea.nosp@m.knet.nosp@m..org

Definition in file say.c.

Macro Definition Documentation

◆ IL_DATE_STR

#define IL_DATE_STR   "AdBY"

◆ IL_DATE_STR_FULL

#define IL_DATE_STR_FULL   IL_DATE_STR " 'digits/at' " IL_TIME_STR

◆ IL_TIME_STR

#define IL_TIME_STR   "HM" /* NOTE: In Hebrew we do not support 12 hours, only 24. No AM or PM exists in the Hebrew language */

◆ SAY_NUM_BUF_SIZE

#define SAY_NUM_BUF_SIZE   256

Definition at line 1580 of file say.c.

Function Documentation

◆ __say_init()

static void __say_init ( void  )
static

remap the 'say' functions to use those in this file

Definition at line 9766 of file say.c.

9767 {
9780 }
static int say_datetime_from_now(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
Definition: say.c:7967
static int say_time(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
Definition: say.c:7206
static int say_digit_str_full(struct ast_channel *chan, const char *str, const char *ints, const char *lang, int audiofd, int ctrlfd)
Definition: say.c:353
static int say_phonetic_str_full(struct ast_channel *chan, const char *str, const char *ints, const char *lang, int audiofd, int ctrlfd)
Definition: say.c:299
static int say_date_with_format(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
Definition: say.c:4339
static int say_character_str_full(struct ast_channel *chan, const char *str, const char *ints, const char *lang, enum ast_say_case_sensitivity sensitivity, int audiofd, int ctrlfd)
Definition: say.c:215
static int say_ordinal_full(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
say_ordinal_full
Definition: say.c:924
static int say_datetime(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
Definition: say.c:7527
static int say_money_str_full(struct ast_channel *chan, const char *str, const char *ints, const char *lang, int audiofd, int ctrlfd)
Definition: say.c:444
static int say_date(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
Definition: say.c:3941
static int say_number_full(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
ast_say_number_full: call language-specific functions
Definition: say.c:858
static int say_enumeration_full(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
ast_say_enumeration_full: call language-specific functions
Definition: say.c:3213
SAY_EXTERN int(* ast_say_money_str_full)(struct ast_channel *chan, const char *num, const char *ints, const char *lang, int audiofd, int ctrlfd) SAY_INIT(ast_say_money_str_full)
Definition: say.h:170
SAY_EXTERN int(* ast_say_datetime_from_now)(struct ast_channel *chan, time_t t, const char *ints, const char *lang) SAY_INIT(ast_say_datetime_from_now)
Definition: say.h:206
SAY_EXTERN int(* ast_say_date)(struct ast_channel *chan, time_t t, const char *ints, const char *lang) SAY_INIT(ast_say_date)
Definition: say.h:204
SAY_EXTERN int(* ast_say_number_full)(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options, int audiofd, int ctrlfd) SAY_INIT(ast_say_number_full)
Same as ast_say_number() with audiofd for received audio and returns 1 on ctrlfd being readable.
Definition: say.h:86
SAY_EXTERN int(* ast_say_enumeration_full)(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options, int audiofd, int ctrlfd) SAY_INIT(ast_say_enumeration_full)
Same as ast_say_enumeration() with audiofd for received audio and returns 1 on ctrlfd being readable.
Definition: say.h:125
SAY_EXTERN int(* ast_say_ordinal_full)(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options, int audiofd, int ctrlfd) SAY_INIT(ast_say_ordinal_full)
Same as ast_say_number() with audiofd for received audio and returns 1 on ctrlfd being readable.
Definition: say.h:105
SAY_EXTERN int(* ast_say_character_str_full)(struct ast_channel *chan, const char *num, const char *ints, const char *lang, enum ast_say_case_sensitivity sensitivity, int audiofd, int ctrlfd) SAY_INIT(ast_say_character_str_full)
Definition: say.h:194
SAY_EXTERN int(* ast_say_date_with_format)(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *timezone) SAY_INIT(ast_say_date_with_format)
Definition: say.h:208
SAY_EXTERN int(* ast_say_digit_str_full)(struct ast_channel *chan, const char *num, const char *ints, const char *lang, int audiofd, int ctrlfd) SAY_INIT(ast_say_digit_str_full)
Same as ast_say_digit_str() with audiofd for received audio and returns 1 on ctrlfd being readable.
Definition: say.h:162
SAY_EXTERN int(* ast_say_time)(struct ast_channel *chan, time_t t, const char *ints, const char *lang) SAY_INIT(ast_say_time)
Definition: say.h:202
SAY_EXTERN int(* ast_say_phonetic_str_full)(struct ast_channel *chan, const char *num, const char *ints, const char *lang, int audiofd, int ctrlfd) SAY_INIT(ast_say_phonetic_str_full)
Definition: say.h:199
SAY_EXTERN int(* ast_say_datetime)(struct ast_channel *chan, time_t t, const char *ints, const char *lang) SAY_INIT(ast_say_datetime)
Definition: say.h:201

References ast_say_character_str_full, ast_say_date, ast_say_date_with_format, ast_say_datetime, ast_say_datetime_from_now, ast_say_digit_str_full, ast_say_enumeration_full, ast_say_money_str_full, ast_say_number_full, ast_say_ordinal_full, ast_say_phonetic_str_full, ast_say_time, say_character_str_full(), say_date(), say_date_with_format(), say_datetime(), say_datetime_from_now(), say_digit_str_full(), say_enumeration_full(), say_money_str_full(), say_number_full(), say_ordinal_full(), say_phonetic_str_full(), and say_time().

◆ ast_get_character_str()

struct ast_str* ast_get_character_str ( const char *  str,
const char *  lang,
enum ast_say_case_sensitivity  sensitivity 
)

Returns an ast_str of files for SayAlpha playback.

Parameters
strText to be translated to the corresponding audio files.
langChannel language
sensitivityCase sensitivity

Computes the list of files to be played by SayAlpha.

Return values
ampersand-separatedstring of Asterisk sound files that can be played back.

Definition at line 63 of file say.c.

63  {
64  const char *fn;
65  char fnbuf[10], asciibuf[20] = "letters/ascii";
66  char ltr;
67  int num = 0;
68  int res = 0;
69  int upper = 0;
70  int lower = 0;
71 
72  struct ast_str *filenames = ast_str_create(20);
73  if (!filenames) {
74  return NULL;
75  }
76  ast_str_reset(filenames);
77 
78  while (str[num] && !res) {
79  fn = NULL;
80  switch (str[num]) {
81  case ('*'):
82  fn = "digits/star";
83  break;
84  case ('#'):
85  fn = "digits/pound";
86  break;
87  case ('!'):
88  fn = "letters/exclaimation-point";
89  break;
90  case ('@'):
91  fn = "letters/at";
92  break;
93  case ('$'):
94  fn = "letters/dollar";
95  break;
96  case ('-'):
97  fn = "letters/dash";
98  break;
99  case ('.'):
100  fn = "letters/dot";
101  break;
102  case ('='):
103  fn = "letters/equals";
104  break;
105  case ('+'):
106  fn = "letters/plus";
107  break;
108  case ('/'):
109  fn = "letters/slash";
110  break;
111  case (' '):
112  fn = "letters/space";
113  break;
114  case ('0'):
115  case ('1'):
116  case ('2'):
117  case ('3'):
118  case ('4'):
119  case ('5'):
120  case ('6'):
121  case ('7'):
122  case ('8'):
123  case ('9'):
124  strcpy(fnbuf, "digits/X");
125  fnbuf[7] = str[num];
126  fn = fnbuf;
127  break;
128  default:
129  ltr = str[num];
130  if ('A' <= ltr && ltr <= 'Z') {
131  ltr += 'a' - 'A'; /* file names are all lower-case */
132  switch (sensitivity) {
133  case AST_SAY_CASE_UPPER:
134  case AST_SAY_CASE_ALL:
135  upper = !upper;
136  case AST_SAY_CASE_LOWER:
137  case AST_SAY_CASE_NONE:
138  break;
139  }
140  } else if ('a' <= ltr && ltr <= 'z') {
141  switch (sensitivity) {
142  case AST_SAY_CASE_LOWER:
143  case AST_SAY_CASE_ALL:
144  lower = !lower;
145  case AST_SAY_CASE_UPPER:
146  case AST_SAY_CASE_NONE:
147  break;
148  }
149  }
150 
151  if (upper) {
152  strcpy(fnbuf, "uppercase");
153  } else if (lower) {
154  strcpy(fnbuf, "lowercase");
155  } else {
156  strcpy(fnbuf, "letters/X");
157  fnbuf[8] = ltr;
158  }
159  fn = fnbuf;
160  }
161  if ((fn && ast_fileexists(fn, NULL, lang) > 0) ||
162  (snprintf(asciibuf + 13, sizeof(asciibuf) - 13, "%d", str[num]) > 0 && ast_fileexists(asciibuf, NULL, lang) > 0 && (fn = asciibuf))) {
163  ast_str_append(&filenames, 0, (num == 0 ? "%s" : "&%s"), fn);
164  }
165  if (upper || lower) {
166  continue;
167  }
168  num++;
169  }
170 
171  return filenames;
172 }
const char * str
Definition: app_jack.c:147
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:1127
#define NULL
Definition: resample.c:96
@ AST_SAY_CASE_LOWER
Definition: say.h:183
@ AST_SAY_CASE_ALL
Definition: say.h:185
@ AST_SAY_CASE_UPPER
Definition: say.h:184
@ AST_SAY_CASE_NONE
Definition: say.h:182
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1117
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:674
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:640
Support for dynamic strings.
Definition: strings.h:604

References ast_fileexists(), AST_SAY_CASE_ALL, AST_SAY_CASE_LOWER, AST_SAY_CASE_NONE, AST_SAY_CASE_UPPER, ast_str_append(), ast_str_create, ast_str_reset(), NULL, and str.

Referenced by say_character_str_full(), and sayfile_exec().

◆ ast_get_digit_str()

struct ast_str* ast_get_digit_str ( const char *  str,
const char *  lang 
)

Returns an ast_str of files for SayDigits playback.

Parameters
strText to be translated to the corresponding audio files.
langChannel language

Computes the list of files to be played by SayDigits.

Return values
ampersand-separatedstring of Asterisk sound files that can be played back.

Definition at line 305 of file say.c.

306 {
307  const char *fn;
308  char fnbuf[256];
309  int num = 0;
310 
311  struct ast_str *filenames = ast_str_create(20);
312  if (!filenames) {
313  return NULL;
314  }
315  ast_str_reset(filenames);
316 
317  while (str[num]) {
318  fn = NULL;
319  switch (str[num]) {
320  case ('*'):
321  fn = "digits/star";
322  break;
323  case ('#'):
324  fn = "digits/pound";
325  break;
326  case ('-'):
327  fn = "digits/minus";
328  break;
329  case '0':
330  case '1':
331  case '2':
332  case '3':
333  case '4':
334  case '5':
335  case '6':
336  case '7':
337  case '8':
338  case '9':
339  strcpy(fnbuf, "digits/X");
340  fnbuf[7] = str[num];
341  fn = fnbuf;
342  break;
343  }
344  if (fn && ast_fileexists(fn, NULL, lang) > 0) {
345  ast_str_append(&filenames, 0, (num == 0 ? "%s" : "&%s"), fn);
346  }
347  num++;
348  }
349 
350  return filenames;
351 }

References ast_fileexists(), ast_str_append(), ast_str_create, ast_str_reset(), NULL, and str.

Referenced by ast_get_money_en_dollars_str(), get_number_str_en(), say_digit_str_full(), and sayfile_exec().

◆ ast_get_money_en_dollars_str()

static struct ast_str* ast_get_money_en_dollars_str ( const char *  str,
const char *  lang 
)
static

Definition at line 359 of file say.c.

360 {
361  const char *fnr;
362 
363  double dollars = 0;
364  int amt, cents;
365  struct ast_str *fnrecurse = NULL;
366 
367  struct ast_str *filenames = ast_str_create(20);
368  if (!filenames) {
369  return NULL;
370  }
371  ast_str_reset(filenames);
372 
373  if (sscanf(str, "%30lf", &dollars) != 1) {
374  amt = 0;
375  } else { /* convert everything to cents */
376  amt = dollars * 100;
377  }
378 
379  /* Just the cents after the dollar decimal point */
380  cents = amt - (((int) dollars) * 100);
381  ast_debug(1, "Cents is %d, amount is %d\n", cents, amt);
382 
383  if (amt >= 100) {
384  fnrecurse = ast_get_number_str((amt / 100), lang);
385  if (!fnrecurse) {
386  ast_log(LOG_WARNING, "Couldn't get string for dollars\n");
387  } else {
388  fnr = ast_str_buffer(fnrecurse);
389  ast_str_append(&filenames, 0, "%s", fnr);
390  }
391 
392  /* If this is it, end on a down pitch, otherwise up pitch */
393  if (amt < 200) {
394  ast_str_append(&filenames, 0, "&%s", (cents > 0) ? "letters/dollar_" : "letters/dollar");
395  } else {
396  ast_str_append(&filenames, 0, "&%s", "dollars");
397  }
398 
399  /* If dollars and cents, add "and" in the middle */
400  if (cents > 0) {
401  ast_str_append(&filenames, 0, "&%s", "and");
402  }
403  }
404 
405  if (cents > 0) {
406  fnrecurse = ast_get_number_str(cents, lang);
407  if (!fnrecurse) {
408  ast_log(LOG_ERROR, "Couldn't get string for cents\n");
409  } else {
410  fnr = ast_str_buffer(fnrecurse);
411  ast_str_append(&filenames, 0, (amt < 100 ? "%s" : "&%s"), fnr);
412  }
413  ast_str_append(&filenames, 0, "&%s", (cents == 1) ? "cent" : "cents");
414  } else if (amt == 0) {
415  fnrecurse = ast_get_digit_str("0", lang);
416  if (!fnrecurse) {
417  ast_log(LOG_ERROR, "Couldn't get string for cents\n");
418  } else {
419  fnr = ast_str_buffer(fnrecurse);
420  ast_str_append(&filenames, 0, "%s", fnr);
421  }
422  ast_str_append(&filenames, 0, "&%s", "cents");
423  }
424 
425  if (fnrecurse) {
426  ast_free(fnrecurse);
427  }
428 
429  return filenames;
430 }
#define ast_free(a)
Definition: astmm.h:180
#define ast_log
Definition: astobj2.c:42
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define LOG_WARNING
struct ast_str * ast_get_digit_str(const char *str, const char *lang)
Returns an ast_str of files for SayDigits playback.
Definition: say.c:305
struct ast_str * ast_get_number_str(int num, const char *lang)
ast_get_number_str: call language-specific functions
Definition: say.c:550
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:739

References ast_debug, ast_free, ast_get_digit_str(), ast_get_number_str(), ast_log, ast_str_append(), ast_str_buffer(), ast_str_create, ast_str_reset(), LOG_ERROR, LOG_WARNING, NULL, and str.

Referenced by ast_get_money_str().

◆ ast_get_money_str()

struct ast_str* ast_get_money_str ( const char *  str,
const char *  lang 
)

ast_get_money_str: call language-specific functions

Returns an ast_str of files for SayMoney playback.

Definition at line 433 of file say.c.

434 {
435  if (!strncasecmp(lang, "en", 2)) { /* English syntax */
436  return ast_get_money_en_dollars_str(str, lang);
437  }
438 
439  ast_log(LOG_WARNING, "Language %s not currently supported, defaulting to US Dollars\n", lang);
440  /* Default to english */
441  return ast_get_money_en_dollars_str(str, lang);
442 }
static struct ast_str * ast_get_money_en_dollars_str(const char *str, const char *lang)
Definition: say.c:359

References ast_get_money_en_dollars_str(), ast_log, LOG_WARNING, and str.

Referenced by say_money_str_full(), and sayfile_exec().

◆ ast_get_number_str()

struct ast_str* ast_get_number_str ( int  num,
const char *  lang 
)

ast_get_number_str: call language-specific functions

Returns an ast_str of files for SayNumber playback.

Definition at line 550 of file say.c.

551 {
552  if (!strncasecmp(lang, "en", 2)) { /* English syntax */
553  return get_number_str_en(num, lang);
554  }
555 
556  ast_log(LOG_WARNING, "Language %s not currently supported, defaulting to English\n", lang);
557  /* Default to english */
558  return get_number_str_en(num, lang);
559 }
static struct ast_str * get_number_str_en(int num, const char *lang)
Definition: say.c:450

References ast_log, get_number_str_en(), and LOG_WARNING.

Referenced by ast_get_money_en_dollars_str(), ast_say_number_full_en(), and sayfile_exec().

◆ ast_get_ordinal_str()

struct ast_str* ast_get_ordinal_str ( int  num,
const char *  lang 
)

ast_get_ordinal_str: call language-specific functions

Returns an ast_str of files for SayOrdinal playback.

Definition at line 670 of file say.c.

671 {
672  if (!strncasecmp(lang, "en", 2)) { /* English syntax */
673  return get_ordinal_str_en(num, lang);
674  }
675 
676  ast_log(LOG_WARNING, "Language %s not currently supported, defaulting to English\n", lang);
677  /* Default to english */
678  return get_ordinal_str_en(num, lang);
679 }
static struct ast_str * get_ordinal_str_en(int num, const char *lang)
Definition: say.c:561

References ast_log, get_ordinal_str_en(), and LOG_WARNING.

Referenced by say_ordinal_full(), and sayfile_exec().

◆ ast_get_phonetic_str()

struct ast_str* ast_get_phonetic_str ( const char *  str,
const char *  lang 
)

Returns an ast_str of files for SayPhonetic playback.

Parameters
strText to be translated to the corresponding audio files.
langChannel language

Computes the list of files to be played by SayPhonetic.

Return values
ampersand-separatedstring of Asterisk sound files that can be played back.

Definition at line 221 of file say.c.

222 {
223  const char *fn;
224  char fnbuf[256];
225  char ltr;
226  int num = 0;
227 
228  struct ast_str *filenames = ast_str_create(20);
229  if (!filenames) {
230  return NULL;
231  }
232  ast_str_reset(filenames);
233 
234  while (str[num]) {
235  fn = NULL;
236  switch (str[num]) {
237  case ('*'):
238  fn = "digits/star";
239  break;
240  case ('#'):
241  fn = "digits/pound";
242  break;
243  case ('!'):
244  fn = "letters/exclaimation-point";
245  break;
246  case ('@'):
247  fn = "letters/at";
248  break;
249  case ('$'):
250  fn = "letters/dollar";
251  break;
252  case ('-'):
253  fn = "letters/dash";
254  break;
255  case ('.'):
256  fn = "letters/dot";
257  break;
258  case ('='):
259  fn = "letters/equals";
260  break;
261  case ('+'):
262  fn = "letters/plus";
263  break;
264  case ('/'):
265  fn = "letters/slash";
266  break;
267  case (' '):
268  fn = "letters/space";
269  break;
270  case ('0'):
271  case ('1'):
272  case ('2'):
273  case ('3'):
274  case ('4'):
275  case ('5'):
276  case ('6'):
277  case ('7'):
278  case ('8'):
279  strcpy(fnbuf, "digits/X");
280  fnbuf[7] = str[num];
281  fn = fnbuf;
282  break;
283  default: /* '9' falls here... */
284  ltr = str[num];
285  if ('A' <= ltr && ltr <= 'Z') ltr += 'a' - 'A'; /* file names are all lower-case */
286  strcpy(fnbuf, "phonetic/X_p");
287  fnbuf[9] = ltr;
288  fn = fnbuf;
289  }
290  if (fn && ast_fileexists(fn, NULL, lang) > 0) {
291  ast_str_append(&filenames, 0, (num == 0 ? "%s" : "&%s"), fn);
292  }
293  num++;
294  }
295 
296  return filenames;
297 }

References ast_fileexists(), ast_str_append(), ast_str_create, ast_str_reset(), NULL, and str.

Referenced by say_phonetic_str_full(), and sayfile_exec().

◆ ast_say_counted_adjective()

int ast_say_counted_adjective ( struct ast_channel chan,
int  num,
const char  adjective[],
const char  gender[] 
)

Definition at line 9742 of file say.c.

9743 {
9744  char *temp;
9745  int temp_len;
9746  const char *ending;
9747  if (!strncasecmp(ast_channel_language(chan), "ru", 2)) { /* Russian */
9748  ending = counted_adjective_ending_ru(num, gender);
9749  } else if (!strncasecmp(ast_channel_language(chan), "ua", 2)) { /* Ukrainian */
9750  ending = counted_adjective_ending_ru(num, gender);
9751  } else if (!strncasecmp(ast_channel_language(chan), "pl", 2)) { /* Polish */
9752  ending = counted_adjective_ending_ru(num, gender);
9753  } else { /* English and default */
9754  ending = "";
9755  }
9756  temp = ast_alloca((temp_len = (strlen(adjective) + strlen(ending) + 1)));
9757  snprintf(temp, temp_len, "%s%s", adjective, ending);
9758  return ast_play_and_wait(chan, temp);
9759 }
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
const char * ast_channel_language(const struct ast_channel *chan)
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: main/app.c:1686
static const char * counted_adjective_ending_ru(int num, const char gender[])
In slavic languages such as Russian and Ukrainian the rules for declining adjectives are simpler than...
Definition: say.c:9726

References ast_alloca, ast_channel_language(), ast_play_and_wait(), and counted_adjective_ending_ru().

◆ ast_say_counted_noun()

int ast_say_counted_noun ( struct ast_channel chan,
int  num,
const char  noun[] 
)

Definition at line 9700 of file say.c.

9701 {
9702  char *temp;
9703  int temp_len;
9704  const char *ending;
9705  if (!strncasecmp(ast_channel_language(chan), "ru", 2)) { /* Russian */
9706  ending = counted_noun_ending_slavic(num);
9707  } else if (!strncasecmp(ast_channel_language(chan), "ua", 2)) { /* Ukrainian */
9708  ending = counted_noun_ending_slavic(num);
9709  } else if (!strncasecmp(ast_channel_language(chan), "pl", 2)) { /* Polish */
9710  ending = counted_noun_ending_slavic(num);
9711  } else { /* English and default */
9712  ending = counted_noun_ending_en(num);
9713  }
9714  temp = ast_alloca((temp_len = (strlen(noun) + strlen(ending) + 1)));
9715  snprintf(temp, temp_len, "%s%s", noun, ending);
9716  return ast_play_and_wait(chan, temp);
9717 }
static const char * counted_noun_ending_en(int num)
In English, we use the plural for everything but one. For example:
Definition: say.c:9662
static const char * counted_noun_ending_slavic(int num)
Counting of objects in slavic languages such as Russian and Ukrainian the rules are more complicated....
Definition: say.c:9681

References ast_alloca, ast_channel_language(), ast_play_and_wait(), counted_noun_ending_en(), and counted_noun_ending_slavic().

◆ ast_say_date_da()

int ast_say_date_da ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang 
)
static

Danish syntax.

Definition at line 4005 of file say.c.

4006 {
4007  struct timeval when = { t, 0 };
4008  struct ast_tm tm;
4009  char fn[256];
4010  int res = 0;
4011  ast_localtime(&when, &tm, NULL);
4012  if (!res) {
4013  snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
4014  res = ast_streamfile(chan, fn, lang);
4015  if (!res)
4016  res = ast_waitstream(chan, ints);
4017  }
4018  if (!res)
4019  res = ast_say_enumeration(chan, tm.tm_mday, ints, lang, (char * ) NULL);
4020  if (!res)
4021  res = ast_waitstream(chan, ints);
4022  if (!res) {
4023  snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
4024  res = ast_streamfile(chan, fn, lang);
4025  if (!res)
4026  res = ast_waitstream(chan, ints);
4027  }
4028  if (!res) {
4029  /* Year */
4030  int year = tm.tm_year + 1900;
4031  if (year > 1999) { /* year 2000 and later */
4032  res = ast_say_number(chan, year, ints, lang, (char *) NULL);
4033  } else {
4034  if (year < 1100) {
4035  /* I'm not going to handle 1100 and prior */
4036  /* We'll just be silent on the year, instead of bombing out. */
4037  } else {
4038  /* year 1100 to 1999. will anybody need this?!? */
4039  snprintf(fn, sizeof(fn), "digits/%d", (year / 100));
4040  res = wait_file(chan, ints, fn, lang);
4041  if (!res) {
4042  res = wait_file(chan, ints, "digits/hundred", lang);
4043  if (!res && year % 100 != 0) {
4044  res = ast_say_number(chan, (year % 100), ints, lang, (char *) NULL);
4045  }
4046  }
4047  }
4048  }
4049  }
4050  return res;
4051 }
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:1291
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1817
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1739
static int wait_file(struct ast_channel *chan, const char *ints, const char *file, const char *lang)
Definition: say.c:844
int ast_say_number(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options)
says a number
Definition: channel.c:8318
int ast_say_enumeration(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options)
says an enumeration
Definition: channel.c:8330

References ast_localtime(), ast_say_enumeration(), ast_say_number(), ast_streamfile(), ast_waitstream(), NULL, ast_tm::tm_mday, ast_tm::tm_mon, ast_tm::tm_wday, ast_tm::tm_year, and wait_file().

Referenced by say_date().

◆ ast_say_date_de()

int ast_say_date_de ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang 
)
static

German syntax.

Definition at line 4054 of file say.c.

4055 {
4056  struct timeval when = { t, 0 };
4057  struct ast_tm tm;
4058  char fn[256];
4059  int res = 0;
4060  ast_localtime(&when, &tm, NULL);
4061  if (!res) {
4062  snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
4063  res = ast_streamfile(chan, fn, lang);
4064  if (!res)
4065  res = ast_waitstream(chan, ints);
4066  }
4067  if (!res)
4068  res = ast_say_enumeration(chan, tm.tm_mday, ints, lang, (char * ) NULL);
4069  if (!res)
4070  res = ast_waitstream(chan, ints);
4071  if (!res) {
4072  snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
4073  res = ast_streamfile(chan, fn, lang);
4074  if (!res)
4075  res = ast_waitstream(chan, ints);
4076  }
4077  if (!res) {
4078  /* Year */
4079  int year = tm.tm_year + 1900;
4080  if (year > 1999) { /* year 2000 and later */
4081  res = ast_say_number(chan, year, ints, lang, (char *) NULL);
4082  } else {
4083  if (year < 1100) {
4084  /* I'm not going to handle 1100 and prior */
4085  /* We'll just be silent on the year, instead of bombing out. */
4086  } else {
4087  /* year 1100 to 1999. will anybody need this?!? */
4088  /* say 1967 as 'neunzehn hundert sieben und sechzig' */
4089  snprintf(fn, sizeof(fn), "digits/%d", (year / 100) );
4090  res = wait_file(chan, ints, fn, lang);
4091  if (!res) {
4092  res = wait_file(chan, ints, "digits/hundred", lang);
4093  if (!res && year % 100 != 0) {
4094  res = ast_say_number(chan, (year % 100), ints, lang, (char *) NULL);
4095  }
4096  }
4097  }
4098  }
4099  }
4100  return res;
4101 }

References ast_localtime(), ast_say_enumeration(), ast_say_number(), ast_streamfile(), ast_waitstream(), NULL, ast_tm::tm_mday, ast_tm::tm_mon, ast_tm::tm_wday, ast_tm::tm_year, and wait_file().

Referenced by say_date().

◆ ast_say_date_en()

int ast_say_date_en ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang 
)
static

English syntax.

Definition at line 3976 of file say.c.

3977 {
3978  struct ast_tm tm;
3979  struct timeval when = { t, 0 };
3980  char fn[256];
3981  int res = 0;
3982  ast_localtime(&when, &tm, NULL);
3983  if (!res) {
3984  snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
3985  res = ast_streamfile(chan, fn, lang);
3986  if (!res)
3987  res = ast_waitstream(chan, ints);
3988  }
3989  if (!res) {
3990  snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
3991  res = ast_streamfile(chan, fn, lang);
3992  if (!res)
3993  res = ast_waitstream(chan, ints);
3994  }
3995  if (!res)
3996  res = ast_say_number(chan, tm.tm_mday, ints, lang, (char * ) NULL);
3997  if (!res)
3998  res = ast_waitstream(chan, ints);
3999  if (!res)
4000  res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
4001  return res;
4002 }

References ast_localtime(), ast_say_number(), ast_streamfile(), ast_waitstream(), NULL, ast_tm::tm_mday, ast_tm::tm_mon, ast_tm::tm_wday, and ast_tm::tm_year.

Referenced by say_date().

◆ ast_say_date_fr()

int ast_say_date_fr ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang 
)
static

French syntax.

Definition at line 4136 of file say.c.

4137 {
4138  struct timeval when = { t, 0 };
4139  struct ast_tm tm;
4140  char fn[256];
4141  int res = 0;
4142  ast_localtime(&when, &tm, NULL);
4143  if (!res) {
4144  snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
4145  res = ast_streamfile(chan, fn, lang);
4146  if (!res)
4147  res = ast_waitstream(chan, ints);
4148  }
4149  if (!res)
4150  res = ast_say_number(chan, tm.tm_mday, ints, lang, (char * ) NULL);
4151  if (!res)
4152  res = ast_waitstream(chan, ints);
4153  if (!res) {
4154  snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
4155  res = ast_streamfile(chan, fn, lang);
4156  if (!res)
4157  res = ast_waitstream(chan, ints);
4158  }
4159  if (!res)
4160  res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
4161  return res;
4162 }

References ast_localtime(), ast_say_number(), ast_streamfile(), ast_waitstream(), NULL, ast_tm::tm_mday, ast_tm::tm_mon, ast_tm::tm_wday, and ast_tm::tm_year.

Referenced by say_date().

◆ ast_say_date_gr()

static int ast_say_date_gr ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang 
)
static

Greek support.

The format is weekday - day - month -year

A list of the files that you need to create digits/day-[1..7] : "Deytera .. Paraskeyh" digits/months/1..12 : "Ianouariou .. Dekembriou" Attention the months are in "gekinh klhsh"

Definition at line 8345 of file say.c.

8346 {
8347  struct ast_tm tm;
8348  struct timeval when = { t, 0 };
8349 
8350  char fn[256];
8351  int res = 0;
8352 
8353 
8354  ast_localtime(&when, &tm, NULL);
8355  /* W E E K - D A Y */
8356  if (!res) {
8357  snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
8358  res = ast_streamfile(chan, fn, lang);
8359  if (!res)
8360  res = ast_waitstream(chan, ints);
8361  }
8362  /* D A Y */
8363  if (!res) {
8364  gr_say_number_female(tm.tm_mday, chan, ints, lang);
8365  }
8366  /* M O N T H */
8367  if (!res) {
8368  snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
8369  res = ast_streamfile(chan, fn, lang);
8370  if (!res)
8371  res = ast_waitstream(chan, ints);
8372  }
8373  /* Y E A R */
8374  if (!res)
8375  res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
8376  return res;
8377 }
static int gr_say_number_female(int num, struct ast_channel *chan, const char *ints, const char *lang)
Greek digits/female-[1..4] : "Mia, dyo , treis, tessereis".
Definition: say.c:8156

References ast_localtime(), ast_say_number(), ast_streamfile(), ast_waitstream(), gr_say_number_female(), NULL, ast_tm::tm_mday, ast_tm::tm_mon, ast_tm::tm_wday, and ast_tm::tm_year.

Referenced by say_date().

◆ ast_say_date_he()

int ast_say_date_he ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang 
)
static

Hebrew syntax.

Definition at line 4257 of file say.c.

4258 {
4259  struct timeval when = { t, 0 };
4260  struct ast_tm tm;
4261  char fn[256];
4262  int res = 0;
4263  ast_localtime(&when, &tm, NULL);
4264  if (!res) {
4265  snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
4266  res = ast_streamfile(chan, fn, lang);
4267  if (!res) {
4268  res = ast_waitstream(chan, ints);
4269  }
4270  }
4271  if (!res) {
4272  snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
4273  res = ast_streamfile(chan, fn, lang);
4274  if (!res) {
4275  res = ast_waitstream(chan, ints);
4276  }
4277  }
4278  if (!res) {
4279  res = ast_say_number(chan, tm.tm_mday, ints, lang, "m");
4280  }
4281  if (!res) {
4282  res = ast_waitstream(chan, ints);
4283  }
4284  if (!res) {
4285  res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, "m");
4286  }
4287  return res;
4288 }

References ast_localtime(), ast_say_number(), ast_streamfile(), ast_waitstream(), NULL, ast_tm::tm_mday, ast_tm::tm_mon, ast_tm::tm_wday, and ast_tm::tm_year.

Referenced by say_date().

◆ ast_say_date_hu()

int ast_say_date_hu ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang 
)
static

Hungarian syntax.

Definition at line 4104 of file say.c.

4105 {
4106  struct timeval when = { t, 0 };
4107  struct ast_tm tm;
4108  char fn[256];
4109  int res = 0;
4110  ast_localtime(&when, &tm, NULL);
4111 
4112  if (!res)
4113  res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
4114  if (!res)
4115  res = ast_waitstream(chan, ints);
4116  if (!res) {
4117  snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
4118  res = ast_streamfile(chan, fn, lang);
4119  if (!res)
4120  res = ast_waitstream(chan, ints);
4121  }
4122  if (!res)
4123  ast_say_number(chan, tm.tm_mday , ints, lang, (char *) NULL);
4124  if (!res)
4125  res = ast_waitstream(chan, ints);
4126  if (!res) {
4127  snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
4128  res = ast_streamfile(chan, fn, lang);
4129  if (!res)
4130  res = ast_waitstream(chan, ints);
4131  }
4132  return res;
4133 }

References ast_localtime(), ast_say_number(), ast_streamfile(), ast_waitstream(), NULL, ast_tm::tm_mday, ast_tm::tm_mon, ast_tm::tm_wday, and ast_tm::tm_year.

Referenced by say_date().

◆ ast_say_date_is()

int ast_say_date_is ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang 
)
static

Definition at line 4291 of file say.c.

4292 {
4293  struct timeval when = { t, 0 };
4294  struct ast_tm tm;
4295  char fn[256];
4296  int res = 0;
4297  ast_localtime(&when, &tm, NULL);
4298  if (!res) {
4299  snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
4300  res = ast_streamfile(chan, fn, lang);
4301  if (!res)
4302  res = ast_waitstream(chan, ints);
4303  }
4304  if (!res)
4305  res = ast_say_enumeration(chan, tm.tm_mday, ints, lang, (char * ) NULL);
4306  if (!res)
4307  res = ast_waitstream(chan, ints);
4308  if (!res) {
4309  snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
4310  res = ast_streamfile(chan, fn, lang);
4311  if (!res)
4312  res = ast_waitstream(chan, ints);
4313  }
4314  if (!res) {
4315  /* Year */
4316  int year = tm.tm_year + 1900;
4317  if (year > 1999) { /* year 2000 and later */
4318  res = ast_say_number(chan, year, ints, lang, (char *) NULL);
4319  } else {
4320  if (year < 1100) {
4321  /* I'm not going to handle 1100 and prior */
4322  /* We'll just be silent on the year, instead of bombing out. */
4323  } else {
4324  /* year 1100 to 1999. will anybody need this?!? */
4325  snprintf(fn, sizeof(fn), "digits/%d", (year / 100));
4326  res = wait_file(chan, ints, fn, lang);
4327  if (!res) {
4328  res = wait_file(chan, ints, "digits/hundred", lang);
4329  if (!res && year % 100 != 0) {
4330  res = ast_say_number(chan, (year % 100), ints, lang, (char *) NULL);
4331  }
4332  }
4333  }
4334  }
4335  }
4336  return res;
4337 }

References ast_localtime(), ast_say_enumeration(), ast_say_number(), ast_streamfile(), ast_waitstream(), NULL, ast_tm::tm_mday, ast_tm::tm_mon, ast_tm::tm_wday, ast_tm::tm_year, and wait_file().

Referenced by say_date().

◆ ast_say_date_ja()

int ast_say_date_ja ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang 
)
static

Definition at line 8381 of file say.c.

8382 {
8383  struct ast_tm tm;
8384  struct timeval tv = { t, 0 };
8385  char fn[256];
8386  int res = 0;
8387 
8388  ast_localtime(&tv, &tm, NULL);
8389 
8390  if (!res)
8391  res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
8392  if (!res)
8393  res = ast_waitstream(chan, ints);
8394  if (!res)
8395  res = ast_streamfile(chan, "digits/nen", lang);
8396  if (!res) {
8397  snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
8398  res = ast_streamfile(chan, fn, lang);
8399  if (!res)
8400  res = ast_waitstream(chan, ints);
8401  }
8402  if (!res)
8403  res = ast_say_number(chan, tm.tm_mday, ints, lang, (char * ) NULL);
8404  if (!res)
8405  res = ast_streamfile(chan, "digits/nichi", lang);
8406  if (!res) {
8407  snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
8408  res = ast_streamfile(chan, fn, lang);
8409  if (!res)
8410  res = ast_waitstream(chan, ints);
8411  }
8412  return res;
8413 }

References ast_localtime(), ast_say_number(), ast_streamfile(), ast_waitstream(), NULL, ast_tm::tm_mday, ast_tm::tm_mon, ast_tm::tm_wday, and ast_tm::tm_year.

Referenced by say_date().

◆ ast_say_date_ka()

static int ast_say_date_ka ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang 
)
static

Georgian syntax. e.g. "oriatas xuti tslis 5 noemberi".

Georgian support for date/time requires the following files (*.gsm):

  • mon-1, mon-2, ... (ianvari, tebervali, ...)
  • day-1, day-2, ... (orshabati, samshabati, ...)
  • saati_da
  • tsuti
  • tslis

Definition at line 9513 of file say.c.

9514 {
9515  struct timeval when = { t, 0 };
9516  struct ast_tm tm;
9517  char fn[256];
9518  int res = 0;
9519  ast_localtime(&when, &tm, NULL);
9520 
9521  if (!res) {
9522  res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
9523  }
9524 
9525  if (!res) {
9526  snprintf(fn, sizeof(fn), "digits/tslis %d", tm.tm_wday);
9527  res = ast_streamfile(chan, fn, lang);
9528  if (!res) {
9529  res = ast_waitstream(chan, ints);
9530  }
9531  }
9532 
9533  if (!res) {
9534  res = ast_say_number(chan, tm.tm_mday, ints, lang, (char * ) NULL);
9535 /* if (!res)
9536  res = ast_waitstream(chan, ints);
9537 */
9538  }
9539 
9540  if (!res) {
9541  snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
9542  res = ast_streamfile(chan, fn, lang);
9543  if (!res) {
9544  res = ast_waitstream(chan, ints);
9545  }
9546  }
9547  return res;
9548 
9549 }

References ast_localtime(), ast_say_number(), ast_streamfile(), ast_waitstream(), NULL, ast_tm::tm_mday, ast_tm::tm_mon, ast_tm::tm_wday, and ast_tm::tm_year.

Referenced by say_date().

◆ ast_say_date_nl()

int ast_say_date_nl ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang 
)
static

Dutch syntax.

Definition at line 4165 of file say.c.

4166 {
4167  struct timeval when = { t, 0 };
4168  struct ast_tm tm;
4169  char fn[256];
4170  int res = 0;
4171  ast_localtime(&when, &tm, NULL);
4172  if (!res) {
4173  snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
4174  res = ast_streamfile(chan, fn, lang);
4175  if (!res)
4176  res = ast_waitstream(chan, ints);
4177  }
4178  if (!res)
4179  res = ast_say_number(chan, tm.tm_mday, ints, lang, (char * ) NULL);
4180  if (!res) {
4181  snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
4182  res = ast_streamfile(chan, fn, lang);
4183  if (!res)
4184  res = ast_waitstream(chan, ints);
4185  }
4186  if (!res)
4187  res = ast_waitstream(chan, ints);
4188  if (!res)
4189  res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
4190  return res;
4191 }

References ast_localtime(), ast_say_number(), ast_streamfile(), ast_waitstream(), NULL, ast_tm::tm_mday, ast_tm::tm_mon, ast_tm::tm_wday, and ast_tm::tm_year.

Referenced by say_date().

◆ ast_say_date_pt()

int ast_say_date_pt ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang 
)
static

Portuguese syntax.

Definition at line 4230 of file say.c.

4231 {
4232  struct timeval when = { t, 0 };
4233  struct ast_tm tm;
4234  char fn[256];
4235  int res = 0;
4236 
4237  ast_localtime(&when, &tm, NULL);
4238  snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
4239  if (!res)
4240  res = wait_file(chan, ints, fn, lang);
4241  if (!res)
4242  res = ast_say_number(chan, tm.tm_mday, ints, lang, (char *) NULL);
4243  if (!res)
4244  res = wait_file(chan, ints, "digits/pt-de", lang);
4245  snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
4246  if (!res)
4247  res = wait_file(chan, ints, fn, lang);
4248  if (!res)
4249  res = wait_file(chan, ints, "digits/pt-de", lang);
4250  if (!res)
4251  res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
4252 
4253  return res;
4254 }

References ast_localtime(), ast_say_number(), NULL, ast_tm::tm_mday, ast_tm::tm_mon, ast_tm::tm_wday, ast_tm::tm_year, and wait_file().

Referenced by say_date().

◆ ast_say_date_th()

int ast_say_date_th ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang 
)
static

Thai syntax.

Definition at line 4194 of file say.c.

4195 {
4196  struct timeval when = { t, 0 };
4197  struct ast_tm tm;
4198  char fn[256];
4199  int res = 0;
4200  ast_localtime(&when, &tm, NULL);
4201  if (!res) {
4202  snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
4203  res = ast_streamfile(chan, fn, lang);
4204  ast_copy_string(fn, "digits/tee", sizeof(fn));
4205  res = ast_streamfile(chan, fn, lang);
4206  if (!res)
4207  res = ast_waitstream(chan, ints);
4208  }
4209  if (!res)
4210  res = ast_say_number(chan, tm.tm_mday, ints, lang, (char * ) NULL);
4211  if (!res)
4212  res = ast_waitstream(chan, ints);
4213  if (!res) {
4214  ast_copy_string(fn, "digits/duan", sizeof(fn));
4215  res = ast_streamfile(chan, fn, lang);
4216  snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
4217  res = ast_streamfile(chan, fn, lang);
4218  if (!res)
4219  res = ast_waitstream(chan, ints);
4220  }
4221  if (!res){
4222  ast_copy_string(fn, "digits/posor", sizeof(fn));
4223  res = ast_streamfile(chan, fn, lang);
4224  res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
4225  }
4226  return res;
4227 }
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:406

References ast_copy_string(), ast_localtime(), ast_say_number(), ast_streamfile(), ast_waitstream(), NULL, ast_tm::tm_mday, ast_tm::tm_mon, ast_tm::tm_wday, and ast_tm::tm_year.

Referenced by say_date().

◆ ast_say_date_with_format_da()

int ast_say_date_with_format_da ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang,
const char *  format,
const char *  tzone 
)
static

Danish syntax.

Definition at line 4658 of file say.c.

4659 {
4660  struct timeval when = { t, 0 };
4661  struct ast_tm tm;
4662  int res=0, offset, sndoffset;
4663  char sndfile[256], nextmsg[256];
4664 
4665  if (!format)
4666  format = "A dBY HMS";
4667 
4668  ast_localtime(&when, &tm, tzone);
4669 
4670  for (offset=0 ; format[offset] != '\0' ; offset++) {
4671  ast_debug(1, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
4672  switch (format[offset]) {
4673  /* NOTE: if you add more options here, please try to be consistent with strftime(3) */
4674  case '\'':
4675  /* Literal name of a sound file */
4676  for (sndoffset = 0; !strchr("\'\0", format[++offset]) && (sndoffset < sizeof(sndfile) - 1) ; sndoffset++) {
4677  sndfile[sndoffset] = format[offset];
4678  }
4679  sndfile[sndoffset] = '\0';
4680  res = wait_file(chan, ints, sndfile, lang);
4681  break;
4682  case 'A':
4683  case 'a':
4684  /* Sunday - Saturday */
4685  snprintf(nextmsg, sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
4686  res = wait_file(chan, ints, nextmsg, lang);
4687  break;
4688  case 'B':
4689  case 'b':
4690  case 'h':
4691  /* January - December */
4692  snprintf(nextmsg, sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
4693  res = wait_file(chan, ints, nextmsg, lang);
4694  break;
4695  case 'm':
4696  /* Month enumerated */
4697  res = ast_say_enumeration(chan, (tm.tm_mon + 1), ints, lang, "m");
4698  break;
4699  case 'd':
4700  case 'e':
4701  /* First - Thirtyfirst */
4702  res = ast_say_enumeration(chan, tm.tm_mday, ints, lang, "m");
4703  break;
4704  case 'Y':
4705  /* Year */
4706  {
4707  int year = tm.tm_year + 1900;
4708  if (year > 1999) { /* year 2000 and later */
4709  res = ast_say_number(chan, year, ints, lang, (char *) NULL);
4710  } else {
4711  if (year < 1100) {
4712  /* I'm not going to handle 1100 and prior */
4713  /* We'll just be silent on the year, instead of bombing out. */
4714  } else {
4715  /* year 1100 to 1999. will anybody need this?!? */
4716  /* say 1967 as 'nineteen hundred seven and sixty' */
4717  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", (year / 100) );
4718  res = wait_file(chan, ints, nextmsg, lang);
4719  if (!res) {
4720  res = wait_file(chan, ints, "digits/hundred", lang);
4721  if (!res && year % 100 != 0) {
4722  res = ast_say_number(chan, (year % 100), ints, lang, (char *) NULL);
4723  }
4724  }
4725  }
4726  }
4727  }
4728  break;
4729  case 'I':
4730  case 'l':
4731  /* 12-Hour */
4732  res = wait_file(chan, ints, "digits/oclock", lang);
4733  if (tm.tm_hour == 0)
4734  ast_copy_string(nextmsg, "digits/12", sizeof(nextmsg));
4735  else if (tm.tm_hour > 12)
4736  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_hour - 12);
4737  else
4738  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_hour);
4739  if (!res) {
4740  res = wait_file(chan, ints, nextmsg, lang);
4741  }
4742  break;
4743  case 'H':
4744  /* 24-Hour, single digit hours preceded by "oh" (0) */
4745  if (tm.tm_hour < 10 && tm.tm_hour > 0) {
4746  res = wait_file(chan, ints, "digits/0", lang);
4747  }
4748  /* FALLTRHU */
4749  case 'k':
4750  /* 24-Hour */
4751  res = ast_say_number(chan, tm.tm_hour, ints, lang, (char *) NULL);
4752  break;
4753  case 'M':
4754  /* Minute */
4755  if (tm.tm_min > 0 || next_item(&format[offset + 1]) == 'S') { /* zero 'digits/0' only if seconds follow */
4756  res = ast_say_number(chan, tm.tm_min, ints, lang, "f");
4757  }
4758  if (!res && next_item(&format[offset + 1]) == 'S') { /* minutes only if seconds follow */
4759  if (tm.tm_min == 1) {
4760  res = wait_file(chan, ints, "minute", lang);
4761  } else {
4762  res = wait_file(chan, ints, "minutes", lang);
4763  }
4764  }
4765  break;
4766  case 'P':
4767  case 'p':
4768  /* AM/PM */
4769  if (tm.tm_hour > 11)
4770  ast_copy_string(nextmsg, "digits/p-m", sizeof(nextmsg));
4771  else
4772  ast_copy_string(nextmsg, "digits/a-m", sizeof(nextmsg));
4773  res = wait_file(chan, ints, nextmsg, lang);
4774  break;
4775  case 'Q':
4776  /* Shorthand for "Today", "Yesterday", or AdBY */
4777  /* XXX As emphasized elsewhere, this should the native way in your
4778  * language to say the date, with changes in what you say, depending
4779  * upon how recent the date is. XXX */
4780  {
4781  struct timeval now = ast_tvnow();
4782  struct ast_tm tmnow;
4783  time_t beg_today;
4784 
4785  ast_localtime(&now, &tmnow, tzone);
4786  /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
4787  /* In any case, it saves not having to do ast_mktime() */
4788  beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
4789  if (beg_today < t) {
4790  /* Today */
4791  res = wait_file(chan, ints, "digits/today", lang);
4792  } else if (beg_today - 86400 < t) {
4793  /* Yesterday */
4794  res = wait_file(chan, ints, "digits/yesterday", lang);
4795  } else {
4796  res = ast_say_date_with_format_da(chan, t, ints, lang, "AdBY", tzone);
4797  }
4798  }
4799  break;
4800  case 'q':
4801  /* Shorthand for "" (today), "Yesterday", A (weekday), or AdBY */
4802  /* XXX As emphasized elsewhere, this should the native way in your
4803  * language to say the date, with changes in what you say, depending
4804  * upon how recent the date is. XXX */
4805  {
4806  struct timeval now = ast_tvnow();
4807  struct ast_tm tmnow;
4808  time_t beg_today;
4809 
4810  ast_localtime(&now, &tmnow, tzone);
4811  /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
4812  /* In any case, it saves not having to do ast_mktime() */
4813  beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
4814  if (beg_today < t) {
4815  /* Today */
4816  } else if ((beg_today - 86400) < t) {
4817  /* Yesterday */
4818  res = wait_file(chan, ints, "digits/yesterday", lang);
4819  } else if (beg_today - 86400 * 6 < t) {
4820  /* Within the last week */
4821  res = ast_say_date_with_format_da(chan, t, ints, lang, "A", tzone);
4822  } else {
4823  res = ast_say_date_with_format_da(chan, t, ints, lang, "AdBY", tzone);
4824  }
4825  }
4826  break;
4827  case 'R':
4828  res = ast_say_date_with_format_da(chan, t, ints, lang, "HM", tzone);
4829  break;
4830  case 'S':
4831  /* Seconds */
4832  res = wait_file(chan, ints, "digits/and", lang);
4833  if (!res) {
4834  res = ast_say_number(chan, tm.tm_sec, ints, lang, "f");
4835  if (!res) {
4836  res = wait_file(chan, ints, "seconds", lang);
4837  }
4838  }
4839  break;
4840  case 'T':
4841  res = ast_say_date_with_format_da(chan, t, ints, lang, "HMS", tzone);
4842  break;
4843  case ' ':
4844  case ' ':
4845  /* Just ignore spaces and tabs */
4846  break;
4847  default:
4848  /* Unknown character */
4849  ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
4850  }
4851  /* Jump out on DTMF */
4852  if (res) {
4853  break;
4854  }
4855  }
4856  return res;
4857 }
static snd_pcm_format_t format
Definition: chan_alsa.c:106
static int ast_say_date_with_format_da(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
Danish syntax.
Definition: say.c:4658
static char next_item(const char *format)
Definition: say.c:4651
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:157

References ast_copy_string(), ast_debug, ast_localtime(), ast_log, ast_say_enumeration(), ast_say_number(), ast_tvnow(), format, LOG_WARNING, next_item(), NULL, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_wday, ast_tm::tm_year, and wait_file().

Referenced by say_date_with_format().

◆ ast_say_date_with_format_de()

int ast_say_date_with_format_de ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang,
const char *  format,
const char *  tzone 
)
static

German syntax.

Definition at line 4860 of file say.c.

4861 {
4862  struct timeval when = { t, 0 };
4863  struct ast_tm tm;
4864  int res=0, offset, sndoffset;
4865  char sndfile[256], nextmsg[256];
4866 
4867  if (!format)
4868  format = "A dBY HMS";
4869 
4870  ast_localtime(&when, &tm, tzone);
4871 
4872  for (offset=0 ; format[offset] != '\0' ; offset++) {
4873  ast_debug(1, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
4874  switch (format[offset]) {
4875  /* NOTE: if you add more options here, please try to be consistent with strftime(3) */
4876  case '\'':
4877  /* Literal name of a sound file */
4878  for (sndoffset = 0; !strchr("\'\0", format[++offset]) && (sndoffset < sizeof(sndfile) - 1) ; sndoffset++) {
4879  sndfile[sndoffset] = format[offset];
4880  }
4881  sndfile[sndoffset] = '\0';
4882  res = wait_file(chan, ints, sndfile, lang);
4883  break;
4884  case 'A':
4885  case 'a':
4886  /* Sunday - Saturday */
4887  snprintf(nextmsg, sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
4888  res = wait_file(chan, ints, nextmsg, lang);
4889  break;
4890  case 'B':
4891  case 'b':
4892  case 'h':
4893  /* January - December */
4894  snprintf(nextmsg, sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
4895  res = wait_file(chan, ints, nextmsg, lang);
4896  break;
4897  case 'm':
4898  /* Month enumerated */
4899  res = ast_say_enumeration(chan, (tm.tm_mon + 1), ints, lang, "m");
4900  break;
4901  case 'd':
4902  case 'e':
4903  /* First - Thirtyfirst */
4904  res = ast_say_enumeration(chan, tm.tm_mday, ints, lang, "m");
4905  break;
4906  case 'Y':
4907  /* Year */
4908  {
4909  int year = tm.tm_year + 1900;
4910  if (year > 1999) { /* year 2000 and later */
4911  res = ast_say_number(chan, year, ints, lang, (char *) NULL);
4912  } else {
4913  if (year < 1100) {
4914  /* I'm not going to handle 1100 and prior */
4915  /* We'll just be silent on the year, instead of bombing out. */
4916  } else {
4917  /* year 1100 to 1999. will anybody need this?!? */
4918  /* say 1967 as 'neunzehn hundert sieben und sechzig' */
4919  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", (year / 100) );
4920  res = wait_file(chan, ints, nextmsg, lang);
4921  if (!res) {
4922  res = wait_file(chan, ints, "digits/hundred", lang);
4923  if (!res && year % 100 != 0) {
4924  res = ast_say_number(chan, (year % 100), ints, lang, (char *) NULL);
4925  }
4926  }
4927  }
4928  }
4929  }
4930  break;
4931  case 'I':
4932  case 'l':
4933  /* 12-Hour */
4934  if (tm.tm_hour == 0)
4935  ast_copy_string(nextmsg, "digits/12", sizeof(nextmsg));
4936  else if (tm.tm_hour > 12)
4937  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_hour - 12);
4938  else
4939  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_hour);
4940  res = wait_file(chan, ints, nextmsg, lang);
4941  if (!res) {
4942  res = wait_file(chan, ints, "digits/oclock", lang);
4943  }
4944  break;
4945  case 'H':
4946  case 'k':
4947  /* 24-Hour */
4948  res = ast_say_number(chan, tm.tm_hour, ints, lang, (char *) NULL);
4949  if (!res) {
4950  res = wait_file(chan, ints, "digits/oclock", lang);
4951  }
4952  break;
4953  case 'M':
4954  /* Minute */
4955  if (next_item(&format[offset + 1]) == 'S') { /* zero 'digits/0' only if seconds follow */
4956  res = ast_say_number(chan, tm.tm_min, ints, lang, "f"); /* female only if we say minutes */
4957  } else if (tm.tm_min > 0) {
4958  res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
4959  }
4960 
4961  if (!res && next_item(&format[offset + 1]) == 'S') { /* minutes only if seconds follow */
4962  if (tm.tm_min == 1) {
4963  res = wait_file(chan, ints, "minute", lang);
4964  } else {
4965  res = wait_file(chan, ints, "minutes", lang);
4966  }
4967  }
4968  break;
4969  case 'P':
4970  case 'p':
4971  /* AM/PM */
4972  if (tm.tm_hour > 11)
4973  ast_copy_string(nextmsg, "digits/p-m", sizeof(nextmsg));
4974  else
4975  ast_copy_string(nextmsg, "digits/a-m", sizeof(nextmsg));
4976  res = wait_file(chan, ints, nextmsg, lang);
4977  break;
4978  case 'Q':
4979  /* Shorthand for "Today", "Yesterday", or AdBY */
4980  /* XXX As emphasized elsewhere, this should the native way in your
4981  * language to say the date, with changes in what you say, depending
4982  * upon how recent the date is. XXX */
4983  {
4984  struct timeval now = ast_tvnow();
4985  struct ast_tm tmnow;
4986  time_t beg_today;
4987 
4988  ast_localtime(&now, &tmnow, tzone);
4989  /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
4990  /* In any case, it saves not having to do ast_mktime() */
4991  beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
4992  if (beg_today < t) {
4993  /* Today */
4994  res = wait_file(chan, ints, "digits/today", lang);
4995  } else if (beg_today - 86400 < t) {
4996  /* Yesterday */
4997  res = wait_file(chan, ints, "digits/yesterday", lang);
4998  } else {
4999  res = ast_say_date_with_format_de(chan, t, ints, lang, "AdBY", tzone);
5000  }
5001  }
5002  break;
5003  case 'q':
5004  /* Shorthand for "" (today), "Yesterday", A (weekday), or AdBY */
5005  /* XXX As emphasized elsewhere, this should the native way in your
5006  * language to say the date, with changes in what you say, depending
5007  * upon how recent the date is. XXX */
5008  {
5009  struct timeval now = ast_tvnow();
5010  struct ast_tm tmnow;
5011  time_t beg_today;
5012 
5013  ast_localtime(&now, &tmnow, tzone);
5014  /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
5015  /* In any case, it saves not having to do ast_mktime() */
5016  beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
5017  if (beg_today < t) {
5018  /* Today */
5019  } else if ((beg_today - 86400) < t) {
5020  /* Yesterday */
5021  res = wait_file(chan, ints, "digits/yesterday", lang);
5022  } else if (beg_today - 86400 * 6 < t) {
5023  /* Within the last week */
5024  res = ast_say_date_with_format_de(chan, t, ints, lang, "A", tzone);
5025  } else {
5026  res = ast_say_date_with_format_de(chan, t, ints, lang, "AdBY", tzone);
5027  }
5028  }
5029  break;
5030  case 'R':
5031  res = ast_say_date_with_format_de(chan, t, ints, lang, "HM", tzone);
5032  break;
5033  case 'S':
5034  /* Seconds */
5035  res = wait_file(chan, ints, "digits/and", lang);
5036  if (!res) {
5037  res = ast_say_number(chan, tm.tm_sec, ints, lang, "f");
5038  if (!res) {
5039  res = wait_file(chan, ints, tm.tm_sec == 1 ? "second" : "seconds", lang);
5040  }
5041  }
5042  break;
5043  case 'T':
5044  res = ast_say_date_with_format_de(chan, t, ints, lang, "HMS", tzone);
5045  break;
5046  case ' ':
5047  case ' ':
5048  /* Just ignore spaces and tabs */
5049  break;
5050  default:
5051  /* Unknown character */
5052  ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
5053  }
5054  /* Jump out on DTMF */
5055  if (res) {
5056  break;
5057  }
5058  }
5059  return res;
5060 }
static int ast_say_date_with_format_de(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
German syntax.
Definition: say.c:4860

References ast_copy_string(), ast_debug, ast_localtime(), ast_log, ast_say_enumeration(), ast_say_number(), ast_tvnow(), format, LOG_WARNING, next_item(), NULL, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_wday, ast_tm::tm_year, and wait_file().

Referenced by say_date_with_format().

◆ ast_say_date_with_format_en()

int ast_say_date_with_format_en ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang,
const char *  format,
const char *  tzone 
)
static

English syntax.

Definition at line 4380 of file say.c.

4381 {
4382  struct timeval when = { t, 0 };
4383  struct ast_tm tm;
4384  int res=0, offset, sndoffset;
4385  char sndfile[256], nextmsg[256];
4386 
4387  if (format == NULL)
4388  format = "ABdY 'digits/at' IMp";
4389 
4390  ast_localtime(&when, &tm, tzone);
4391 
4392  for (offset=0 ; format[offset] != '\0' ; offset++) {
4393  ast_debug(1, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
4394  switch (format[offset]) {
4395  /* NOTE: if you add more options here, please try to be consistent with strftime(3) */
4396  case '\'':
4397  /* Literal name of a sound file */
4398  for (sndoffset = 0; !strchr("\'\0", format[++offset]) && (sndoffset < sizeof(sndfile) - 1) ; sndoffset++) {
4399  sndfile[sndoffset] = format[offset];
4400  }
4401  sndfile[sndoffset] = '\0';
4402  res = wait_file(chan, ints, sndfile, lang);
4403  break;
4404  case 'A':
4405  case 'a':
4406  /* Sunday - Saturday */
4407  snprintf(nextmsg, sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
4408  res = wait_file(chan, ints, nextmsg, lang);
4409  break;
4410  case 'B':
4411  case 'b':
4412  case 'h':
4413  /* January - December */
4414  snprintf(nextmsg, sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
4415  res = wait_file(chan, ints, nextmsg, lang);
4416  break;
4417  case 'm':
4418  /* Month enumerated */
4419  res = ast_say_enumeration(chan, (tm.tm_mon + 1), ints, lang, (char *) NULL);
4420  break;
4421  case 'd':
4422  case 'e':
4423  /* First - Thirtyfirst */
4424  res = ast_say_enumeration(chan, tm.tm_mday, ints, lang, (char *) NULL);
4425  break;
4426  case 'Y':
4427  /* Year */
4428  if (tm.tm_year > 99) {
4429  res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
4430  } else if (tm.tm_year < 1) {
4431  /* I'm not going to handle 1900 and prior */
4432  /* We'll just be silent on the year, instead of bombing out. */
4433  } else {
4434  res = wait_file(chan, ints, "digits/19", lang);
4435  if (!res) {
4436  if (tm.tm_year <= 9) {
4437  /* 1901 - 1909 */
4438  res = wait_file(chan, ints, "digits/oh", lang);
4439  }
4440 
4441  res |= ast_say_number(chan, tm.tm_year, ints, lang, (char *) NULL);
4442  }
4443  }
4444  break;
4445  case 'I':
4446  case 'l':
4447  /* 12-Hour */
4448  if (tm.tm_hour == 0)
4449  ast_copy_string(nextmsg, "digits/12", sizeof(nextmsg));
4450  else if (tm.tm_hour > 12)
4451  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_hour - 12);
4452  else
4453  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_hour);
4454  res = wait_file(chan, ints, nextmsg, lang);
4455  break;
4456  case 'H':
4457  case 'k':
4458  /* 24-Hour */
4459  if (format[offset] == 'H') {
4460  /* e.g. oh-eight */
4461  if (tm.tm_hour < 10) {
4462  res = wait_file(chan, ints, "digits/oh", lang);
4463  }
4464  } else {
4465  /* e.g. eight */
4466  if (tm.tm_hour == 0) {
4467  res = wait_file(chan, ints, "digits/oh", lang);
4468  }
4469  }
4470  if (!res) {
4471  if (tm.tm_hour != 0) {
4472  int remaining = tm.tm_hour;
4473  if (tm.tm_hour > 20) {
4474  res = wait_file(chan, ints, "digits/20", lang);
4475  remaining -= 20;
4476  }
4477  if (!res) {
4478  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", remaining);
4479  res = wait_file(chan, ints, nextmsg, lang);
4480  }
4481  }
4482  }
4483  break;
4484  case 'M':
4485  case 'N':
4486  /* Minute */
4487  if (tm.tm_min == 0) {
4488  if (format[offset] == 'M') {
4489  res = wait_file(chan, ints, "digits/oclock", lang);
4490  } else {
4491  res = wait_file(chan, ints, "digits/hundred", lang);
4492  }
4493  } else if (tm.tm_min < 10) {
4494  res = wait_file(chan, ints, "digits/oh", lang);
4495  if (!res) {
4496  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_min);
4497  res = wait_file(chan, ints, nextmsg, lang);
4498  }
4499  } else {
4500  res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
4501  }
4502  break;
4503  case 'P':
4504  case 'p':
4505  /* AM/PM */
4506  if (tm.tm_hour > 11)
4507  ast_copy_string(nextmsg, "digits/p-m", sizeof(nextmsg));
4508  else
4509  ast_copy_string(nextmsg, "digits/a-m", sizeof(nextmsg));
4510  res = wait_file(chan, ints, nextmsg, lang);
4511  break;
4512  case 'Q':
4513  /* Shorthand for "Today", "Yesterday", or ABdY */
4514  /* XXX As emphasized elsewhere, this should the native way in your
4515  * language to say the date, with changes in what you say, depending
4516  * upon how recent the date is. XXX */
4517  {
4518  struct timeval now = ast_tvnow();
4519  struct ast_tm tmnow;
4520  time_t beg_today;
4521 
4522  gettimeofday(&now, NULL);
4523  ast_localtime(&now, &tmnow, tzone);
4524  /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
4525  /* In any case, it saves not having to do ast_mktime() */
4526  beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
4527  if (beg_today + 15768000 < t) {
4528  /* More than 6 months from now - "April nineteenth two thousand three" */
4529  res = ast_say_date_with_format_en(chan, t, ints, lang, "BdY", tzone);
4530  } else if (beg_today + 2628000 < t) {
4531  /* Less than 6 months from now - "August seventh" */
4532  res = ast_say_date_with_format_en(chan, t, ints, lang, "Bd", tzone);
4533  } else if (beg_today + 86400 * 6 < t) {
4534  /* Less than a month from now - "Sunday, October third" */
4535  res = ast_say_date_with_format_en(chan, t, ints, lang, "ABd", tzone);
4536  } else if (beg_today + 172800 < t) {
4537  /* Within the next week */
4538  res = ast_say_date_with_format_en(chan, t, ints, lang, "A", tzone);
4539  } else if (beg_today + 86400 < t) {
4540  /* Tomorrow */
4541  res = wait_file(chan, ints, "digits/tomorrow", lang);
4542  } else if (beg_today < t) {
4543  /* Today */
4544  res = wait_file(chan, ints, "digits/today", lang);
4545  } else if (beg_today - 86400 < t) {
4546  /* Yesterday */
4547  res = wait_file(chan, ints, "digits/yesterday", lang);
4548  } else if (beg_today - 86400 * 6 < t) {
4549  /* Within the last week */
4550  res = ast_say_date_with_format_en(chan, t, ints, lang, "A", tzone);
4551  } else if (beg_today - 2628000 < t) {
4552  /* Less than a month ago - "Sunday, October third" */
4553  res = ast_say_date_with_format_en(chan, t, ints, lang, "ABd", tzone);
4554  } else if (beg_today - 15768000 < t) {
4555  /* Less than 6 months ago - "August seventh" */
4556  res = ast_say_date_with_format_en(chan, t, ints, lang, "Bd", tzone);
4557  } else {
4558  /* More than 6 months ago - "April nineteenth two thousand three" */
4559  res = ast_say_date_with_format_en(chan, t, ints, lang, "BdY", tzone);
4560  }
4561  }
4562  break;
4563  case 'q':
4564  /* Shorthand for "" (today), "Yesterday", A (weekday), or ABdY */
4565  /* XXX As emphasized elsewhere, this should the native way in your
4566  * language to say the date, with changes in what you say, depending
4567  * upon how recent the date is. XXX */
4568  {
4569  struct timeval now;
4570  struct ast_tm tmnow;
4571  time_t beg_today;
4572 
4573  now = ast_tvnow();
4574  ast_localtime(&now, &tmnow, tzone);
4575  /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
4576  /* In any case, it saves not having to do ast_mktime() */
4577  beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
4578  if (beg_today + 15768000 < t) {
4579  /* More than 6 months from now - "April nineteenth two thousand three" */
4580  res = ast_say_date_with_format_en(chan, t, ints, lang, "BdY", tzone);
4581  } else if (beg_today + 2628000 < t) {
4582  /* Less than 6 months from now - "August seventh" */
4583  res = ast_say_date_with_format_en(chan, t, ints, lang, "Bd", tzone);
4584  } else if (beg_today + 86400 * 6 < t) {
4585  /* Less than a month from now - "Sunday, October third" */
4586  res = ast_say_date_with_format_en(chan, t, ints, lang, "ABd", tzone);
4587  } else if (beg_today + 172800 < t) {
4588  /* Within the next week */
4589  res = ast_say_date_with_format_en(chan, t, ints, lang, "A", tzone);
4590  } else if (beg_today + 86400 < t) {
4591  /* Tomorrow */
4592  res = wait_file(chan, ints, "digits/tomorrow", lang);
4593  } else if (beg_today < t) {
4594  /* Today */
4595  res = wait_file(chan, ints, "digits/today", lang);
4596  } else if (beg_today - 86400 < t) {
4597  /* Yesterday */
4598  res = wait_file(chan, ints, "digits/yesterday", lang);
4599  } else if (beg_today - 86400 * 6 < t) {
4600  /* Within the last week */
4601  res = ast_say_date_with_format_en(chan, t, ints, lang, "A", tzone);
4602  } else if (beg_today - 2628000 < t) {
4603  /* Less than a month ago - "Sunday, October third" */
4604  res = ast_say_date_with_format_en(chan, t, ints, lang, "ABd", tzone);
4605  } else if (beg_today - 15768000 < t) {
4606  /* Less than 6 months ago - "August seventh" */
4607  res = ast_say_date_with_format_en(chan, t, ints, lang, "Bd", tzone);
4608  } else {
4609  /* More than 6 months ago - "April nineteenth two thousand three" */
4610  res = ast_say_date_with_format_en(chan, t, ints, lang, "BdY", tzone);
4611  }
4612  }
4613  break;
4614  case 'R':
4615  res = ast_say_date_with_format_en(chan, t, ints, lang, "HM", tzone);
4616  break;
4617  case 'S':
4618  /* Seconds */
4619  if (tm.tm_sec == 0) {
4620  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_sec);
4621  res = wait_file(chan, ints, nextmsg, lang);
4622  } else if (tm.tm_sec < 10) {
4623  res = wait_file(chan, ints, "digits/oh", lang);
4624  if (!res) {
4625  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_sec);
4626  res = wait_file(chan, ints, nextmsg, lang);
4627  }
4628  } else {
4629  res = ast_say_number(chan, tm.tm_sec, ints, lang, (char *) NULL);
4630  }
4631  break;
4632  case 'T':
4633  res = ast_say_date_with_format_en(chan, t, ints, lang, "HMS", tzone);
4634  break;
4635  case ' ':
4636  case ' ':
4637  /* Just ignore spaces and tabs */
4638  break;
4639  default:
4640  /* Unknown character */
4641  ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
4642  }
4643  /* Jump out on DTMF */
4644  if (res) {
4645  break;
4646  }
4647  }
4648  return res;
4649 }
static int ast_say_date_with_format_en(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
English syntax.
Definition: say.c:4380

References ast_copy_string(), ast_debug, ast_localtime(), ast_log, ast_say_enumeration(), ast_say_number(), ast_tvnow(), format, LOG_WARNING, NULL, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_wday, ast_tm::tm_year, and wait_file().

Referenced by ast_say_date_with_format_th(), ast_say_date_with_format_vi(), and say_date_with_format().

◆ ast_say_date_with_format_es()

int ast_say_date_with_format_es ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang,
const char *  format,
const char *  tzone 
)
static

Spanish syntax.

Definition at line 5607 of file say.c.

5608 {
5609  struct timeval when = { t, 0 };
5610  struct ast_tm tm;
5611  int res=0, offset, sndoffset;
5612  char sndfile[256], nextmsg[256];
5613 
5614  if (format == NULL)
5615  format = "'digits/es-el' Ad 'digits/es-de' B 'digits/es-de' Y 'digits/at' IMp";
5616 
5617  ast_localtime(&when, &tm, tzone);
5618 
5619  for (offset=0 ; format[offset] != '\0' ; offset++) {
5620  ast_debug(1, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
5621  switch (format[offset]) {
5622  /* NOTE: if you add more options here, please try to be consistent with strftime(3) */
5623  case '\'':
5624  /* Literal name of a sound file */
5625  for (sndoffset = 0; !strchr("\'\0", format[++offset]) && (sndoffset < sizeof(sndfile) - 1) ; sndoffset++) {
5626  sndfile[sndoffset] = format[offset];
5627  }
5628  sndfile[sndoffset] = '\0';
5629  snprintf(nextmsg, sizeof(nextmsg), "%s", sndfile);
5630  res = wait_file(chan, ints, nextmsg, lang);
5631  break;
5632  case 'A':
5633  case 'a':
5634  /* Sunday - Saturday */
5635  snprintf(nextmsg, sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
5636  res = wait_file(chan, ints, nextmsg, lang);
5637  break;
5638  case 'B':
5639  case 'b':
5640  case 'h':
5641  /* January - December */
5642  snprintf(nextmsg, sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
5643  res = wait_file(chan, ints, nextmsg, lang);
5644  break;
5645  case 'm':
5646  /* First - Twelfth */
5647  snprintf(nextmsg, sizeof(nextmsg), "digits/h-%d", tm.tm_mon +1);
5648  res = wait_file(chan, ints, nextmsg, lang);
5649  break;
5650  case 'd':
5651  case 'e':
5652  /* First - Thirtyfirst */
5653  res = ast_say_number(chan, tm.tm_mday, ints, lang, (char *) NULL);
5654  break;
5655  case 'Y':
5656  /* Year */
5657  res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
5658  break;
5659  case 'I':
5660  case 'l':
5661  /* 12-Hour */
5662  if (tm.tm_hour == 0)
5663  ast_copy_string(nextmsg, "digits/12", sizeof(nextmsg));
5664  else if (tm.tm_hour == 1 || tm.tm_hour == 13)
5665  snprintf(nextmsg,sizeof(nextmsg), "digits/1F");
5666  else if (tm.tm_hour > 12)
5667  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_hour - 12);
5668  else
5669  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_hour);
5670  res = wait_file(chan, ints, nextmsg, lang);
5671  break;
5672  case 'H':
5673  case 'k':
5674  /* 24-Hour */
5675  res = ast_say_number(chan, tm.tm_hour, ints, lang, NULL);
5676  break;
5677  case 'M':
5678  /* Minute */
5679  res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
5680  break;
5681  case 'P':
5682  case 'p':
5683  /* AM/PM */
5684  if (tm.tm_hour > 18)
5685  res = wait_file(chan, ints, "digits/p-m", lang);
5686  else if (tm.tm_hour > 12)
5687  res = wait_file(chan, ints, "digits/afternoon", lang);
5688  else if (tm.tm_hour)
5689  res = wait_file(chan, ints, "digits/a-m", lang);
5690  break;
5691  case 'Q':
5692  /* Shorthand for "Today", "Yesterday", or ABdY */
5693  /* XXX As emphasized elsewhere, this should the native way in your
5694  * language to say the date, with changes in what you say, depending
5695  * upon how recent the date is. XXX */
5696  {
5697  struct timeval now = ast_tvnow();
5698  struct ast_tm tmnow;
5699  time_t beg_today;
5700 
5701  ast_localtime(&now, &tmnow, tzone);
5702  /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
5703  /* In any case, it saves not having to do ast_mktime() */
5704  beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
5705  if (beg_today < t) {
5706  /* Today */
5707  res = wait_file(chan, ints, "digits/today", lang);
5708  } else if (beg_today - 86400 < t) {
5709  /* Yesterday */
5710  res = wait_file(chan, ints, "digits/yesterday", lang);
5711  } else {
5712  res = ast_say_date_with_format_es(chan, t, ints, lang, "'digits/es-el' Ad 'digits/es-de' B 'digits/es-de' Y", tzone);
5713  }
5714  }
5715  break;
5716  case 'q':
5717  /* Shorthand for "" (today), "Yesterday", A (weekday), or ABdY */
5718  /* XXX As emphasized elsewhere, this should the native way in your
5719  * language to say the date, with changes in what you say, depending
5720  * upon how recent the date is. XXX */
5721  {
5722  struct timeval now = ast_tvnow();
5723  struct ast_tm tmnow;
5724  time_t beg_today;
5725 
5726  ast_localtime(&now, &tmnow, tzone);
5727  /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
5728  /* In any case, it saves not having to do ast_mktime() */
5729  beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
5730  if (beg_today < t) {
5731  /* Today */
5732  res = wait_file(chan, ints, "digits/today", lang);
5733  } else if ((beg_today - 86400) < t) {
5734  /* Yesterday */
5735  res = wait_file(chan, ints, "digits/yesterday", lang);
5736  } else if (beg_today - 86400 * 6 < t) {
5737  /* Within the last week */
5738  res = ast_say_date_with_format_es(chan, t, ints, lang, "A", tzone);
5739  } else {
5740  res = ast_say_date_with_format_es(chan, t, ints, lang, "'digits/es-el' Ad 'digits/es-de' B 'digits/es-de' Y", tzone);
5741  }
5742  }
5743  break;
5744  case 'R':
5745  res = ast_say_date_with_format_es(chan, t, ints, lang, "H 'digits/y' M", tzone);
5746  break;
5747  case 'S':
5748  /* Seconds */
5749  if (tm.tm_sec == 0) {
5750  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_sec);
5751  res = wait_file(chan, ints, nextmsg, lang);
5752  } else if (tm.tm_sec < 10) {
5753  res = wait_file(chan, ints, "digits/oh", lang);
5754  if (!res) {
5755  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_sec);
5756  res = wait_file(chan, ints, nextmsg, lang);
5757  }
5758  } else if ((tm.tm_sec < 21) || (tm.tm_sec % 10 == 0)) {
5759  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_sec);
5760  res = wait_file(chan, ints, nextmsg, lang);
5761  } else {
5762  int ten, one;
5763  ten = (tm.tm_sec / 10) * 10;
5764  one = (tm.tm_sec % 10);
5765  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", ten);
5766  res = wait_file(chan, ints, nextmsg, lang);
5767  if (!res) {
5768  /* Fifty, not fifty-zero */
5769  if (one != 0) {
5770  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", one);
5771  res = wait_file(chan, ints, nextmsg, lang);
5772  }
5773  }
5774  }
5775  break;
5776  case 'T':
5777  res = ast_say_date_with_format_es(chan, t, ints, lang, "HMS", tzone);
5778  break;
5779  case ' ':
5780  case ' ':
5781  /* Just ignore spaces and tabs */
5782  break;
5783  default:
5784  /* Unknown character */
5785  ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
5786  }
5787  /* Jump out on DTMF */
5788  if (res) {
5789  break;
5790  }
5791  }
5792  return res;
5793 }
static int ast_say_date_with_format_es(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
Spanish syntax.
Definition: say.c:5607

References ast_copy_string(), ast_debug, ast_localtime(), ast_log, ast_say_number(), ast_tvnow(), format, LOG_WARNING, NULL, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_wday, ast_tm::tm_year, and wait_file().

Referenced by say_date_with_format().

◆ ast_say_date_with_format_fr()

int ast_say_date_with_format_fr ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang,
const char *  format,
const char *  tzone 
)
static

French syntax oclock = heure.

Definition at line 5798 of file say.c.

5799 {
5800  struct timeval when = { t, 0 };
5801  struct ast_tm tm;
5802  int res=0, offset, sndoffset;
5803  char sndfile[256], nextmsg[256];
5804 
5805  if (format == NULL)
5806  format = "AdBY 'digits/at' IMp";
5807 
5808  ast_localtime(&when, &tm, tzone);
5809 
5810  for (offset=0 ; format[offset] != '\0' ; offset++) {
5811  ast_debug(1, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
5812  switch (format[offset]) {
5813  /* NOTE: if you add more options here, please try to be consistent with strftime(3) */
5814  case '\'':
5815  /* Literal name of a sound file */
5816  for (sndoffset = 0; !strchr("\'\0", format[++offset]) && (sndoffset < sizeof(sndfile) - 1) ; sndoffset++) {
5817  sndfile[sndoffset] = format[offset];
5818  }
5819  sndfile[sndoffset] = '\0';
5820  res = wait_file(chan, ints, sndfile, lang);
5821  break;
5822  case 'A':
5823  case 'a':
5824  /* Sunday - Saturday */
5825  snprintf(nextmsg, sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
5826  res = wait_file(chan, ints, nextmsg, lang);
5827  break;
5828  case 'B':
5829  case 'b':
5830  case 'h':
5831  /* January - December */
5832  snprintf(nextmsg, sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
5833  res = wait_file(chan, ints, nextmsg, lang);
5834  break;
5835  case 'm':
5836  /* First - Twelfth */
5837  snprintf(nextmsg, sizeof(nextmsg), "digits/h-%d", tm.tm_mon +1);
5838  res = wait_file(chan, ints, nextmsg, lang);
5839  break;
5840  case 'd':
5841  case 'e':
5842  /* First */
5843  if (tm.tm_mday == 1) {
5844  snprintf(nextmsg, sizeof(nextmsg), "digits/h-%d", tm.tm_mday);
5845  res = wait_file(chan, ints, nextmsg, lang);
5846  } else {
5847  res = ast_say_number(chan, tm.tm_mday, ints, lang, (char * ) NULL);
5848  }
5849  break;
5850  case 'Y':
5851  /* Year */
5852  if (tm.tm_year > 99) {
5853  res = wait_file(chan, ints, "digits/2", lang);
5854  if (!res) {
5855  res = wait_file(chan, ints, "digits/thousand", lang);
5856  }
5857  if (tm.tm_year > 100) {
5858  if (!res) {
5859  res = ast_say_number(chan, tm.tm_year - 100, ints, lang, (char * ) NULL);
5860  }
5861  }
5862  } else {
5863  if (tm.tm_year < 1) {
5864  /* I'm not going to handle 1900 and prior */
5865  /* We'll just be silent on the year, instead of bombing out. */
5866  } else {
5867  res = wait_file(chan, ints, "digits/thousand", lang);
5868  if (!res) {
5869  wait_file(chan, ints, "digits/9", lang);
5870  wait_file(chan, ints, "digits/hundred", lang);
5871  res = ast_say_number(chan, tm.tm_year, ints, lang, (char * ) NULL);
5872  }
5873  }
5874  }
5875  break;
5876  case 'I':
5877  case 'l':
5878  /* 12-Hour */
5879  if (tm.tm_hour == 0)
5880  ast_copy_string(nextmsg, "digits/12", sizeof(nextmsg));
5881  else if (tm.tm_hour > 12)
5882  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_hour - 12);
5883  else
5884  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_hour);
5885  res = wait_file(chan, ints, nextmsg, lang);
5886  if (!res)
5887  res = wait_file(chan, ints, "digits/oclock", lang);
5888  break;
5889  case 'H':
5890  case 'k':
5891  /* 24-Hour */
5892  res = ast_say_number(chan, tm.tm_hour, ints, lang, (char * ) NULL);
5893  if (!res)
5894  res = wait_file(chan, ints, "digits/oclock", lang);
5895  break;
5896  case 'M':
5897  /* Minute */
5898  if (tm.tm_min == 0) {
5899  break;
5900  }
5901  res = ast_say_number(chan, tm.tm_min, ints, lang, (char * ) NULL);
5902  break;
5903  case 'P':
5904  case 'p':
5905  /* AM/PM */
5906  if (tm.tm_hour > 11)
5907  ast_copy_string(nextmsg, "digits/p-m", sizeof(nextmsg));
5908  else
5909  ast_copy_string(nextmsg, "digits/a-m", sizeof(nextmsg));
5910  res = wait_file(chan, ints, nextmsg, lang);
5911  break;
5912  case 'Q':
5913  /* Shorthand for "Today", "Yesterday", or AdBY */
5914  /* XXX As emphasized elsewhere, this should the native way in your
5915  * language to say the date, with changes in what you say, depending
5916  * upon how recent the date is. XXX */
5917  {
5918  struct timeval now = ast_tvnow();
5919  struct ast_tm tmnow;
5920  time_t beg_today;
5921 
5922  ast_localtime(&now, &tmnow, tzone);
5923  /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
5924  /* In any case, it saves not having to do ast_mktime() */
5925  beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
5926  if (beg_today < t) {
5927  /* Today */
5928  res = wait_file(chan, ints, "digits/today", lang);
5929  } else if (beg_today - 86400 < t) {
5930  /* Yesterday */
5931  res = wait_file(chan, ints, "digits/yesterday", lang);
5932  } else {
5933  res = ast_say_date_with_format_fr(chan, t, ints, lang, "AdBY", tzone);
5934  }
5935  }
5936  break;
5937  case 'q':
5938  /* Shorthand for "" (today), "Yesterday", A (weekday), or AdBY */
5939  /* XXX As emphasized elsewhere, this should the native way in your
5940  * language to say the date, with changes in what you say, depending
5941  * upon how recent the date is. XXX */
5942  {
5943  struct timeval now = ast_tvnow();
5944  struct ast_tm tmnow;
5945  time_t beg_today;
5946 
5947  ast_localtime(&now, &tmnow, tzone);
5948  /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
5949  /* In any case, it saves not having to do ast_mktime() */
5950  beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
5951  if (beg_today < t) {
5952  /* Today */
5953  } else if ((beg_today - 86400) < t) {
5954  /* Yesterday */
5955  res = wait_file(chan, ints, "digits/yesterday", lang);
5956  } else if (beg_today - 86400 * 6 < t) {
5957  /* Within the last week */
5958  res = ast_say_date_with_format_fr(chan, t, ints, lang, "A", tzone);
5959  } else {
5960  res = ast_say_date_with_format_fr(chan, t, ints, lang, "AdBY", tzone);
5961  }
5962  }
5963  break;
5964  case 'R':
5965  res = ast_say_date_with_format_fr(chan, t, ints, lang, "HM", tzone);
5966  break;
5967  case 'S':
5968  /* Seconds */
5969  res = ast_say_number(chan, tm.tm_sec, ints, lang, (char * ) NULL);
5970  if (!res) {
5971  res = wait_file(chan, ints, "second", lang);
5972  }
5973  break;
5974  case 'T':
5975  res = ast_say_date_with_format_fr(chan, t, ints, lang, "HMS", tzone);
5976  break;
5977  case ' ':
5978  case ' ':
5979  /* Just ignore spaces and tabs */
5980  break;
5981  default:
5982  /* Unknown character */
5983  ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
5984  }
5985  /* Jump out on DTMF */
5986  if (res) {
5987  break;
5988  }
5989  }
5990  return res;
5991 }
static int ast_say_date_with_format_fr(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
French syntax oclock = heure.
Definition: say.c:5798

References ast_copy_string(), ast_debug, ast_localtime(), ast_log, ast_say_number(), ast_tvnow(), format, LOG_WARNING, NULL, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_wday, ast_tm::tm_year, and wait_file().

Referenced by say_date_with_format().

◆ ast_say_date_with_format_gr()

static int ast_say_date_with_format_gr ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang,
const char *  format,
const char *  tzone 
)
static

Greek support.

Definition at line 8620 of file say.c.

8621 {
8622  struct timeval when = { t, 0 };
8623  struct ast_tm tm;
8624  int res=0, offset, sndoffset;
8625  char sndfile[256], nextmsg[256];
8626 
8627  if (!format)
8628  format = "AdBY 'digits/at' IMp";
8629 
8630  ast_localtime(&when, &tm, tzone);
8631 
8632  for (offset=0 ; format[offset] != '\0' ; offset++) {
8633  ast_debug(1, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
8634  switch (format[offset]) {
8635  /* NOTE: if you add more options here, please try to be consistent with strftime(3) */
8636  case '\'':
8637  /* Literal name of a sound file */
8638  for (sndoffset = 0; !strchr("\'\0", format[++offset]) && (sndoffset < sizeof(sndfile) - 1) ; sndoffset++) {
8639  sndfile[sndoffset] = format[offset];
8640  }
8641  sndfile[sndoffset] = '\0';
8642  res = wait_file(chan, ints, sndfile, lang);
8643  break;
8644  case 'A':
8645  case 'a':
8646  /* Sunday - Saturday */
8647  snprintf(nextmsg, sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
8648  res = wait_file(chan, ints, nextmsg, lang);
8649  break;
8650  case 'B':
8651  case 'b':
8652  case 'h':
8653  /* January - December */
8654  snprintf(nextmsg, sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
8655  res = wait_file(chan, ints, nextmsg, lang);
8656  break;
8657  case 'd':
8658  case 'e':
8659  /* first - thirtyfirst */
8660  gr_say_number_female(tm.tm_mday, chan, ints, lang);
8661  break;
8662  case 'Y':
8663  /* Year */
8664 
8665  ast_say_number_full_gr(chan, 1900+tm.tm_year, ints, ast_channel_language(chan), -1, -1);
8666  break;
8667  case 'I':
8668  case 'l':
8669  /* 12-Hour */
8670  if (tm.tm_hour == 0)
8671  gr_say_number_female(12, chan, ints, lang);
8672  else if (tm.tm_hour > 12)
8673  gr_say_number_female(tm.tm_hour - 12, chan, ints, lang);
8674  else
8675  gr_say_number_female(tm.tm_hour, chan, ints, lang);
8676  break;
8677  case 'H':
8678  case 'k':
8679  /* 24-Hour */
8680  gr_say_number_female(tm.tm_hour, chan, ints, lang);
8681  break;
8682  case 'M':
8683  /* Minute */
8684  if (tm.tm_min) {
8685  if (!res)
8686  res = ast_streamfile(chan, "digits/kai", lang);
8687  if (!res)
8688  res = ast_waitstream(chan, ints);
8689  if (!res)
8690  res = ast_say_number_full_gr(chan, tm.tm_min, ints, lang, -1, -1);
8691  } else {
8692  if (!res)
8693  res = ast_streamfile(chan, "digits/oclock", lang);
8694  if (!res)
8695  res = ast_waitstream(chan, ints);
8696  }
8697  break;
8698  case 'P':
8699  case 'p':
8700  /* AM/PM */
8701  if (tm.tm_hour > 11)
8702  ast_copy_string(nextmsg, "digits/p-m", sizeof(nextmsg));
8703  else
8704  ast_copy_string(nextmsg, "digits/a-m", sizeof(nextmsg));
8705  res = wait_file(chan, ints, nextmsg, lang);
8706  break;
8707  case 'Q':
8708  /* Shorthand for "Today", "Yesterday", or ABdY */
8709  /* XXX As emphasized elsewhere, this should the native way in your
8710  * language to say the date, with changes in what you say, depending
8711  * upon how recent the date is. XXX */
8712  {
8713  struct timeval now = ast_tvnow();
8714  struct ast_tm tmnow;
8715  time_t beg_today;
8716 
8717  ast_localtime(&now, &tmnow, tzone);
8718  /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
8719  /* In any case, it saves not having to do ast_mktime() */
8720  beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
8721  if (beg_today < t) {
8722  /* Today */
8723  res = wait_file(chan, ints, "digits/today", lang);
8724  } else if (beg_today - 86400 < t) {
8725  /* Yesterday */
8726  res = wait_file(chan, ints, "digits/yesterday", lang);
8727  } else {
8728  res = ast_say_date_with_format_gr(chan, t, ints, lang, "AdBY", tzone);
8729  }
8730  }
8731  break;
8732  case 'q':
8733  /* Shorthand for "" (today), "Yesterday", A (weekday), or ABdY */
8734  /* XXX As emphasized elsewhere, this should the native way in your
8735  * language to say the date, with changes in what you say, depending
8736  * upon how recent the date is. XXX */
8737  {
8738  struct timeval now = ast_tvnow();
8739  struct ast_tm tmnow;
8740  time_t beg_today;
8741 
8742  ast_localtime(&now, &tmnow, tzone);
8743  /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
8744  /* In any case, it saves not having to do ast_mktime() */
8745  beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
8746  if (beg_today < t) {
8747  /* Today */
8748  } else if ((beg_today - 86400) < t) {
8749  /* Yesterday */
8750  res = wait_file(chan, ints, "digits/yesterday", lang);
8751  } else if (beg_today - 86400 * 6 < t) {
8752  /* Within the last week */
8753  res = ast_say_date_with_format_gr(chan, t, ints, lang, "A", tzone);
8754  } else {
8755  res = ast_say_date_with_format_gr(chan, t, ints, lang, "AdBY", tzone);
8756  }
8757  }
8758  break;
8759  case 'R':
8760  res = ast_say_date_with_format_gr(chan, t, ints, lang, "HM", tzone);
8761  break;
8762  case 'S':
8763  /* Seconds */
8764  ast_copy_string(nextmsg, "digits/kai", sizeof(nextmsg));
8765  res = wait_file(chan, ints, nextmsg, lang);
8766  if (!res)
8767  res = ast_say_number_full_gr(chan, tm.tm_sec, ints, lang, -1, -1);
8768  if (!res)
8769  ast_copy_string(nextmsg, "seconds", sizeof(nextmsg));
8770  res = wait_file(chan, ints, nextmsg, lang);
8771  break;
8772  case 'T':
8773  res = ast_say_date_with_format_gr(chan, t, ints, lang, "HMS", tzone);
8774  break;
8775  case ' ':
8776  case ' ':
8777  /* Just ignore spaces and tabs */
8778  break;
8779  default:
8780  /* Unknown character */
8781  ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
8782  }
8783  /* Jump out on DTMF */
8784  if (res) {
8785  break;
8786  }
8787  }
8788  return res;
8789 }
static int ast_say_date_with_format_gr(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
Greek support.
Definition: say.c:8620
static int ast_say_number_full_gr(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
Greek support A list of the files that you need to create -> digits/xilia = "xilia" -> digits/myrio =...
Definition: say.c:8201

References ast_channel_language(), ast_copy_string(), ast_debug, ast_localtime(), ast_log, ast_say_number_full_gr(), ast_streamfile(), ast_tvnow(), ast_waitstream(), format, gr_say_number_female(), LOG_WARNING, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_wday, ast_tm::tm_year, and wait_file().

Referenced by say_date_with_format().

◆ ast_say_date_with_format_he()

int ast_say_date_with_format_he ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang,
const char *  format,
const char *  tzone 
)
static

ast_say_date_with_format_he Say formatted date in Hebrew

ast_say_date_with_format_en for the details of the options

Changes from the English version:

  • don't replicate in here the logic of ast_say_number_full_he
  • year is always 4-digit (because it's simpler)
  • added c, x, and X. Mainly for my tests
  • The standard "long" format used in Hebrew is AdBY, rather than ABdY

    Todo:

Definition at line 5460 of file say.c.

5461 {
5462 #define IL_DATE_STR "AdBY"
5463 #define IL_TIME_STR "HM" /* NOTE: In Hebrew we do not support 12 hours, only 24. No AM or PM exists in the Hebrew language */
5464 #define IL_DATE_STR_FULL IL_DATE_STR " 'digits/at' " IL_TIME_STR
5465  /* TODO: This whole function is cut&paste from
5466  * ast_say_date_with_format_en . Is that considered acceptable?
5467  **/
5468  struct timeval when = { t, 0 };
5469  struct ast_tm tm;
5470  int res = 0, offset, sndoffset;
5471  char sndfile[256], nextmsg[256];
5472 
5473  if (!format) {
5475  }
5476 
5477  ast_localtime(&when, &tm, tzone);
5478 
5479  for (offset = 0; format[offset] != '\0'; offset++) {
5480  ast_debug(1, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
5481  switch (format[offset]) {
5482  /* NOTE: if you add more options here, please try to be consistent with strftime(3) */
5483  case '\'':
5484  /* Literal name of a sound file */
5485  for (sndoffset = 0; !strchr("\'\0", format[++offset]) && (sndoffset < sizeof(sndfile) - 1) ; sndoffset++) {
5486  sndfile[sndoffset] = format[offset];
5487  }
5488  sndfile[sndoffset] = '\0';
5489  res = wait_file(chan, ints, sndfile, lang);
5490  break;
5491  case 'A':
5492  case 'a':
5493  /* Sunday - Saturday */
5494  snprintf(nextmsg, sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
5495  res = wait_file(chan, ints, nextmsg, lang);
5496  break;
5497  case 'B':
5498  case 'b':
5499  case 'h':
5500  /* January - December */
5501  snprintf(nextmsg, sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
5502  res = wait_file(chan, ints, nextmsg, lang);
5503  break;
5504  case 'd':
5505  case 'e': /* Day of the month */
5506  /* I'm not sure exactly what the parameters
5507  * audiofd and ctrlfd to
5508  * ast_say_number_full_he mean, but it seems
5509  * safe to pass -1 there.
5510  *
5511  * At least in one of the paths :-(
5512  */
5513  res = ast_say_number_full_he(chan, tm.tm_mday, ints, lang, "m", -1, -1);
5514  break;
5515  case 'Y': /* Year */
5516  res = ast_say_number_full_he(chan, tm.tm_year + 1900, ints, lang, "f", -1, -1);
5517  break;
5518  case 'I':
5519  case 'l': /* 12-Hour -> we do not support 12 hour based languages in Hebrew */
5520  case 'H':
5521  case 'k': /* 24-Hour */
5522  res = ast_say_number_full_he(chan, tm.tm_hour, ints, lang, "f", -1, -1);
5523  break;
5524  case 'M': /* Minute */
5525  if (tm.tm_min >= 0 && tm.tm_min <= 9) /* say a leading zero if needed */
5526  res = ast_say_number_full_he(chan, 0, ints, lang, "f", -1, -1);
5527  res = ast_say_number_full_he(chan, tm.tm_min, ints, lang, "f", -1, -1);
5528  break;
5529  case 'P':
5530  case 'p':
5531  /* AM/PM - There is no AM/PM in Hebrew... */
5532  break;
5533  case 'Q':
5534  /* Shorthand for "Today", "Yesterday", or "date" */
5535  case 'q':
5536  /* Shorthand for "" (today), "Yesterday", A
5537  * (weekday), or "date" */
5538  /* XXX As emphasized elsewhere, this should the native way in your
5539  * language to say the date, with changes in what you say, depending
5540  * upon how recent the date is. XXX */
5541  {
5542  struct timeval now = ast_tvnow();
5543  struct ast_tm tmnow;
5544  time_t beg_today;
5545  char todo = format[offset]; /* The letter to format*/
5546 
5547  ast_localtime(&now, &tmnow, tzone);
5548  /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
5549  /* In any case, it saves not having to do ast_mktime() */
5550  beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
5551  if (beg_today < t) {
5552  /* Today */
5553  if (todo == 'Q') {
5554  res = wait_file(chan, ints, "digits/today", lang);
5555  }
5556  } else if (beg_today - 86400 < t) {
5557  /* Yesterday */
5558  res = wait_file(chan, ints, "digits/yesterday", lang);
5559  } else if ((todo != 'Q') && (beg_today - 86400 * 6 < t)) {
5560  /* Within the last week */
5561  res = ast_say_date_with_format_he(chan, t, ints, lang, "A", tzone);
5562  } else {
5563  res = ast_say_date_with_format_he(chan, t, ints, lang, IL_DATE_STR, tzone);
5564  }
5565  }
5566  break;
5567  case 'R':
5568  res = ast_say_date_with_format_he(chan, t, ints, lang, "HM", tzone);
5569  break;
5570  case 'S': /* Seconds */
5571  res = ast_say_number_full_he(chan, tm.tm_sec,
5572  ints, lang, "f", -1, -1
5573  );
5574  break;
5575  case 'T':
5576  res = ast_say_date_with_format_he(chan, t, ints, lang, "HMS", tzone);
5577  break;
5578  /* c, x, and X seem useful for testing. Not sure
5579  * if they're good for the general public */
5580  case 'c':
5581  res = ast_say_date_with_format_he(chan, t, ints, lang, IL_DATE_STR_FULL, tzone);
5582  break;
5583  case 'x':
5584  res = ast_say_date_with_format_he(chan, t, ints, lang, IL_DATE_STR, tzone);
5585  break;
5586  case 'X': /* Currently not locale-dependent...*/
5587  res = ast_say_date_with_format_he(chan, t, ints, lang, IL_TIME_STR, tzone);
5588  break;
5589  case ' ':
5590  case ' ':
5591  /* Just ignore spaces and tabs */
5592  break;
5593  default:
5594  /* Unknown character */
5595  ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
5596  }
5597  /* Jump out on DTMF */
5598  if (res) {
5599  break;
5600  }
5601  }
5602  return res;
5603 }
#define IL_DATE_STR
#define IL_DATE_STR_FULL
#define IL_TIME_STR
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)
Definition: say.c:1581
static int ast_say_date_with_format_he(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
ast_say_date_with_format_he Say formatted date in Hebrew
Definition: say.c:5460

References ast_debug, ast_localtime(), ast_log, ast_say_number_full_he(), ast_tvnow(), format, IL_DATE_STR, IL_DATE_STR_FULL, IL_TIME_STR, LOG_WARNING, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_wday, ast_tm::tm_year, and wait_file().

Referenced by say_date_with_format().

◆ ast_say_date_with_format_is()

int ast_say_date_with_format_is ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang,
const char *  format,
const char *  tzone 
)
static

Definition at line 5063 of file say.c.

5064 {
5065  struct timeval when = { t, 0 };
5066  struct ast_tm tm;
5067  int res=0, offset, sndoffset;
5068  char sndfile[256], nextmsg[256];
5069 
5070  if (!format)
5071  format = "A dBY HMS";
5072 
5073  ast_localtime(&when, &tm, tzone);
5074 
5075  for (offset=0 ; format[offset] != '\0' ; offset++) {
5076  ast_debug(1, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
5077  switch (format[offset]) {
5078  /* NOTE: if you add more options here, please try to be consistent with strftime(3) */
5079  case '\'':
5080  /* Literal name of a sound file */
5081  for (sndoffset = 0; !strchr("\'\0", format[++offset]) && (sndoffset < sizeof(sndfile) - 1) ; sndoffset++) {
5082  sndfile[sndoffset] = format[offset];
5083  }
5084  sndfile[sndoffset] = '\0';
5085  res = wait_file(chan, ints, sndfile, lang);
5086  break;
5087  case 'A':
5088  case 'a':
5089  /* Sunday - Saturday */
5090  snprintf(nextmsg, sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
5091  res = wait_file(chan, ints, nextmsg, lang);
5092  break;
5093  case 'B':
5094  case 'b':
5095  case 'h':
5096  /* January - December */
5097  snprintf(nextmsg, sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
5098  res = wait_file(chan, ints, nextmsg, lang);
5099  break;
5100  case 'm':
5101  /* Month enumerated */
5102  res = ast_say_enumeration(chan, (tm.tm_mon + 1), ints, lang, "m");
5103  break;
5104  case 'd':
5105  case 'e':
5106  /* First - Thirtyfirst */
5107  res = ast_say_enumeration(chan, tm.tm_mday, ints, lang, "m");
5108  break;
5109  case 'Y':
5110  /* Year */
5111  {
5112  int year = tm.tm_year + 1900;
5113  if (year > 1999) { /* year 2000 and later */
5114  res = ast_say_number(chan, year, ints, lang, (char *) NULL);
5115  } else {
5116  if (year < 1100) {
5117  /* I'm not going to handle 1100 and prior */
5118  /* We'll just be silent on the year, instead of bombing out. */
5119  } else {
5120  /* year 1100 to 1999. will anybody need this?!? */
5121  /* say 1967 as 'nineteen hundred seven and sixty' */
5122  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", (year / 100) );
5123  res = wait_file(chan, ints, nextmsg, lang);
5124  if (!res) {
5125  res = wait_file(chan, ints, "digits/hundred", lang);
5126  if (!res && year % 100 != 0) {
5127  res = ast_say_number(chan, (year % 100), ints, lang, (char *) NULL);
5128  }
5129  }
5130  }
5131  }
5132  }
5133  break;
5134  case 'I':
5135  case 'l':
5136  /* 12-Hour */
5137  res = wait_file(chan, ints, "digits/oclock", lang);
5138  if (tm.tm_hour == 0)
5139  ast_copy_string(nextmsg, "digits/12", sizeof(nextmsg));
5140  else if (tm.tm_hour > 12)
5141  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_hour - 12);
5142  else
5143  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_hour);
5144  if (!res) {
5145  res = wait_file(chan, ints, nextmsg, lang);
5146  }
5147  break;
5148  case 'H':
5149  /* 24-Hour, single digit hours preceeded by "oh" (0) */
5150  if (tm.tm_hour < 10 && tm.tm_hour > 0) {
5151  res = wait_file(chan, ints, "digits/0", lang);
5152  }
5153  /* FALLTRHU */
5154  case 'k':
5155  /* 24-Hour */
5156  res = ast_say_number(chan, tm.tm_hour, ints, lang, "n");
5157  break;
5158  case 'M':
5159  /* Minute */
5160  if (tm.tm_min > 0 || next_item(&format[offset + 1]) == 'S') { /* zero 'digits/0' only if seconds follow */
5161  if (tm.tm_min < 10)
5162  res = wait_file(chan, ints, "digits/0", lang);
5163  /* Gender depends on whether or not seconds follow */
5164  if (next_item(&format[offset + 1]) == 'S')
5165  res = ast_say_number(chan, tm.tm_min, ints, lang, "f");
5166  else
5167  res = ast_say_number(chan, tm.tm_min, ints, lang, "n");
5168  }
5169  if (!res && next_item(&format[offset + 1]) == 'S') { /* minutes only if seconds follow */
5170  /* Say minute/minutes depending on whether minutes end in 1 */
5171  if ((tm.tm_min % 10 == 1) && (tm.tm_min != 11)) {
5172  res = wait_file(chan, ints, "minute", lang);
5173  } else {
5174  res = wait_file(chan, ints, "minutes", lang);
5175  }
5176  }
5177  break;
5178  case 'P':
5179  case 'p':
5180  /* AM/PM */
5181  if (tm.tm_hour > 11)
5182  ast_copy_string(nextmsg, "digits/p-m", sizeof(nextmsg));
5183  else
5184  ast_copy_string(nextmsg, "digits/a-m", sizeof(nextmsg));
5185  res = wait_file(chan, ints, nextmsg, lang);
5186  break;
5187  case 'Q':
5188  /* Shorthand for "Today", "Yesterday", or AdBY */
5189  /* XXX As emphasized elsewhere, this should the native way in your
5190  * language to say the date, with changes in what you say, depending
5191  * upon how recent the date is. XXX */
5192  {
5193  struct timeval now = ast_tvnow();
5194  struct ast_tm tmnow;
5195  time_t beg_today;
5196 
5197  ast_localtime(&now, &tmnow, tzone);
5198  /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
5199  /* In any case, it saves not having to do ast_mktime() */
5200  beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
5201  if (beg_today < t) {
5202  /* Today */
5203  res = wait_file(chan, ints, "digits/today", lang);
5204  } else if (beg_today - 86400 < t) {
5205  /* Yesterday */
5206  res = wait_file(chan, ints, "digits/yesterday", lang);
5207  } else {
5208  res = ast_say_date_with_format_is(chan, t, ints, lang, "AdBY", tzone);
5209  }
5210  }
5211  break;
5212  case 'q':
5213  /* Shorthand for "" (today), "Yesterday", A (weekday), or AdBY */
5214  /* XXX As emphasized elsewhere, this should the native way in your
5215  * language to say the date, with changes in what you say, depending
5216  * upon how recent the date is. XXX */
5217  {
5218  struct timeval now = ast_tvnow();
5219  struct ast_tm tmnow;
5220  time_t beg_today;
5221 
5222  ast_localtime(&now, &tmnow, tzone);
5223  /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
5224  /* In any case, it saves not having to do ast_mktime() */
5225  beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
5226  if (beg_today < t) {
5227  /* Today */
5228  } else if ((beg_today - 86400) < t) {
5229  /* Yesterday */
5230  res = wait_file(chan, ints, "digits/yesterday", lang);
5231  } else if (beg_today - 86400 * 6 < t) {
5232  /* Within the last week */
5233  res = ast_say_date_with_format_is(chan, t, ints, lang, "A", tzone);
5234  } else {
5235  res = ast_say_date_with_format_is(chan, t, ints, lang, "AdBY", tzone);
5236  }
5237  }
5238  break;
5239  case 'R':
5240  res = ast_say_date_with_format_is(chan, t, ints, lang, "HM", tzone);
5241  break;
5242  case 'S':
5243  /* Seconds */
5244  res = wait_file(chan, ints, "digits/and", lang);
5245  if (!res) {
5246  res = ast_say_number(chan, tm.tm_sec, ints, lang, "f");
5247  /* Say minute/minutes depending on whether seconds end in 1 */
5248  if (!res && (tm.tm_sec % 10 == 1) && (tm.tm_sec != 11)) {
5249  res = wait_file(chan, ints, "second", lang);
5250  } else {
5251  res = wait_file(chan, ints, "seconds", lang);
5252  }
5253  }
5254  break;
5255  case 'T':
5256  res = ast_say_date_with_format_is(chan, t, ints, lang, "HMS", tzone);
5257  break;
5258  case ' ':
5259  case ' ':
5260  /* Just ignore spaces and tabs */
5261  break;
5262  default:
5263  /* Unknown character */
5264  ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
5265  }
5266  /* Jump out on DTMF */
5267  if (res) {
5268  break;
5269  }
5270  }
5271  return res;
5272 }
static int ast_say_date_with_format_is(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
Definition: say.c:5063

References ast_copy_string(), ast_debug, ast_localtime(), ast_log, ast_say_enumeration(), ast_say_number(), ast_tvnow(), format, LOG_WARNING, next_item(), NULL, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_wday, ast_tm::tm_year, and wait_file().

Referenced by say_date_with_format().

◆ ast_say_date_with_format_it()

int ast_say_date_with_format_it ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang,
const char *  format,
const char *  tzone 
)
static

Italian syntax.

Definition at line 5994 of file say.c.

5995 {
5996  struct timeval when = { t, 0 };
5997  struct ast_tm tm;
5998  int res=0, offset, sndoffset;
5999  char sndfile[256], nextmsg[256];
6000 
6001  if (format == NULL)
6002  format = "AdB 'digits/at' IMp";
6003 
6004  ast_localtime(&when, &tm, tzone);
6005 
6006  for (offset=0 ; format[offset] != '\0' ; offset++) {
6007  ast_debug(1, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
6008  switch (format[offset]) {
6009  /* NOTE: if you add more options here, please try to be consistent with strftime(3) */
6010  case '\'':
6011  /* Literal name of a sound file */
6012  for (sndoffset = 0; !strchr("\'\0", format[++offset]) && (sndoffset < sizeof(sndfile) - 1) ; sndoffset++) {
6013  sndfile[sndoffset] = format[offset];
6014  }
6015  sndfile[sndoffset] = '\0';
6016  res = wait_file(chan, ints, sndfile, lang);
6017  break;
6018  case 'A':
6019  case 'a':
6020  /* Sunday - Saturday */
6021  snprintf(nextmsg, sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
6022  res = wait_file(chan, ints, nextmsg, lang);
6023  break;
6024  case 'B':
6025  case 'b':
6026  case 'h':
6027  /* January - December */
6028  snprintf(nextmsg, sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
6029  res = wait_file(chan, ints, nextmsg, lang);
6030  break;
6031  case 'm':
6032  /* First - Twelfth */
6033  snprintf(nextmsg, sizeof(nextmsg), "digits/h-%d", tm.tm_mon +1);
6034  res = wait_file(chan, ints, nextmsg, lang);
6035  break;
6036  case 'd':
6037  case 'e':
6038  /* First day of the month is spelled as ordinal */
6039  if (tm.tm_mday == 1) {
6040  snprintf(nextmsg, sizeof(nextmsg), "digits/h-%d", tm.tm_mday);
6041  res = wait_file(chan, ints, nextmsg, lang);
6042  } else {
6043  if (!res) {
6044  res = ast_say_number(chan, tm.tm_mday, ints, lang, (char *) NULL);
6045  }
6046  }
6047  break;
6048  case 'Y':
6049  /* Year */
6050  if (tm.tm_year > 99) {
6051  res = wait_file(chan, ints, "digits/ore-2000", lang);
6052  if (tm.tm_year > 100) {
6053  if (!res) {
6054  /* This works until the end of 2021 */
6055  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_year - 100);
6056  res = wait_file(chan, ints, nextmsg, lang);
6057  }
6058  }
6059  } else {
6060  if (tm.tm_year < 1) {
6061  /* I'm not going to handle 1900 and prior */
6062  /* We'll just be silent on the year, instead of bombing out. */
6063  } else {
6064  res = wait_file(chan, ints, "digits/ore-1900", lang);
6065  if ((!res) && (tm.tm_year != 0)) {
6066  if (tm.tm_year <= 21) {
6067  /* 1910 - 1921 */
6068  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_year);
6069  res = wait_file(chan, ints, nextmsg, lang);
6070  } else {
6071  /* 1922 - 1999, but sounds badly in 1928, 1931, 1938, etc... */
6072  int ten, one;
6073  ten = tm.tm_year / 10;
6074  one = tm.tm_year % 10;
6075  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", ten * 10);
6076  res = wait_file(chan, ints, nextmsg, lang);
6077  if (!res) {
6078  if (one != 0) {
6079  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", one);
6080  res = wait_file(chan, ints, nextmsg, lang);
6081  }
6082  }
6083  }
6084  }
6085  }
6086  }
6087  break;
6088  case 'I':
6089  case 'l':
6090  /* 12-Hour */
6091  if (tm.tm_hour == 0) {
6092  ast_copy_string(nextmsg, "digits/12", sizeof(nextmsg));
6093  } else if (tm.tm_hour > 12) {
6094  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_hour - 12);
6095  } else {
6096  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_hour);
6097  }
6098  res = wait_file(chan, ints, nextmsg, lang);
6099  break;
6100  case 'H':
6101  case 'k':
6102  /* 24-Hour */
6103  if (tm.tm_hour == 0) {
6104  res = wait_file(chan, ints, "digits/ore-mezzanotte", lang);
6105  } else if (tm.tm_hour == 1) {
6106  res = wait_file(chan, ints, "digits/ore-una", lang);
6107  } else {
6108  res = ast_say_number(chan, tm.tm_hour, ints, lang, (char *) NULL);
6109  }
6110  break;
6111  case 'M':
6112  /* Minute */
6113  res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
6114  break;
6115  case 'P':
6116  case 'p':
6117  /* AM/PM */
6118  if (tm.tm_hour > 11) {
6119  ast_copy_string(nextmsg, "digits/p-m", sizeof(nextmsg));
6120  } else {
6121  ast_copy_string(nextmsg, "digits/a-m", sizeof(nextmsg));
6122  }
6123  res = wait_file(chan, ints, nextmsg, lang);
6124  break;
6125  case 'Q':
6126  /* Shorthand for "Today", "Yesterday", or ABdY */
6127  /* XXX As emphasized elsewhere, this should the native way in your
6128  * language to say the date, with changes in what you say, depending
6129  * upon how recent the date is. XXX */
6130  {
6131  struct timeval now = ast_tvnow();
6132  struct ast_tm tmnow;
6133  time_t beg_today;
6134 
6135  ast_localtime(&now, &tmnow, tzone);
6136  /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
6137  /* In any case, it saves not having to do ast_mktime() */
6138  beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
6139  if (beg_today < t) {
6140  /* Today */
6141  res = wait_file(chan, ints, "digits/today", lang);
6142  } else if (beg_today - 86400 < t) {
6143  /* Yesterday */
6144  res = wait_file(chan, ints, "digits/yesterday", lang);
6145  } else {
6146  res = ast_say_date_with_format_it(chan, t, ints, lang, "AdB", tzone);
6147  }
6148  }
6149  break;
6150  case 'q':
6151  /* Shorthand for "" (today), "Yesterday", A (weekday), or ABdY */
6152  {
6153  struct timeval now = ast_tvnow();
6154  struct ast_tm tmnow;
6155  time_t beg_today;
6156 
6157  ast_localtime(&now, &tmnow, tzone);
6158  /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
6159  /* In any case, it saves not having to do ast_mktime() */
6160  beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
6161  if (beg_today < t) {
6162  /* Today */
6163  } else if ((beg_today - 86400) < t) {
6164  /* Yesterday */
6165  res = wait_file(chan, ints, "digits/yesterday", lang);
6166  } else if (beg_today - 86400 * 6 < t) {
6167  /* Within the last week */
6168  res = ast_say_date_with_format_it(chan, t, ints, lang, "A", tzone);
6169  } else {
6170  res = ast_say_date_with_format_it(chan, t, ints, lang, "AdB", tzone);
6171  }
6172  }
6173  break;
6174  case 'R':
6175  res = ast_say_date_with_format_it(chan, t, ints, lang, "HM", tzone);
6176  break;
6177  case 'S':
6178  /* Seconds */
6179  if (tm.tm_sec == 0) {
6180  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_sec);
6181  res = wait_file(chan, ints, nextmsg, lang);
6182  } else if (tm.tm_sec < 10) {
6183  res = wait_file(chan, ints, "digits/oh", lang);
6184  if (!res) {
6185  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_sec);
6186  res = wait_file(chan, ints, nextmsg, lang);
6187  }
6188  } else if ((tm.tm_sec < 21) || (tm.tm_sec % 10 == 0)) {
6189  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_sec);
6190  res = wait_file(chan, ints, nextmsg, lang);
6191  } else {
6192  int ten, one;
6193  ten = (tm.tm_sec / 10) * 10;
6194  one = (tm.tm_sec % 10);
6195  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", ten);
6196  res = wait_file(chan, ints, nextmsg, lang);
6197  if (!res) {
6198  /* Fifty, not fifty-zero */
6199  if (one != 0) {
6200  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", one);
6201  res = wait_file(chan, ints, nextmsg, lang);
6202  }
6203  }
6204  }
6205  break;
6206  case 'T':
6207  res = ast_say_date_with_format_it(chan, t, ints, lang, "HMS", tzone);
6208  break;
6209  case ' ':
6210  case ' ':
6211  /* Just ignore spaces and tabs */
6212  break;
6213  default:
6214  /* Unknown character */
6215  ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
6216  }
6217  /* Jump out on DTMF */
6218  if (res) {
6219  break;
6220  }
6221  }
6222  return res;
6223 }
static int ast_say_date_with_format_it(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
Italian syntax.
Definition: say.c:5994

References ast_copy_string(), ast_debug, ast_localtime(), ast_log, ast_say_number(), ast_tvnow(), format, LOG_WARNING, NULL, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_wday, ast_tm::tm_year, and wait_file().

Referenced by say_date_with_format().

◆ ast_say_date_with_format_ja()

int ast_say_date_with_format_ja ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang,
const char *  format,
const char *  tzone 
)
static

Definition at line 8792 of file say.c.

8793 {
8794  struct timeval tv = { time, 0 };
8795  struct ast_tm tm;
8796  int res = 0, offset, sndoffset;
8797  char sndfile[256], nextmsg[256];
8798 
8799  if (!format)
8800  format = "YbdAPIMS";
8801 
8802  ast_localtime(&tv, &tm, timezone);
8803 
8804  for (offset = 0; format[offset] != '\0'; offset++) {
8805  ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
8806  switch (format[offset]) {
8807  /* NOTE: if you add more options here, please try to be consistent with strftime(3) */
8808  case '\'':
8809  /* Literal name of a sound file */
8810  for (sndoffset = 0; (format[++offset] != '\'') && (sndoffset < sizeof(sndfile) - 1) ; sndoffset++) {
8811  sndfile[sndoffset] = format[offset];
8812  }
8813  sndfile[sndoffset] = '\0';
8814  res = wait_file(chan,ints,sndfile,lang);
8815  break;
8816  case 'A':
8817  case 'a':
8818  /* Sunday - Saturday */
8819  snprintf(nextmsg,sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
8820  res = wait_file(chan,ints,nextmsg,lang);
8821  break;
8822  case 'B':
8823  case 'b':
8824  case 'h':
8825  /* January - December */
8826  snprintf(nextmsg,sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
8827  res = wait_file(chan,ints,nextmsg,lang);
8828  break;
8829  case 'd':
8830  case 'e':
8831  /* First - Thirtyfirst */
8832  if (tm.tm_mday < 21) {
8833  snprintf(nextmsg,sizeof(nextmsg), "digits/h-%d_2", tm.tm_mday);
8834  res = wait_file(chan,ints,nextmsg,lang);
8835  } else if (tm.tm_mday < 30) {
8836  /* Between 21 and 29 - two sounds */
8837  res = wait_file(chan,ints, "digits/20",lang);
8838  if (!res) {
8839  snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_mday - 20);
8840  res = wait_file(chan,ints,nextmsg,lang);
8841  }
8842  res = wait_file(chan,ints, "digits/nichi",lang);
8843  } else if (tm.tm_mday == 30) {
8844  /* 30 */
8845  res = wait_file(chan,ints, "digits/h-30_2",lang);
8846  } else {
8847  /* 31 */
8848  res = wait_file(chan,ints, "digits/30",lang);
8849  res = wait_file(chan,ints, "digits/1",lang);
8850  res = wait_file(chan,ints, "digits/nichi",lang);
8851  }
8852  break;
8853  case 'Y':
8854  /* Year */
8855  if (tm.tm_year > 99) {
8856  res = wait_file(chan,ints, "digits/2",lang);
8857  if (!res) {
8858  res = wait_file(chan,ints, "digits/thousand",lang);
8859  }
8860  if (tm.tm_year > 100) {
8861  if (!res) {
8862  /* This works until the end of 2020 */
8863  snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_year - 100);
8864  res = wait_file(chan,ints,nextmsg,lang);
8865  }
8866  }
8867  } else {
8868  if (tm.tm_year < 1) {
8869  /* I'm not going to handle 1900 and prior */
8870  /* We'll just be silent on the year, instead of bombing out. */
8871  } else {
8872  res = wait_file(chan,ints, "digits/19",lang);
8873  if (!res) {
8874  if (tm.tm_year <= 9) {
8875  /* 1901 - 1909 */
8876  res = wait_file(chan,ints, "digits/oh",lang);
8877  if (!res) {
8878  snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_year);
8879  res = wait_file(chan,ints,nextmsg,lang);
8880  }
8881  } else if (tm.tm_year <= 20) {
8882  /* 1910 - 1920 */
8883  snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_year);
8884  res = wait_file(chan,ints,nextmsg,lang);
8885  } else {
8886  /* 1921 - 1999 */
8887  int ten, one;
8888  ten = tm.tm_year / 10;
8889  one = tm.tm_year % 10;
8890  snprintf(nextmsg,sizeof(nextmsg), "digits/%d", ten * 10);
8891  res = wait_file(chan,ints,nextmsg,lang);
8892  if (!res) {
8893  if (one != 0) {
8894  snprintf(nextmsg,sizeof(nextmsg), "digits/%d", one);
8895  res = wait_file(chan,ints,nextmsg,lang);
8896  }
8897  }
8898  }
8899  }
8900  }
8901  }
8902  res = wait_file(chan,ints, "digits/nen",lang);
8903  break;
8904  case 'P':
8905  case 'p':
8906  /* AM/PM */
8907  if (tm.tm_hour > 11)
8908  snprintf(nextmsg,sizeof(nextmsg), "digits/p-m");
8909  else
8910  snprintf(nextmsg,sizeof(nextmsg), "digits/a-m");
8911  res = wait_file(chan,ints,nextmsg,lang);
8912  break;
8913  case 'I':
8914  case 'l':
8915  /* 12-Hour */
8916  if (tm.tm_hour == 0)
8917  snprintf(nextmsg,sizeof(nextmsg), "digits/12");
8918  else if (tm.tm_hour == 9 || tm.tm_hour == 21)
8919  snprintf(nextmsg,sizeof(nextmsg), "digits/9_2");
8920  else if (tm.tm_hour > 12)
8921  snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour - 12);
8922  else
8923  snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour);
8924  res = wait_file(chan,ints,nextmsg,lang);
8925  if(!res) res = wait_file(chan,ints, "digits/ji",lang);
8926  break;
8927  case 'H':
8928  case 'k':
8929  if (!res) {
8930  if (tm.tm_hour != 0) {
8931  int remainder = tm.tm_hour;
8932  if (tm.tm_hour > 20) {
8933  res = wait_file(chan,ints, "digits/20",lang);
8934  remainder -= 20;
8935  }
8936  if (!res) {
8937  snprintf(nextmsg,sizeof(nextmsg), "digits/%d", remainder);
8938  res = wait_file(chan,ints,nextmsg,lang);
8939  }
8940  }
8941  }
8942  res = wait_file(chan,ints, "digits/ji",lang);
8943  break;
8944  case 'M':
8945  /* Minute */
8946  if ((tm.tm_min < 21) || (tm.tm_min % 10 == 0)) {
8947  snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_min);
8948  res = wait_file(chan,ints,nextmsg,lang);
8949  } else {
8950  int ten, one;
8951  ten = (tm.tm_min / 10) * 10;
8952  one = (tm.tm_min % 10);
8953  snprintf(nextmsg,sizeof(nextmsg), "digits/%d", ten);
8954  res = wait_file(chan,ints,nextmsg,lang);
8955  if (!res) {
8956  /* Fifty, not fifty-zero */
8957  if (one != 0) {
8958  snprintf(nextmsg,sizeof(nextmsg), "digits/%d", one);
8959  res = wait_file(chan,ints,nextmsg,lang);
8960  }
8961  }
8962  }
8963  res = wait_file(chan,ints, "digits/fun",lang);
8964  break;
8965  case 'Q':
8966  /* Shorthand for "Today", "Yesterday", or ABdY */
8967  {
8968  struct timeval now;
8969  struct ast_tm tmnow;
8970  time_t beg_today;
8971 
8972  gettimeofday(&now,NULL);
8973  ast_localtime(&now,&tmnow,timezone);
8974  /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
8975  /* In any case, it saves not having to do ast_mktime() */
8976  beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
8977  if (beg_today < time) {
8978  /* Today */
8979  res = wait_file(chan,ints, "digits/today",lang);
8980  } else if (beg_today - 86400 < time) {
8981  /* Yesterday */
8982  res = wait_file(chan,ints, "digits/yesterday",lang);
8983  } else {
8984  res = ast_say_date_with_format(chan, time, ints, lang, "ABdY", timezone);
8985  }
8986  }
8987  break;
8988  case 'q':
8989  /* Shorthand for "" (today), "Yesterday", A (weekday), or ABdY */
8990  {
8991  struct timeval now;
8992  struct ast_tm tmnow;
8993  time_t beg_today;
8994 
8995  gettimeofday(&now,NULL);
8996  ast_localtime(&now,&tmnow,timezone);
8997  /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
8998  /* In any case, it saves not having to do ast_mktime() */
8999  beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
9000  if (beg_today < time) {
9001  /* Today */
9002  } else if ((beg_today - 86400) < time) {
9003  /* Yesterday */
9004  res = wait_file(chan,ints, "digits/yesterday",lang);
9005  } else if (beg_today - 86400 * 6 < time) {
9006  /* Within the last week */
9007  res = ast_say_date_with_format(chan, time, ints, lang, "A", timezone);
9008  } else {
9009  res = ast_say_date_with_format(chan, time, ints, lang, "ABdY", timezone);
9010  }
9011  }
9012  break;
9013  case 'R':
9014  res = ast_say_date_with_format(chan, time, ints, lang, "HM", timezone);
9015  break;
9016  case 'S':
9017  /* Seconds */
9018  if (tm.tm_sec == 0) {
9019  snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
9020  res = wait_file(chan,ints,nextmsg,lang);
9021  } else if ((tm.tm_sec < 21) || (tm.tm_sec % 10 == 0)) {
9022  snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
9023  res = wait_file(chan,ints,nextmsg,lang);
9024  } else {
9025  int ten, one;
9026  ten = (tm.tm_sec / 10) * 10;
9027  one = (tm.tm_sec % 10);
9028  snprintf(nextmsg,sizeof(nextmsg), "digits/%d", ten);
9029  res = wait_file(chan,ints,nextmsg,lang);
9030  if (!res) {
9031  /* Fifty, not fifty-zero */
9032  if (one != 0) {
9033  snprintf(nextmsg,sizeof(nextmsg), "digits/%d", one);
9034  res = wait_file(chan,ints,nextmsg,lang);
9035  }
9036  }
9037  }
9038  res = wait_file(chan,ints, "digits/byou",lang);
9039  break;
9040  case 'T':
9041  res = ast_say_date_with_format(chan, time, ints, lang, "HMS", timezone);
9042  break;
9043  case ' ':
9044  case ' ':
9045  /* Just ignore spaces and tabs */
9046  break;
9047  default:
9048  /* Unknown character */
9049  ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
9050  }
9051  /* Jump out on DTMF */
9052  if (res) {
9053  break;
9054  }
9055  }
9056  return res;
9057 }
#define LOG_DEBUG

References ast_localtime(), ast_log, ast_say_date_with_format, format, LOG_DEBUG, LOG_WARNING, NULL, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_wday, ast_tm::tm_year, and wait_file().

Referenced by say_date_with_format().

◆ ast_say_date_with_format_nl()

int ast_say_date_with_format_nl ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang,
const char *  format,
const char *  tzone 
)
static

Dutch syntax.

Definition at line 6226 of file say.c.

6227 {
6228  struct timeval when = { t, 0 };
6229  struct ast_tm tm;
6230  int res=0, offset, sndoffset;
6231  char sndfile[256], nextmsg[256];
6232 
6233  if (format == NULL)
6234  format = "AdBY 'digits/at' IMp";
6235 
6236  ast_localtime(&when, &tm, tzone);
6237 
6238  for (offset=0 ; format[offset] != '\0' ; offset++) {
6239  ast_debug(1, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
6240  switch (format[offset]) {
6241  /* NOTE: if you add more options here, please try to be consistent with strftime(3) */
6242  case '\'':
6243  /* Literal name of a sound file */
6244  for (sndoffset = 0; !strchr("\'\0", format[++offset]) && (sndoffset < sizeof(sndfile) - 1) ; sndoffset++) {
6245  sndfile[sndoffset] = format[offset];
6246  }
6247  sndfile[sndoffset] = '\0';
6248  res = wait_file(chan, ints, sndfile, lang);
6249  break;
6250  case 'A':
6251  case 'a':
6252  /* Sunday - Saturday */
6253  snprintf(nextmsg, sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
6254  res = wait_file(chan, ints, nextmsg, lang);
6255  break;
6256  case 'B':
6257  case 'b':
6258  case 'h':
6259  /* January - December */
6260  snprintf(nextmsg, sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
6261  res = wait_file(chan, ints, nextmsg, lang);
6262  break;
6263  case 'm':
6264  /* First - Twelfth */
6265  snprintf(nextmsg, sizeof(nextmsg), "digits/h-%d", tm.tm_mon +1);
6266  res = wait_file(chan, ints, nextmsg, lang);
6267  break;
6268  case 'd':
6269  case 'e':
6270  /* First - Thirtyfirst */
6271  res = ast_say_number(chan, tm.tm_mday, ints, lang, NULL);
6272  break;
6273  case 'Y':
6274  /* Year */
6275  if (tm.tm_year > 99) {
6276  res = wait_file(chan, ints, "digits/2", lang);
6277  if (!res) {
6278  res = wait_file(chan, ints, "digits/thousand", lang);
6279  }
6280  if (tm.tm_year > 100) {
6281  if (!res) {
6282  res = ast_say_number(chan, tm.tm_year - 100, ints, lang, (char *) NULL);
6283  }
6284  }
6285  } else {
6286  if (tm.tm_year < 1) {
6287  /* I'm not going to handle 1900 and prior */
6288  /* We'll just be silent on the year, instead of bombing out. */
6289  } else {
6290  res = wait_file(chan, ints, "digits/19", lang);
6291  if (!res) {
6292  if (tm.tm_year <= 9) {
6293  /* 1901 - 1909 */
6294  res = wait_file(chan, ints, "digits/oh", lang);
6295  if (!res) {
6296  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_year);
6297  res = wait_file(chan, ints, nextmsg, lang);
6298  }
6299  } else if (tm.tm_year <= 20) {
6300  /* 1910 - 1920 */
6301  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_year);
6302  res = wait_file(chan, ints, nextmsg, lang);
6303  } else {
6304  /* 1921 - 1999 */
6305  int ten, one;
6306  ten = tm.tm_year / 10;
6307  one = tm.tm_year % 10;
6308  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", ten * 10);
6309  res = wait_file(chan, ints, nextmsg, lang);
6310  if (!res) {
6311  if (one != 0) {
6312  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", one);
6313  res = wait_file(chan, ints, nextmsg, lang);
6314  }
6315  }
6316  }
6317  }
6318  }
6319  }
6320  break;
6321  case 'I':
6322  case 'l':
6323  /* 12-Hour */
6324  if (tm.tm_hour == 0)
6325  ast_copy_string(nextmsg, "digits/12", sizeof(nextmsg));
6326  else if (tm.tm_hour > 12)
6327  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_hour - 12);
6328  else
6329  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_hour);
6330  res = wait_file(chan, ints, nextmsg, lang);
6331  break;
6332  case 'H':
6333  case 'k':
6334  /* 24-Hour */
6335  res = ast_say_number(chan, tm.tm_hour, ints, lang, (char *) NULL);
6336  if (!res) {
6337  res = wait_file(chan, ints, "digits/nl-uur", lang);
6338  }
6339  break;
6340  case 'M':
6341  /* Minute */
6342  res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
6343  break;
6344  case 'P':
6345  case 'p':
6346  /* AM/PM */
6347  if (tm.tm_hour > 11)
6348  ast_copy_string(nextmsg, "digits/p-m", sizeof(nextmsg));
6349  else
6350  ast_copy_string(nextmsg, "digits/a-m", sizeof(nextmsg));
6351  res = wait_file(chan, ints, nextmsg, lang);
6352  break;
6353  case 'Q':
6354  /* Shorthand for "Today", "Yesterday", or AdBY */
6355  /* XXX As emphasized elsewhere, this should the native way in your
6356  * language to say the date, with changes in what you say, depending
6357  * upon how recent the date is. XXX */
6358  {
6359  struct timeval now = ast_tvnow();
6360  struct ast_tm tmnow;
6361  time_t beg_today;
6362 
6363  ast_localtime(&now, &tmnow, tzone);
6364  /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
6365  /* In any case, it saves not having to do ast_mktime() */
6366  beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
6367  if (beg_today < t) {
6368  /* Today */
6369  res = wait_file(chan, ints, "digits/today", lang);
6370  } else if (beg_today - 86400 < t) {
6371  /* Yesterday */
6372  res = wait_file(chan, ints, "digits/yesterday", lang);
6373  } else {
6374  res = ast_say_date_with_format_nl(chan, t, ints, lang, "AdBY", tzone);
6375  }
6376  }
6377  break;
6378  case 'q':
6379  /* Shorthand for "" (today), "Yesterday", A (weekday), or AdBY */
6380  {
6381  struct timeval now = ast_tvnow();
6382  struct ast_tm tmnow;
6383  time_t beg_today;
6384 
6385  ast_localtime(&now, &tmnow, tzone);
6386  /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
6387  /* In any case, it saves not having to do ast_mktime() */
6388  beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
6389  if (beg_today < t) {
6390  /* Today */
6391  } else if ((beg_today - 86400) < t) {
6392  /* Yesterday */
6393  res = wait_file(chan, ints, "digits/yesterday", lang);
6394  } else if (beg_today - 86400 * 6 < t) {
6395  /* Within the last week */
6396  res = ast_say_date_with_format_nl(chan, t, ints, lang, "A", tzone);
6397  } else {
6398  res = ast_say_date_with_format_nl(chan, t, ints, lang, "AdBY", tzone);
6399  }
6400  }
6401  break;
6402  case 'R':
6403  res = ast_say_date_with_format_nl(chan, t, ints, lang, "HM", tzone);
6404  break;
6405  case 'S':
6406  /* Seconds */
6407  res = ast_say_number(chan, tm.tm_sec, ints, lang, (char *) NULL);
6408  break;
6409  case 'T':
6410  res = ast_say_date_with_format_nl(chan, t, ints, lang, "HMS", tzone);
6411  break;
6412  case ' ':
6413  case ' ':
6414  /* Just ignore spaces and tabs */
6415  break;
6416  default:
6417  /* Unknown character */
6418  ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
6419  }
6420  /* Jump out on DTMF */
6421  if (res) {
6422  break;
6423  }
6424  }
6425  return res;
6426 }
static int ast_say_date_with_format_nl(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
Dutch syntax.
Definition: say.c:6226

References ast_copy_string(), ast_debug, ast_localtime(), ast_log, ast_say_number(), ast_tvnow(), format, LOG_WARNING, NULL, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_wday, ast_tm::tm_year, and wait_file().

Referenced by say_date_with_format().

◆ ast_say_date_with_format_pl()

int ast_say_date_with_format_pl ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang,
const char *  format,
const char *  tzone 
)
static

Polish syntax.

Definition at line 6429 of file say.c.

6430 {
6431  struct timeval when = { thetime, 0 };
6432  struct ast_tm tm;
6433  int res=0, offset, sndoffset;
6434  char sndfile[256], nextmsg[256];
6435 
6436  ast_localtime(&when, &tm, tzone);
6437 
6438  for (offset = 0 ; format[offset] != '\0' ; offset++) {
6439  int remaining;
6440  ast_debug(1, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
6441  switch (format[offset]) {
6442  /* NOTE: if you add more options here, please try to be consistent with strftime(3) */
6443  case '\'':
6444  /* Literal name of a sound file */
6445  for (sndoffset = 0; !strchr("\'\0", format[++offset]) && (sndoffset < sizeof(sndfile) - 1) ; sndoffset++) {
6446  sndfile[sndoffset] = format[offset];
6447  }
6448  sndfile[sndoffset] = '\0';
6449  res = wait_file(chan, ints, sndfile, lang);
6450  break;
6451  case 'A':
6452  case 'a':
6453  /* Sunday - Saturday */
6454  snprintf(nextmsg, sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
6455  res = wait_file(chan, ints, nextmsg, lang);
6456  break;
6457  case 'B':
6458  case 'b':
6459  case 'h':
6460  /* January - December */
6461  snprintf(nextmsg, sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
6462  res = wait_file(chan, ints, nextmsg, lang);
6463  break;
6464  case 'm':
6465  /* Month enumerated */
6466  res = ast_say_enumeration(chan, (tm.tm_mon + 1), ints, lang, NULL);
6467  break;
6468  case 'd':
6469  case 'e':
6470  /* First - Thirtyfirst */
6471  remaining = tm.tm_mday;
6472  if (tm.tm_mday > 30) {
6473  res = wait_file(chan, ints, "digits/h-30", lang);
6474  remaining -= 30;
6475  }
6476  if (tm.tm_mday > 20 && tm.tm_mday < 30) {
6477  res = wait_file(chan, ints, "digits/h-20", lang);
6478  remaining -= 20;
6479  }
6480  if (!res) {
6481  snprintf(nextmsg, sizeof(nextmsg), "digits/h-%d", remaining);
6482  res = wait_file(chan, ints, nextmsg, lang);
6483  }
6484  break;
6485  case 'Y':
6486  /* Year */
6487  if (tm.tm_year > 100) {
6488  res = wait_file(chan, ints, "digits/2", lang);
6489  if (!res)
6490  res = wait_file(chan, ints, "digits/1000.2", lang);
6491  if (tm.tm_year > 100) {
6492  if (!res)
6493  res = ast_say_enumeration(chan, tm.tm_year - 100, ints, lang, NULL);
6494  }
6495  } else if (tm.tm_year == 100) {
6496  res = wait_file(chan, ints, "digits/h-2000", lang);
6497  } else {
6498  if (tm.tm_year < 1) {
6499  /* I'm not going to handle 1900 and prior */
6500  /* We'll just be silent on the year, instead of bombing out. */
6501  break;
6502  } else {
6503  res = wait_file(chan, ints, "digits/1000", lang);
6504  if (!res) {
6505  wait_file(chan, ints, "digits/900", lang);
6506  res = ast_say_enumeration(chan, tm.tm_year, ints, lang, NULL);
6507  }
6508  }
6509  }
6510  if (!res)
6511  wait_file(chan, ints, "digits/year", lang);
6512  break;
6513  case 'I':
6514  case 'l':
6515  /* 12-Hour */
6516  if (tm.tm_hour == 0)
6517  ast_copy_string(nextmsg, "digits/t-12", sizeof(nextmsg));
6518  else if (tm.tm_hour > 12)
6519  snprintf(nextmsg, sizeof(nextmsg), "digits/t-%d", tm.tm_hour - 12);
6520  else
6521  snprintf(nextmsg, sizeof(nextmsg), "digits/t-%d", tm.tm_hour);
6522 
6523  res = wait_file(chan, ints, nextmsg, lang);
6524  break;
6525  case 'H':
6526  case 'k':
6527  /* 24-Hour */
6528  if (tm.tm_hour != 0) {
6529  snprintf(nextmsg, sizeof(nextmsg), "digits/t-%d", tm.tm_hour);
6530  res = wait_file(chan, ints, nextmsg, lang);
6531  } else
6532  res = wait_file(chan, ints, "digits/t-24", lang);
6533  break;
6534  case 'M':
6535  case 'N':
6536  /* Minute */
6537  if (tm.tm_min == 0) {
6538  if (format[offset] == 'M') {
6539  res = wait_file(chan, ints, "digits/oclock", lang);
6540  } else {
6541  res = wait_file(chan, ints, "digits/100", lang);
6542  }
6543  } else
6544  res = ast_say_number(chan, tm.tm_min, ints, lang, "f");
6545  break;
6546  case 'P':
6547  case 'p':
6548  /* AM/PM */
6549  if (tm.tm_hour > 11)
6550  ast_copy_string(nextmsg, "digits/p-m", sizeof(nextmsg));
6551  else
6552  ast_copy_string(nextmsg, "digits/a-m", sizeof(nextmsg));
6553  res = wait_file(chan, ints, nextmsg, lang);
6554  break;
6555  case 'Q':
6556  /* Shorthand for "Today", "Yesterday", or AdBY */
6557  {
6558  struct timeval now = ast_tvnow();
6559  struct ast_tm tmnow;
6560  time_t beg_today;
6561 
6562  ast_localtime(&now, &tmnow, tzone);
6563  /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
6564  /* In any case, it saves not having to do ast_mktime() */
6565  beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
6566  if (beg_today < thetime) {
6567  /* Today */
6568  res = wait_file(chan, ints, "digits/today", lang);
6569  } else if (beg_today - 86400 < thetime) {
6570  /* Yesterday */
6571  res = wait_file(chan, ints, "digits/yesterday", lang);
6572  } else {
6573  res = ast_say_date_with_format(chan, thetime, ints, lang, "AdBY", tzone);
6574  }
6575  }
6576  break;
6577  case 'q':
6578  /* Shorthand for "" (today), "Yesterday", A (weekday), or AdBY */
6579  {
6580  struct timeval now = ast_tvnow();
6581  struct ast_tm tmnow;
6582  time_t beg_today;
6583 
6584  ast_localtime(&now, &tmnow, tzone);
6585  /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
6586  /* In any case, it saves not having to do ast_mktime() */
6587  beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
6588  if (beg_today < thetime) {
6589  /* Today */
6590  } else if ((beg_today - 86400) < thetime) {
6591  /* Yesterday */
6592  res = wait_file(chan, ints, "digits/yesterday", lang);
6593  } else if (beg_today - 86400 * 6 < thetime) {
6594  /* Within the last week */
6595  res = ast_say_date_with_format(chan, thetime, ints, lang, "A", tzone);
6596  } else {
6597  res = ast_say_date_with_format(chan, thetime, ints, lang, "AdBY", tzone);
6598  }
6599  }
6600  break;
6601  case 'R':
6602  res = ast_say_date_with_format(chan, thetime, ints, lang, "HM", tzone);
6603  break;
6604  case 'S':
6605  /* Seconds */
6606  res = wait_file(chan, ints, "digits/and", lang);
6607  if (!res) {
6608  if (tm.tm_sec == 1) {
6609  res = wait_file(chan, ints, "digits/1z", lang);
6610  if (!res)
6611  res = wait_file(chan, ints, "digits/second-a", lang);
6612  } else {
6613  res = ast_say_number(chan, tm.tm_sec, ints, lang, "f");
6614  if (!res) {
6615  int ten, one;
6616  ten = tm.tm_sec / 10;
6617  one = tm.tm_sec % 10;
6618 
6619  if (one > 1 && one < 5 && ten != 1)
6620  res = wait_file(chan, ints, "seconds", lang);
6621  else
6622  res = wait_file(chan, ints, "second", lang);
6623  }
6624  }
6625  }
6626  break;
6627  case 'T':
6628  res = ast_say_date_with_format(chan, thetime, ints, lang, "HMS", tzone);
6629  break;
6630  case ' ':
6631  case ' ':
6632  /* Just ignore spaces and tabs */
6633  break;
6634  default:
6635  /* Unknown character */
6636  ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
6637  }
6638  /* Jump out on DTMF */
6639  if (res)
6640  break;
6641  }
6642  return res;
6643 }

References ast_copy_string(), ast_debug, ast_localtime(), ast_log, ast_say_date_with_format, ast_say_enumeration(), ast_say_number(), ast_tvnow(), format, LOG_WARNING, NULL, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_wday, ast_tm::tm_year, and wait_file().

Referenced by say_date_with_format().

◆ ast_say_date_with_format_pt()

int ast_say_date_with_format_pt ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang,
const char *  format,
const char *  tzone 
)
static

Portuguese syntax.

Definition at line 6646 of file say.c.

6647 {
6648  struct timeval when = { t, 0 };
6649  struct ast_tm tm;
6650  int res=0, offset, sndoffset;
6651  char sndfile[256], nextmsg[256];
6652 
6653  if (format == NULL)
6654  format = "Ad 'digits/pt-de' B 'digits/pt-de' Y I 'digits/pt-e' Mp";
6655 
6656  ast_localtime(&when, &tm, tzone);
6657 
6658  for (offset=0 ; format[offset] != '\0' ; offset++) {
6659  ast_debug(1, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
6660  switch (format[offset]) {
6661  /* NOTE: if you add more options here, please try to be consistent with strftime(3) */
6662  case '\'':
6663  /* Literal name of a sound file */
6664  for (sndoffset = 0; !strchr("\'\0", format[++offset]) && (sndoffset < sizeof(sndfile) - 1) ; sndoffset++) {
6665  sndfile[sndoffset] = format[offset];
6666  }
6667  sndfile[sndoffset] = '\0';
6668  snprintf(nextmsg, sizeof(nextmsg), "%s", sndfile);
6669  res = wait_file(chan, ints, nextmsg, lang);
6670  break;
6671  case 'A':
6672  case 'a':
6673  /* Sunday - Saturday */
6674  snprintf(nextmsg, sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
6675  res = wait_file(chan, ints, nextmsg, lang);
6676  break;
6677  case 'B':
6678  case 'b':
6679  case 'h':
6680  /* January - December */
6681  snprintf(nextmsg, sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
6682  res = wait_file(chan, ints, nextmsg, lang);
6683  break;
6684  case 'm':
6685  /* First - Twelfth */
6686  if (!strcasecmp(lang, "pt_BR")) {
6687  res = ast_say_number(chan, tm.tm_mon+1, ints, lang, (char *) NULL);
6688  } else {
6689  snprintf(nextmsg, sizeof(nextmsg), "digits/h-%d", tm.tm_mon +1);
6690  res = wait_file(chan, ints, nextmsg, lang);
6691  }
6692  break;
6693  case 'd':
6694  case 'e':
6695  /* First - Thirtyfirst */
6696  res = ast_say_number(chan, tm.tm_mday, ints, lang, (char *) NULL);
6697  break;
6698  case 'Y':
6699  /* Year */
6700  res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
6701  break;
6702  case 'I':
6703  case 'l':
6704  /* 12-Hour */
6705  if (!strcasecmp(lang, "pt_BR")) {
6706  if (tm.tm_hour == 0) {
6707  if (format[offset] == 'I')
6708  res = wait_file(chan, ints, "digits/pt-a", lang);
6709  if (!res)
6710  res = wait_file(chan, ints, "digits/pt-meianoite", lang);
6711  } else if (tm.tm_hour == 12) {
6712  if (format[offset] == 'I')
6713  res = wait_file(chan, ints, "digits/pt-ao", lang);
6714  if (!res)
6715  res = wait_file(chan, ints, "digits/pt-meiodia", lang);
6716  } else {
6717  if (format[offset] == 'I') {
6718  if ((tm.tm_hour % 12) != 1)
6719  res = wait_file(chan, ints, "digits/pt-as", lang);
6720  else
6721  res = wait_file(chan, ints, "digits/pt-a", lang);
6722  }
6723  if (!res)
6724  res = ast_say_number(chan, (tm.tm_hour % 12), ints, lang, "f");
6725  }
6726  } else {
6727  if (tm.tm_hour == 0) {
6728  if (format[offset] == 'I')
6729  res = wait_file(chan, ints, "digits/pt-ah", lang);
6730  if (!res)
6731  res = wait_file(chan, ints, "digits/pt-meianoite", lang);
6732  }
6733  else if (tm.tm_hour == 12) {
6734  if (format[offset] == 'I')
6735  res = wait_file(chan, ints, "digits/pt-ao", lang);
6736  if (!res)
6737  res = wait_file(chan, ints, "digits/pt-meiodia", lang);
6738  }
6739  else {
6740  if (format[offset] == 'I') {
6741  res = wait_file(chan, ints, "digits/pt-ah", lang);
6742  if ((tm.tm_hour % 12) != 1)
6743  if (!res)
6744  res = wait_file(chan, ints, "digits/pt-sss", lang);
6745  }
6746  if (!res)
6747  res = ast_say_number(chan, (tm.tm_hour % 12), ints, lang, "f");
6748  }
6749  }
6750  break;
6751  case 'H':
6752  case 'k':
6753  /* 24-Hour */
6754  if (!strcasecmp(lang, "pt_BR")) {
6755  res = ast_say_number(chan, tm.tm_hour, ints, lang, "f");
6756  if ((!res) && (format[offset] == 'H')) {
6757  if (tm.tm_hour > 1) {
6758  res = wait_file(chan, ints, "digits/hours", lang);
6759  } else {
6760  res = wait_file(chan, ints, "digits/hour", lang);
6761  }
6762  }
6763  } else {
6764  res = ast_say_number(chan, -tm.tm_hour, ints, lang, NULL);
6765  if (!res) {
6766  if (tm.tm_hour != 0) {
6767  int remaining = tm.tm_hour;
6768  if (tm.tm_hour > 20) {
6769  res = wait_file(chan, ints, "digits/20", lang);
6770  remaining -= 20;
6771  }
6772  if (!res) {
6773  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", remaining);
6774  res = wait_file(chan, ints, nextmsg, lang);
6775  }
6776  }
6777  }
6778  }
6779  break;
6780  case 'M':
6781  /* Minute */
6782  if (!strcasecmp(lang, "pt_BR")) {
6783  res = ast_say_number(chan, tm.tm_min, ints, lang, NULL);
6784  if (!res) {
6785  if (tm.tm_min > 1) {
6786  res = wait_file(chan, ints, "minutes", lang);
6787  } else {
6788  res = wait_file(chan, ints, "minute", lang);
6789  }
6790  }
6791  } else {
6792  if (tm.tm_min == 0) {
6793  res = wait_file(chan, ints, "digits/pt-hora", lang);
6794  if (tm.tm_hour != 1)
6795  if (!res)
6796  res = wait_file(chan, ints, "digits/pt-sss", lang);
6797  } else {
6798  res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
6799  }
6800  }
6801  break;
6802  case 'P':
6803  case 'p':
6804  /* AM/PM */
6805  if (!strcasecmp(lang, "pt_BR")) {
6806  if ((tm.tm_hour != 0) && (tm.tm_hour != 12)) {
6807  res = wait_file(chan, ints, "digits/pt-da", lang);
6808  if (!res) {
6809  if ((tm.tm_hour >= 0) && (tm.tm_hour < 12))
6810  res = wait_file(chan, ints, "digits/morning", lang);
6811  else if ((tm.tm_hour >= 12) && (tm.tm_hour < 18))
6812  res = wait_file(chan, ints, "digits/afternoon", lang);
6813  else res = wait_file(chan, ints, "digits/night", lang);
6814  }
6815  }
6816  } else {
6817  if (tm.tm_hour > 12)
6818  res = wait_file(chan, ints, "digits/p-m", lang);
6819  else if (tm.tm_hour && tm.tm_hour < 12)
6820  res = wait_file(chan, ints, "digits/a-m", lang);
6821  }
6822  break;
6823  case 'Q':
6824  /* Shorthand for "Today", "Yesterday", or ABdY */
6825  /* XXX As emphasized elsewhere, this should the native way in your
6826  * language to say the date, with changes in what you say, depending
6827  * upon how recent the date is. XXX */
6828  {
6829  struct timeval now = ast_tvnow();
6830  struct ast_tm tmnow;
6831  time_t beg_today;
6832 
6833  ast_localtime(&now, &tmnow, tzone);
6834  /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
6835  /* In any case, it saves not having to do ast_mktime() */
6836  beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
6837  if (beg_today < t) {
6838  /* Today */
6839  res = wait_file(chan, ints, "digits/today", lang);
6840  } else if (beg_today - 86400 < t) {
6841  /* Yesterday */
6842  res = wait_file(chan, ints, "digits/yesterday", lang);
6843  } else {
6844  res = ast_say_date_with_format_pt(chan, t, ints, lang, "Ad 'digits/pt-de' B 'digits/pt-de' Y", tzone);
6845  }
6846  }
6847  break;
6848  case 'q':
6849  /* Shorthand for "" (today), "Yesterday", A (weekday), or ABdY */
6850  /* XXX As emphasized elsewhere, this should the native way in your
6851  * language to say the date, with changes in what you say, depending
6852  * upon how recent the date is. XXX */
6853  {
6854  struct timeval now = ast_tvnow();
6855  struct ast_tm tmnow;
6856  time_t beg_today;
6857 
6858  ast_localtime(&now, &tmnow, tzone);
6859  /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
6860  /* In any case, it saves not having to do ast_mktime() */
6861  beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
6862  if (beg_today < t) {
6863  /* Today */
6864  } else if ((beg_today - 86400) < t) {
6865  /* Yesterday */
6866  res = wait_file(chan, ints, "digits/yesterday", lang);
6867  } else if (beg_today - 86400 * 6 < t) {
6868  /* Within the last week */
6869  res = ast_say_date_with_format_pt(chan, t, ints, lang, "A", tzone);
6870  } else {
6871  res = ast_say_date_with_format_pt(chan, t, ints, lang, "Ad 'digits/pt-de' B 'digits/pt-de' Y", tzone);
6872  }
6873  }
6874  break;
6875  case 'R':
6876  res = ast_say_date_with_format_pt(chan, t, ints, lang, "H 'digits/pt-e' M", tzone);
6877  break;
6878  case 'S':
6879  /* Seconds */
6880  if (!strcasecmp(lang, "pt_BR")) {
6881  res = ast_say_number(chan, tm.tm_sec, ints, lang, NULL);
6882  if (!res) {
6883  if (tm.tm_sec > 1) {
6884  res = wait_file(chan, ints, "seconds", lang);
6885  } else {
6886  res = wait_file(chan, ints, "second", lang);
6887  }
6888  }
6889  } else {
6890  if (tm.tm_sec == 0) {
6891  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_sec);
6892  res = wait_file(chan, ints, nextmsg, lang);
6893  } else if (tm.tm_sec < 10) {
6894  res = wait_file(chan, ints, "digits/oh", lang);
6895  if (!res) {
6896  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_sec);
6897  res = wait_file(chan, ints, nextmsg, lang);
6898  }
6899  } else if ((tm.tm_sec < 21) || (tm.tm_sec % 10 == 0)) {
6900  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_sec);
6901  res = wait_file(chan, ints, nextmsg, lang);
6902  } else {
6903  int ten, one;
6904  ten = (tm.tm_sec / 10) * 10;
6905  one = (tm.tm_sec % 10);
6906  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", ten);
6907  res = wait_file(chan, ints, nextmsg, lang);
6908  if (!res) {
6909  /* Fifty, not fifty-zero */
6910  if (one != 0) {
6911  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", one);
6912  res = wait_file(chan, ints, nextmsg, lang);
6913  }
6914  }
6915  }
6916  }
6917  break;
6918  case 'T':
6919  res = ast_say_date_with_format_pt(chan, t, ints, lang, "HMS", tzone);
6920  break;
6921  case ' ':
6922  case ' ':
6923  /* Just ignore spaces and tabs */
6924  break;
6925  default:
6926  /* Unknown character */
6927  ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
6928  }
6929  /* Jump out on DTMF */
6930  if (res) {
6931  break;
6932  }
6933  }
6934  return res;
6935 }
static int ast_say_date_with_format_pt(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
Portuguese syntax.
Definition: say.c:6646

References ast_debug, ast_localtime(), ast_log, ast_say_number(), ast_tvnow(), format, LOG_WARNING, NULL, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_wday, ast_tm::tm_year, and wait_file().

Referenced by say_date_with_format().

◆ ast_say_date_with_format_th()

int ast_say_date_with_format_th ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang,
const char *  format,
const char *  tzone 
)
static

Thai syntax.

Definition at line 5275 of file say.c.

5276 {
5277  struct timeval when = { t, 0 };
5278  struct ast_tm tm;
5279  int res=0, offset, sndoffset;
5280  char sndfile[256], nextmsg[256];
5281 
5282  if (format == NULL)
5283  format = "a 'digits/tee' e 'digits/duan' hY I 'digits/naliga' M 'digits/natee'";
5284 
5285  ast_localtime(&when, &tm, tzone);
5286 
5287  for (offset=0 ; format[offset] != '\0' ; offset++) {
5288  ast_debug(1, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
5289  switch (format[offset]) {
5290  /* NOTE: if you add more options here, please try to be consistent with strftime(3) */
5291  case '\'':
5292  /* Literal name of a sound file */
5293  for (sndoffset = 0; !strchr("\'\0", format[++offset]) && (sndoffset < sizeof(sndfile) - 1) ; sndoffset++) {
5294  sndfile[sndoffset] = format[offset];
5295  }
5296  sndfile[sndoffset] = '\0';
5297  res = wait_file(chan, ints, sndfile, lang);
5298  break;
5299  case 'A':
5300  case 'a':
5301  /* Sunday - Saturday */
5302  snprintf(nextmsg, sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
5303  res = wait_file(chan, ints, nextmsg, lang);
5304  break;
5305  case 'B':
5306  case 'b':
5307  case 'h':
5308  /* January - December */
5309  snprintf(nextmsg, sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
5310  res = wait_file(chan, ints, nextmsg, lang);
5311  break;
5312  case 'm':
5313  /* Month enumerated */
5314  res = ast_say_number(chan, (tm.tm_mon + 1), ints, lang, (char *) NULL);
5315  break;
5316  case 'd':
5317  case 'e':
5318  /* First - Thirtyfirst */
5319  res = ast_say_number(chan, tm.tm_mday, ints, lang, (char *) NULL);
5320  break;
5321  case 'Y':
5322  /* Year */
5323  res = ast_say_number(chan, tm.tm_year + 1900 + 543, ints, lang, (char *) NULL);
5324  break;
5325  case 'I':
5326  case 'l':
5327  /* 12-Hour */
5328  if (tm.tm_hour == 0)
5329  ast_copy_string(nextmsg, "digits/24", sizeof(nextmsg));
5330  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_hour);
5331  res = wait_file(chan, ints, nextmsg, lang);
5332  break;
5333  case 'H':
5334  case 'k':
5335  /* 24-Hour */
5336  if (tm.tm_hour == 0)
5337  ast_copy_string(nextmsg, "digits/24", sizeof(nextmsg));
5338  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_hour);
5339  res = wait_file(chan, ints, nextmsg, lang);
5340  break;
5341  case 'M':
5342  case 'N':
5343  res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
5344  break;
5345  case 'P':
5346  case 'p':
5347  break;
5348  case 'Q':
5349  /* Shorthand for "Today", "Yesterday", or ABdY */
5350  /* XXX As emphasized elsewhere, this should the native way in your
5351  * language to say the date, with changes in what you say, depending
5352  * upon how recent the date is. XXX */
5353  {
5354  struct timeval now = ast_tvnow();
5355  struct ast_tm tmnow;
5356  time_t beg_today;
5357 
5358  ast_localtime(&now, &tmnow, tzone);
5359  /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
5360  /* In any case, it saves not having to do ast_mktime() */
5361  beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
5362  if (beg_today < t) {
5363  /* Today */
5364  res = wait_file(chan, ints, "digits/today", lang);
5365  } else if (beg_today - 86400 < t) {
5366  /* Yesterday */
5367  res = wait_file(chan, ints, "digits/yesterday", lang);
5368  } else if (beg_today - 86400 * 6 < t) {
5369  /* Within the last week */
5370  res = ast_say_date_with_format_en(chan, t, ints, lang, "A", tzone);
5371  } else if (beg_today - 2628000 < t) {
5372  /* Less than a month ago - "Sunday, October third" */
5373  res = ast_say_date_with_format_en(chan, t, ints, lang, "ABd", tzone);
5374  } else if (beg_today - 15768000 < t) {
5375  /* Less than 6 months ago - "August seventh" */
5376  res = ast_say_date_with_format_en(chan, t, ints, lang, "Bd", tzone);
5377  } else {
5378  /* More than 6 months ago - "April nineteenth two thousand three" */
5379  res = ast_say_date_with_format_en(chan, t, ints, lang, "BdY", tzone);
5380  }
5381  }
5382  break;
5383  case 'q':
5384  /* Shorthand for "" (today), "Yesterday", A (weekday), or ABdY */
5385  /* XXX As emphasized elsewhere, this should the native way in your
5386  * language to say the date, with changes in what you say, depending
5387  * upon how recent the date is. XXX */
5388  {
5389  struct timeval now = ast_tvnow();
5390  struct ast_tm tmnow;
5391  time_t beg_today;
5392 
5393  ast_localtime(&now, &tmnow, tzone);
5394  /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
5395  /* In any case, it saves not having to do ast_mktime() */
5396  beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
5397  if (beg_today < t) {
5398  /* Today */
5399  } else if ((beg_today - 86400) < t) {
5400  /* Yesterday */
5401  res = wait_file(chan, ints, "digits/yesterday", lang);
5402  } else if (beg_today - 86400 * 6 < t) {
5403  /* Within the last week */
5404  res = ast_say_date_with_format_en(chan, t, ints, lang, "A", tzone);
5405  } else if (beg_today - 2628000 < t) {
5406  /* Less than a month ago - "Sunday, October third" */
5407  res = ast_say_date_with_format_en(chan, t, ints, lang, "ABd", tzone);
5408  } else if (beg_today - 15768000 < t) {
5409  /* Less than 6 months ago - "August seventh" */
5410  res = ast_say_date_with_format_en(chan, t, ints, lang, "Bd", tzone);
5411  } else {
5412  /* More than 6 months ago - "April nineteenth two thousand three" */
5413  res = ast_say_date_with_format_en(chan, t, ints, lang, "BdY", tzone);
5414  }
5415  }
5416  break;
5417  case 'R':
5418  res = ast_say_date_with_format_en(chan, t, ints, lang, "HM", tzone);
5419  break;
5420  case 'S':
5421  res = ast_say_number(chan, tm.tm_sec, ints, lang, (char *) NULL);
5422  break;
5423  case 'T':
5424  res = ast_say_date_with_format_en(chan, t, ints, lang, "HMS", tzone);
5425  break;
5426  case ' ':
5427  case ' ':
5428  /* Just ignore spaces and tabs */
5429  break;
5430  default:
5431  /* Unknown character */
5432  ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
5433  }
5434  /* Jump out on DTMF */
5435  if (res) {
5436  break;
5437  }
5438  }
5439  return res;
5440 }

References ast_copy_string(), ast_debug, ast_localtime(), ast_log, ast_say_date_with_format_en(), ast_say_number(), ast_tvnow(), format, LOG_WARNING, NULL, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_wday, ast_tm::tm_year, and wait_file().

Referenced by say_date_with_format().

◆ ast_say_date_with_format_vi()

int ast_say_date_with_format_vi ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang,
const char *  format,
const char *  tzone 
)
static

Vietnamese syntax.

Definition at line 9060 of file say.c.

9061 {
9062  struct timeval when = { t, 0 };
9063  struct ast_tm tm;
9064  int res = 0, offset, sndoffset;
9065  char sndfile[256], nextmsg[256];
9066 
9067  if (format == NULL)
9068  format = "A 'digits/day' eB 'digits/year' Y 'digits/at' k 'hours' M 'minutes' p";
9069 
9070  ast_localtime(&when, &tm, tzone);
9071 
9072  for (offset=0 ; format[offset] != '\0' ; offset++) {
9073  ast_debug(1, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
9074  switch (format[offset]) {
9075  /* NOTE: if you add more options here, please try to be consistent with strftime(3) */
9076  case '\'':
9077  /* Literal name of a sound file */
9078  for (sndoffset = 0; !strchr("\'\0", format[++offset]) && (sndoffset < sizeof(sndfile) - 1) ; sndoffset++) {
9079  sndfile[sndoffset] = format[offset];
9080  }
9081  sndfile[sndoffset] = '\0';
9082  res = wait_file(chan, ints, sndfile, lang);
9083  break;
9084  case 'A':
9085  case 'a':
9086  /* Sunday - Saturday */
9087  snprintf(nextmsg, sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
9088  res = wait_file(chan, ints, nextmsg, lang);
9089  break;
9090  case 'B':
9091  case 'b':
9092  case 'h':
9093  /* January - December */
9094  snprintf(nextmsg, sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
9095  res = wait_file(chan, ints, nextmsg, lang);
9096  break;
9097  case 'm':
9098  /* Month enumerated */
9099  res = ast_say_enumeration(chan, (tm.tm_mon + 1), ints, lang, (char *) NULL);
9100  break;
9101  case 'd':
9102  case 'e':
9103  /* 1 - 31 */
9104  res = ast_say_number(chan, tm.tm_mday, ints, lang, (char *) NULL);
9105  break;
9106  case 'Y':
9107  /* Year */
9108  if (tm.tm_year > 99) {
9109  res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
9110  } else if (tm.tm_year < 1) {
9111  /* I'm not going to handle 1900 and prior */
9112  /* We'll just be silent on the year, instead of bombing out. */
9113  } else {
9114  res = wait_file(chan, ints, "digits/19", lang);
9115  if (!res) {
9116  if (tm.tm_year <= 9) {
9117  /* 1901 - 1909 */
9118  res = wait_file(chan, ints, "digits/odd", lang);
9119  }
9120 
9121  res |= ast_say_number(chan, tm.tm_year, ints, lang, (char *) NULL);
9122  }
9123  }
9124  break;
9125  case 'I':
9126  case 'l':
9127  /* 12-Hour */
9128  if (tm.tm_hour == 0)
9129  ast_copy_string(nextmsg, "digits/12", sizeof(nextmsg));
9130  else if (tm.tm_hour > 12)
9131  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_hour - 12);
9132  else
9133  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_hour);
9134  res = wait_file(chan, ints, nextmsg, lang);
9135  break;
9136  case 'H':
9137  case 'k':
9138  /* 24-Hour */
9139  if (format[offset] == 'H') {
9140  /* e.g. oh-eight */
9141  if (tm.tm_hour < 10) {
9142  res = wait_file(chan, ints, "digits/0", lang);
9143  }
9144  } else {
9145  /* e.g. eight */
9146  if (tm.tm_hour == 0) {
9147  res = wait_file(chan, ints, "digits/0", lang);
9148  }
9149  }
9150  if (!res) {
9151  if (tm.tm_hour != 0) {
9152  int remaining = tm.tm_hour;
9153  if (tm.tm_hour > 20) {
9154  res = wait_file(chan, ints, "digits/20", lang);
9155  remaining -= 20;
9156  }
9157  if (!res) {
9158  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", remaining);
9159  res = wait_file(chan, ints, nextmsg, lang);
9160  }
9161  }
9162  }
9163  break;
9164  case 'M':
9165  case 'N':
9166  /* Minute */
9167  res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
9168  break;
9169  case 'P':
9170  case 'p':
9171  /* AM/PM */
9172  if (tm.tm_hour > 11)
9173  ast_copy_string(nextmsg, "digits/p-m", sizeof(nextmsg));
9174  else
9175  ast_copy_string(nextmsg, "digits/a-m", sizeof(nextmsg));
9176  res = wait_file(chan, ints, nextmsg, lang);
9177  break;
9178  case 'Q':
9179  /* Shorthand for "Today", "Yesterday", or ABdY */
9180  /* XXX As emphasized elsewhere, this should the native way in your
9181  * language to say the date, with changes in what you say, depending
9182  * upon how recent the date is. XXX */
9183  {
9184  struct timeval now = ast_tvnow();
9185  struct ast_tm tmnow;
9186  time_t beg_today;
9187 
9188  gettimeofday(&now, NULL);
9189  ast_localtime(&now, &tmnow, tzone);
9190  /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
9191  /* In any case, it saves not having to do ast_mktime() */
9192  beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
9193  if (beg_today < t) {
9194  /* Today */
9195  res = wait_file(chan, ints, "digits/today", lang);
9196  } else if (beg_today - 86400 < t) {
9197  /* Yesterday */
9198  res = wait_file(chan, ints, "digits/yesterday", lang);
9199  } else if (beg_today - 86400 * 6 < t) {
9200  /* Within the last week */
9201  res = ast_say_date_with_format_vi(chan, t, ints, lang, "A", tzone);
9202  } else if (beg_today - 2628000 < t) {
9203  /* Less than a month ago - "Chu nhat ngay 13 thang 2" */
9204  res = ast_say_date_with_format_vi(chan, t, ints, lang, "A 'digits/day' dB", tzone);
9205  } else if (beg_today - 15768000 < t) {
9206  /* Less than 6 months ago - "August seventh" */
9207  res = ast_say_date_with_format_vi(chan, t, ints, lang, "'digits/day' dB", tzone);
9208  } else {
9209  /* More than 6 months ago - "April nineteenth two thousand three" */
9210  res = ast_say_date_with_format_vi(chan, t, ints, lang, "'digits/day' dB 'digits/year' Y", tzone);
9211  }
9212  }
9213  break;
9214  case 'q':
9215  /* Shorthand for "" (today), "Yesterday", A (weekday), or ABdY */
9216  /* XXX As emphasized elsewhere, this should the native way in your
9217  * language to say the date, with changes in what you say, depending
9218  * upon how recent the date is. XXX */
9219  {
9220  struct timeval now;
9221  struct ast_tm tmnow;
9222  time_t beg_today;
9223 
9224  now = ast_tvnow();
9225  ast_localtime(&now, &tmnow, tzone);
9226  /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
9227  /* In any case, it saves not having to do ast_mktime() */
9228  beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
9229  if (beg_today < t) {
9230  /* Today */
9231  } else if ((beg_today - 86400) < t) {
9232  /* Yesterday */
9233  res = wait_file(chan, ints, "digits/yesterday", lang);
9234  } else if (beg_today - 86400 * 6 < t) {
9235  /* Within the last week */
9236  res = ast_say_date_with_format_en(chan, t, ints, lang, "A", tzone);
9237  } else if (beg_today - 2628000 < t) {
9238  /* Less than a month ago - "Chu nhat ngay 13 thang 2" */
9239  res = ast_say_date_with_format_vi(chan, t, ints, lang, "A 'digits/day' dB", tzone);
9240  } else if (beg_today - 15768000 < t) {
9241  /* Less than 6 months ago - "August seventh" */
9242  res = ast_say_date_with_format_vi(chan, t, ints, lang, "'digits/day' dB", tzone);
9243  } else {
9244  /* More than 6 months ago - "April nineteenth two thousand three" */
9245  res = ast_say_date_with_format_vi(chan, t, ints, lang, "'digits/day' dB 'digits/year' Y", tzone);
9246  }
9247  }
9248  break;
9249  case 'R':
9250  res = ast_say_date_with_format_vi(chan, t, ints, lang, "HM", tzone);
9251  break;
9252  case 'S':
9253  /* Seconds */
9254  res = ast_say_number(chan, tm.tm_sec, ints, lang, (char *) NULL);
9255  break;
9256  case 'T':
9257  res = ast_say_date_with_format_vi(chan, t, ints, lang, "H 'hours' M 'minutes' S 'seconds'", tzone);
9258  break;
9259  case ' ':
9260  case ' ':
9261  /* Just ignore spaces and tabs */
9262  break;
9263  default:
9264  /* Unknown character */
9265  ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
9266  }
9267  /* Jump out on DTMF */
9268  if (res) {
9269  break;
9270  }
9271  }
9272  return res;
9273 }
static int ast_say_date_with_format_vi(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
Vietnamese syntax.
Definition: say.c:9060

References ast_copy_string(), ast_debug, ast_localtime(), ast_log, ast_say_date_with_format_en(), ast_say_enumeration(), ast_say_number(), ast_tvnow(), format, LOG_WARNING, NULL, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_wday, ast_tm::tm_year, and wait_file().

Referenced by say_date_with_format().

◆ ast_say_date_with_format_zh()

int ast_say_date_with_format_zh ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang,
const char *  format,
const char *  tzone 
)
static

Taiwanese / Chinese syntax.

Definition at line 6938 of file say.c.

6939 {
6940  struct timeval when = { t, 0 };
6941  struct ast_tm tm;
6942  int res=0, offset, sndoffset;
6943  char sndfile[256], nextmsg[256];
6944 
6945  if (format == NULL)
6946  format = "YBdAkM";
6947 
6948  ast_localtime(&when, &tm, tzone);
6949 
6950  for (offset=0 ; format[offset] != '\0' ; offset++) {
6951  ast_debug(1, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
6952  switch (format[offset]) {
6953  /* NOTE: if you add more options here, please try to be consistent with strftime(3) */
6954  case '\'':
6955  /* Literal name of a sound file */
6956  for (sndoffset = 0; !strchr("\'\0", format[++offset]) && (sndoffset < sizeof(sndfile) - 1) ; sndoffset++) {
6957  sndfile[sndoffset] = format[offset];
6958  }
6959  sndfile[sndoffset] = '\0';
6960  res = wait_file(chan, ints, sndfile, lang);
6961  break;
6962  case 'A':
6963  case 'a':
6964  /* Sunday - Saturday */
6965  snprintf(nextmsg, sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
6966  res = wait_file(chan, ints, nextmsg, lang);
6967  break;
6968  case 'B':
6969  case 'b':
6970  case 'h':
6971  case 'm':
6972  /* January - December */
6973  snprintf(nextmsg, sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
6974  res = wait_file(chan, ints, nextmsg, lang);
6975  break;
6976  case 'd':
6977  case 'e':
6978  /* First - Thirtyfirst */
6979  if (!(tm.tm_mday % 10) || (tm.tm_mday < 10)) {
6980  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_mday);
6981  res = wait_file(chan, ints, nextmsg, lang);
6982  } else {
6983  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_mday - (tm.tm_mday % 10));
6984  res = wait_file(chan, ints, nextmsg, lang);
6985  if (!res) {
6986  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_mday % 10);
6987  res = wait_file(chan, ints, nextmsg, lang);
6988  }
6989  }
6990  if (!res) res = wait_file(chan, ints, "digits/day", lang);
6991  break;
6992  case 'Y':
6993  /* Year */
6994  if (tm.tm_year > 99) {
6995  res = wait_file(chan, ints, "digits/2", lang);
6996  if (!res) {
6997  res = wait_file(chan, ints, "digits/thousand", lang);
6998  }
6999  if (tm.tm_year > 100) {
7000  if (!res) {
7001  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", (tm.tm_year - 100) / 10);
7002  res = wait_file(chan, ints, nextmsg, lang);
7003  if (!res) {
7004  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", (tm.tm_year - 100) % 10);
7005  res = wait_file(chan, ints, nextmsg, lang);
7006  }
7007  }
7008  }
7009  if (!res) {
7010  res = wait_file(chan, ints, "digits/year", lang);
7011  }
7012  } else {
7013  if (tm.tm_year < 1) {
7014  /* I'm not going to handle 1900 and prior */
7015  /* We'll just be silent on the year, instead of bombing out. */
7016  } else {
7017  res = wait_file(chan, ints, "digits/1", lang);
7018  if (!res) {
7019  res = wait_file(chan, ints, "digits/9", lang);
7020  }
7021  if (!res) {
7022  if (tm.tm_year <= 9) {
7023  /* 1901 - 1909 */
7024  res = wait_file(chan, ints, "digits/0", lang);
7025  if (!res) {
7026  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_year);
7027  res = wait_file(chan, ints, nextmsg, lang);
7028  }
7029  } else {
7030  /* 1910 - 1999 */
7031  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_year / 10);
7032  res = wait_file(chan, ints, nextmsg, lang);
7033  if (!res) {
7034  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_year % 10);
7035  res = wait_file(chan, ints, nextmsg, lang);
7036  }
7037  }
7038  }
7039  }
7040  if (!res) {
7041  res = wait_file(chan, ints, "digits/year", lang);
7042  }
7043  }
7044  break;
7045  case 'I':
7046  case 'l':
7047  /* 12-Hour */
7048  if (tm.tm_hour == 0)
7049  ast_copy_string(nextmsg, "digits/12", sizeof(nextmsg));
7050  else if (tm.tm_hour > 12)
7051  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_hour - 12);
7052  else
7053  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_hour);
7054  res = wait_file(chan, ints, nextmsg, lang);
7055  if (!res) {
7056  res = wait_file(chan, ints, "digits/oclock", lang);
7057  }
7058  break;
7059  case 'H':
7060  if (tm.tm_hour < 10) {
7061  res = wait_file(chan, ints, "digits/0", lang);
7062  }
7063  /* XXX Static analysis warns of no break here. No idea if this is
7064  * correct or not
7065  */
7066  case 'k':
7067  /* 24-Hour */
7068  if (!(tm.tm_hour % 10) || tm.tm_hour < 10) {
7069  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_hour);
7070  res = wait_file(chan, ints, nextmsg, lang);
7071  } else {
7072  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_hour - (tm.tm_hour % 10));
7073  res = wait_file(chan, ints, nextmsg, lang);
7074  if (!res) {
7075  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_hour % 10);
7076  res = wait_file(chan, ints, nextmsg, lang);
7077  }
7078  }
7079  if (!res) {
7080  res = wait_file(chan, ints, "digits/oclock", lang);
7081  }
7082  break;
7083  case 'M':
7084  /* Minute */
7085  if (!(tm.tm_min % 10) || tm.tm_min < 10) {
7086  if (tm.tm_min < 10) {
7087  res = wait_file(chan, ints, "digits/0", lang);
7088  }
7089  snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_min);
7090  res = wait_file(chan, ints, nextmsg, lang);
7091