<p>Sean Bright has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/16623">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">app_playback.c: Remove experimental 'say' application<br><br>ASTERISK-29695 #close<br><br>Change-Id: I3200aa184d97679e4a134ec1de82389203d2a0de<br>---<br>M apps/app_playback.c<br>D configs/samples/say.conf.sample<br>2 files changed, 2 insertions(+), 801 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/23/16623/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/apps/app_playback.c b/apps/app_playback.c</span><br><span>index 0c9281a..e3531a9 100644</span><br><span>--- a/apps/app_playback.c</span><br><span>+++ b/apps/app_playback.c</span><br><span>@@ -35,11 +35,6 @@</span><br><span> #include "asterisk/pbx.h"</span><br><span> #include "asterisk/module.h"</span><br><span> #include "asterisk/app.h"</span><br><span style="color: hsl(0, 100%, 40%);">-/* This file provides config-file based 'say' functions, and implenents</span><br><span style="color: hsl(0, 100%, 40%);">- * some CLI commands.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/say.h" /*!< provides config-file based 'say' functions */</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/cli.h"</span><br><span> </span><br><span> /*** DOCUMENTATION</span><br><span> <application name="Playback" language="en_US"></span><br><span>@@ -93,359 +88,12 @@</span><br><span> </span><br><span> static char *app = "Playback";</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static struct ast_config *say_cfg = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief save the say' api calls.</span><br><span style="color: hsl(0, 100%, 40%);">- * The first entry is NULL if we have the standard source,</span><br><span style="color: hsl(0, 100%, 40%);">- * otherwise we are sourcing from here.</span><br><span style="color: hsl(0, 100%, 40%);">- * 'say load [new|old]' will enable the new or old method, or report status</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-static const void *say_api_buf[40];</span><br><span style="color: hsl(0, 100%, 40%);">-static const char * const say_old = "old";</span><br><span style="color: hsl(0, 100%, 40%);">-static const char * const say_new = "new";</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void save_say_mode(const void *arg)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- int i = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- say_api_buf[i++] = arg;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- say_api_buf[i++] = ast_say_number_full;</span><br><span style="color: hsl(0, 100%, 40%);">- say_api_buf[i++] = ast_say_enumeration_full;</span><br><span style="color: hsl(0, 100%, 40%);">- say_api_buf[i++] = ast_say_digit_str_full;</span><br><span style="color: hsl(0, 100%, 40%);">- say_api_buf[i++] = ast_say_character_str_full;</span><br><span style="color: hsl(0, 100%, 40%);">- say_api_buf[i++] = ast_say_phonetic_str_full;</span><br><span style="color: hsl(0, 100%, 40%);">- say_api_buf[i++] = ast_say_datetime;</span><br><span style="color: hsl(0, 100%, 40%);">- say_api_buf[i++] = ast_say_time;</span><br><span style="color: hsl(0, 100%, 40%);">- say_api_buf[i++] = ast_say_date;</span><br><span style="color: hsl(0, 100%, 40%);">- say_api_buf[i++] = ast_say_datetime_from_now;</span><br><span style="color: hsl(0, 100%, 40%);">- say_api_buf[i++] = ast_say_date_with_format;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void restore_say_mode(void *arg)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- int i = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- say_api_buf[i++] = arg;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ast_say_number_full = say_api_buf[i++];</span><br><span style="color: hsl(0, 100%, 40%);">- ast_say_enumeration_full = say_api_buf[i++];</span><br><span style="color: hsl(0, 100%, 40%);">- ast_say_digit_str_full = say_api_buf[i++];</span><br><span style="color: hsl(0, 100%, 40%);">- ast_say_character_str_full = say_api_buf[i++];</span><br><span style="color: hsl(0, 100%, 40%);">- ast_say_phonetic_str_full = say_api_buf[i++];</span><br><span style="color: hsl(0, 100%, 40%);">- ast_say_datetime = say_api_buf[i++];</span><br><span style="color: hsl(0, 100%, 40%);">- ast_say_time = say_api_buf[i++];</span><br><span style="color: hsl(0, 100%, 40%);">- ast_say_date = say_api_buf[i++];</span><br><span style="color: hsl(0, 100%, 40%);">- ast_say_datetime_from_now = say_api_buf[i++];</span><br><span style="color: hsl(0, 100%, 40%);">- ast_say_date_with_format = say_api_buf[i++];</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief</span><br><span style="color: hsl(0, 100%, 40%);">- * Typical 'say' arguments in addition to the date or number or string</span><br><span style="color: hsl(0, 100%, 40%);">- * to say. We do not include 'options' because they may be different</span><br><span style="color: hsl(0, 100%, 40%);">- * in recursive calls, and so they are better left as an external</span><br><span style="color: hsl(0, 100%, 40%);">- * parameter.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-typedef struct {</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_channel *chan;</span><br><span style="color: hsl(0, 100%, 40%);">- const char *ints;</span><br><span style="color: hsl(0, 100%, 40%);">- const char *language;</span><br><span style="color: hsl(0, 100%, 40%);">- int audiofd;</span><br><span style="color: hsl(0, 100%, 40%);">- int ctrlfd;</span><br><span style="color: hsl(0, 100%, 40%);">-} say_args_t;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int s_streamwait3(const say_args_t *a, const char *fn)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- int res = ast_streamfile(a->chan, fn, a->language);</span><br><span style="color: hsl(0, 100%, 40%);">- if (res) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(LOG_WARNING, "Unable to play message %s\n", fn);</span><br><span style="color: hsl(0, 100%, 40%);">- return res;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- res = (a->audiofd > -1 && a->ctrlfd > -1) ?</span><br><span style="color: hsl(0, 100%, 40%);">- ast_waitstream_full(a->chan, a->ints, a->audiofd, a->ctrlfd) :</span><br><span style="color: hsl(0, 100%, 40%);">- ast_waitstream(a->chan, a->ints);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_stopstream(a->chan);</span><br><span style="color: hsl(0, 100%, 40%);">- return res;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief</span><br><span style="color: hsl(0, 100%, 40%);">- * the string is 'prefix:data' or prefix:fmt:data'</span><br><span style="color: hsl(0, 100%, 40%);">- * with ':' being invalid in strings.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-static int do_say(say_args_t *a, const char *s, const char *options, int depth)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_variable *v;</span><br><span style="color: hsl(0, 100%, 40%);">- char *lang;</span><br><span style="color: hsl(0, 100%, 40%);">- char *x;</span><br><span style="color: hsl(0, 100%, 40%);">- char *rule = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- char *rule_head = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- int ret = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- struct varshead head = { .first = NULL, .last = NULL };</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_var_t *n;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ast_debug(2, "string <%s> depth <%d>\n", s, depth);</span><br><span style="color: hsl(0, 100%, 40%);">- if (depth++ > 10) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(LOG_WARNING, "recursion too deep, exiting\n");</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(0, 100%, 40%);">- } else if (!say_cfg) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(LOG_WARNING, "no say.conf, cannot spell '%s'\n", s);</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* scan languages same as in file.c */</span><br><span style="color: hsl(0, 100%, 40%);">- if (a->language == NULL)</span><br><span style="color: hsl(0, 100%, 40%);">- a->language = "en"; /* default */</span><br><span style="color: hsl(0, 100%, 40%);">- ast_debug(2, "try <%s> in <%s>\n", s, a->language);</span><br><span style="color: hsl(0, 100%, 40%);">- lang = ast_strdupa(a->language);</span><br><span style="color: hsl(0, 100%, 40%);">- for (;;) {</span><br><span style="color: hsl(0, 100%, 40%);">- for (v = ast_variable_browse(say_cfg, lang); v ; v = v->next) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_extension_match(v->name, s)) {</span><br><span style="color: hsl(0, 100%, 40%);">- rule_head = rule = ast_strdup(v->value);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (rule)</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- if ( (x = strchr(lang, '_')) )</span><br><span style="color: hsl(0, 100%, 40%);">- *x = '\0'; /* try without suffix */</span><br><span style="color: hsl(0, 100%, 40%);">- else if (strcmp(lang, "en"))</span><br><span style="color: hsl(0, 100%, 40%);">- lang = "en"; /* last resort, try 'en' if not done yet */</span><br><span style="color: hsl(0, 100%, 40%);">- else</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (!rule)</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* skip up to two prefixes to get the value */</span><br><span style="color: hsl(0, 100%, 40%);">- if ( (x = strchr(s, ':')) )</span><br><span style="color: hsl(0, 100%, 40%);">- s = x + 1;</span><br><span style="color: hsl(0, 100%, 40%);">- if ( (x = strchr(s, ':')) )</span><br><span style="color: hsl(0, 100%, 40%);">- s = x + 1;</span><br><span style="color: hsl(0, 100%, 40%);">- ast_debug(2, "value is <%s>\n", s);</span><br><span style="color: hsl(0, 100%, 40%);">- n = ast_var_assign("SAY", s);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!n) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(LOG_ERROR, "Memory allocation error in do_say\n");</span><br><span style="color: hsl(0, 100%, 40%);">- ast_free(rule_head);</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- AST_LIST_INSERT_HEAD(&head, n, entries);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* scan the body, one piece at a time */</span><br><span style="color: hsl(0, 100%, 40%);">- while ( !ret && (x = strsep(&rule, ",")) ) { /* exit on key */</span><br><span style="color: hsl(0, 100%, 40%);">- char fn[128];</span><br><span style="color: hsl(0, 100%, 40%);">- const char *p, *fmt, *data; /* format and data pointers */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* prepare a decent file name */</span><br><span style="color: hsl(0, 100%, 40%);">- x = ast_skip_blanks(x);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_trim_blanks(x);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* replace variables */</span><br><span style="color: hsl(0, 100%, 40%);">- pbx_substitute_variables_varshead(&head, x, fn, sizeof(fn));</span><br><span style="color: hsl(0, 100%, 40%);">- ast_debug(2, "doing [%s]\n", fn);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* locate prefix and data, if any */</span><br><span style="color: hsl(0, 100%, 40%);">- fmt = strchr(fn, ':');</span><br><span style="color: hsl(0, 100%, 40%);">- if (!fmt || fmt == fn) { /* regular filename */</span><br><span style="color: hsl(0, 100%, 40%);">- ret = s_streamwait3(a, fn);</span><br><span style="color: hsl(0, 100%, 40%);">- continue;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- fmt++;</span><br><span style="color: hsl(0, 100%, 40%);">- data = strchr(fmt, ':'); /* colon before data */</span><br><span style="color: hsl(0, 100%, 40%);">- if (!data || data == fmt) { /* simple prefix-fmt */</span><br><span style="color: hsl(0, 100%, 40%);">- ret = do_say(a, fn, options, depth);</span><br><span style="color: hsl(0, 100%, 40%);">- continue;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- /* prefix:fmt:data */</span><br><span style="color: hsl(0, 100%, 40%);">- for (p = fmt; p < data && ret <= 0; p++) {</span><br><span style="color: hsl(0, 100%, 40%);">- char fn2[sizeof(fn)];</span><br><span style="color: hsl(0, 100%, 40%);">- if (*p == ' ' || *p == '\t') /* skip blanks */</span><br><span style="color: hsl(0, 100%, 40%);">- continue;</span><br><span style="color: hsl(0, 100%, 40%);">- if (*p == '\'') {/* file name - we trim them */</span><br><span style="color: hsl(0, 100%, 40%);">- char *y;</span><br><span style="color: hsl(0, 100%, 40%);">- strcpy(fn2, ast_skip_blanks(p+1)); /* make a full copy */</span><br><span style="color: hsl(0, 100%, 40%);">- y = strchr(fn2, '\'');</span><br><span style="color: hsl(0, 100%, 40%);">- if (!y) {</span><br><span style="color: hsl(0, 100%, 40%);">- p = data; /* invalid. prepare to end */</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- *y = '\0';</span><br><span style="color: hsl(0, 100%, 40%);">- ast_trim_blanks(fn2);</span><br><span style="color: hsl(0, 100%, 40%);">- p = strchr(p+1, '\'');</span><br><span style="color: hsl(0, 100%, 40%);">- ret = s_streamwait3(a, fn2);</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- int l = fmt-fn;</span><br><span style="color: hsl(0, 100%, 40%);">- strcpy(fn2, fn); /* copy everything */</span><br><span style="color: hsl(0, 100%, 40%);">- /* after prefix, append the format */</span><br><span style="color: hsl(0, 100%, 40%);">- fn2[l++] = *p;</span><br><span style="color: hsl(0, 100%, 40%);">- strcpy(fn2 + l, data);</span><br><span style="color: hsl(0, 100%, 40%);">- ret = do_say(a, fn2, options, depth);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (ret) {</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- ast_var_delete(n);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_free(rule_head);</span><br><span style="color: hsl(0, 100%, 40%);">- return ret;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int say_full(struct ast_channel *chan, const char *string,</span><br><span style="color: hsl(0, 100%, 40%);">- const char *ints, const char *lang, const char *options,</span><br><span style="color: hsl(0, 100%, 40%);">- int audiofd, int ctrlfd)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- say_args_t a = { chan, ints, lang, audiofd, ctrlfd };</span><br><span style="color: hsl(0, 100%, 40%);">- return do_say(&a, string, options, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int say_number_full(struct ast_channel *chan, int num,</span><br><span style="color: hsl(0, 100%, 40%);">- const char *ints, const char *lang, const char *options,</span><br><span style="color: hsl(0, 100%, 40%);">- int audiofd, int ctrlfd)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- char buf[64];</span><br><span style="color: hsl(0, 100%, 40%);">- say_args_t a = { chan, ints, lang, audiofd, ctrlfd };</span><br><span style="color: hsl(0, 100%, 40%);">- snprintf(buf, sizeof(buf), "num:%d", num);</span><br><span style="color: hsl(0, 100%, 40%);">- return do_say(&a, buf, options, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int say_enumeration_full(struct ast_channel *chan, int num,</span><br><span style="color: hsl(0, 100%, 40%);">- const char *ints, const char *lang, const char *options,</span><br><span style="color: hsl(0, 100%, 40%);">- int audiofd, int ctrlfd)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- char buf[64];</span><br><span style="color: hsl(0, 100%, 40%);">- say_args_t a = { chan, ints, lang, audiofd, ctrlfd };</span><br><span style="color: hsl(0, 100%, 40%);">- snprintf(buf, sizeof(buf), "enum:%d", num);</span><br><span style="color: hsl(0, 100%, 40%);">- return do_say(&a, buf, options, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int say_date_generic(struct ast_channel *chan, time_t t,</span><br><span style="color: hsl(0, 100%, 40%);">- const char *ints, const char *lang, const char *format, const char *timezonename, const char *prefix)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- char buf[128];</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_tm tm;</span><br><span style="color: hsl(0, 100%, 40%);">- struct timeval when = { t, 0 };</span><br><span style="color: hsl(0, 100%, 40%);">- say_args_t a = { chan, ints, lang, -1, -1 };</span><br><span style="color: hsl(0, 100%, 40%);">- if (format == NULL)</span><br><span style="color: hsl(0, 100%, 40%);">- format = "";</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ast_localtime(&when, &tm, timezonename);</span><br><span style="color: hsl(0, 100%, 40%);">- snprintf(buf, sizeof(buf), "%s:%s:%04d%02d%02d%02d%02d.%02d-%d-%3d",</span><br><span style="color: hsl(0, 100%, 40%);">- prefix,</span><br><span style="color: hsl(0, 100%, 40%);">- format,</span><br><span style="color: hsl(0, 100%, 40%);">- tm.tm_year+1900,</span><br><span style="color: hsl(0, 100%, 40%);">- tm.tm_mon+1,</span><br><span style="color: hsl(0, 100%, 40%);">- tm.tm_mday,</span><br><span style="color: hsl(0, 100%, 40%);">- tm.tm_hour,</span><br><span style="color: hsl(0, 100%, 40%);">- tm.tm_min,</span><br><span style="color: hsl(0, 100%, 40%);">- tm.tm_sec,</span><br><span style="color: hsl(0, 100%, 40%);">- tm.tm_wday,</span><br><span style="color: hsl(0, 100%, 40%);">- tm.tm_yday);</span><br><span style="color: hsl(0, 100%, 40%);">- return do_say(&a, buf, NULL, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int say_date_with_format(struct ast_channel *chan, time_t t,</span><br><span style="color: hsl(0, 100%, 40%);">- const char *ints, const char *lang, const char *format, const char *timezonename)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- return say_date_generic(chan, t, ints, lang, format, timezonename, "datetime");</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int say_date(struct ast_channel *chan, time_t t, const char *ints, const char *lang)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- return say_date_generic(chan, t, ints, lang, "", NULL, "date");</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int say_time(struct ast_channel *chan, time_t t, const char *ints, const char *lang)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- return say_date_generic(chan, t, ints, lang, "", NULL, "time");</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int say_datetime(struct ast_channel *chan, time_t t, const char *ints, const char *lang)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- return say_date_generic(chan, t, ints, lang, "", NULL, "datetime");</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief</span><br><span style="color: hsl(0, 100%, 40%);">- * remap the 'say' functions to use those in this file</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-static int say_init_mode(const char *mode) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (!strcmp(mode, say_new)) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (say_cfg == NULL) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(LOG_ERROR, "There is no say.conf file to use new mode\n");</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- save_say_mode(say_new);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_say_number_full = say_number_full;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ast_say_enumeration_full = say_enumeration_full;</span><br><span style="color: hsl(0, 100%, 40%);">-#if 0</span><br><span style="color: hsl(0, 100%, 40%);">- /*! \todo XXX</span><br><span style="color: hsl(0, 100%, 40%);">- These functions doesn't exist.</span><br><span style="color: hsl(0, 100%, 40%);">- say.conf.sample indicates this is working...</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">- ast_say_digits_full = say_digits_full;</span><br><span style="color: hsl(0, 100%, 40%);">- ast_say_digit_str_full = say_digit_str_full;</span><br><span style="color: hsl(0, 100%, 40%);">- ast_say_character_str_full = say_character_str_full;</span><br><span style="color: hsl(0, 100%, 40%);">- ast_say_phonetic_str_full = say_phonetic_str_full;</span><br><span style="color: hsl(0, 100%, 40%);">- ast_say_datetime_from_now = say_datetime_from_now;</span><br><span style="color: hsl(0, 100%, 40%);">-#endif</span><br><span style="color: hsl(0, 100%, 40%);">- ast_say_datetime = say_datetime;</span><br><span style="color: hsl(0, 100%, 40%);">- ast_say_time = say_time;</span><br><span style="color: hsl(0, 100%, 40%);">- ast_say_date = say_date;</span><br><span style="color: hsl(0, 100%, 40%);">- ast_say_date_with_format = say_date_with_format;</span><br><span style="color: hsl(0, 100%, 40%);">- } else if (!strcmp(mode, say_old) && say_api_buf[0] == say_new) {</span><br><span style="color: hsl(0, 100%, 40%);">- restore_say_mode(NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- } else if (strcmp(mode, say_old)) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(LOG_WARNING, "unrecognized mode %s\n", mode);</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static char *__say_cli_init(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- const char *old_mode = say_api_buf[0] ? say_new : say_old;</span><br><span style="color: hsl(0, 100%, 40%);">- const char *mode;</span><br><span style="color: hsl(0, 100%, 40%);">- switch (cmd) {</span><br><span style="color: hsl(0, 100%, 40%);">- case CLI_INIT:</span><br><span style="color: hsl(0, 100%, 40%);">- e->command = "say load [new|old]";</span><br><span style="color: hsl(0, 100%, 40%);">- e->usage =</span><br><span style="color: hsl(0, 100%, 40%);">- "Usage: say load [new|old]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- " say load\n"</span><br><span style="color: hsl(0, 100%, 40%);">- " Report status of current say mode\n"</span><br><span style="color: hsl(0, 100%, 40%);">- " say load new\n"</span><br><span style="color: hsl(0, 100%, 40%);">- " Set say method, configured in say.conf\n"</span><br><span style="color: hsl(0, 100%, 40%);">- " say load old\n"</span><br><span style="color: hsl(0, 100%, 40%);">- " Set old say method, coded in asterisk core\n";</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- case CLI_GENERATE:</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (a->argc == 2) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_cli(a->fd, "say mode is [%s]\n", old_mode);</span><br><span style="color: hsl(0, 100%, 40%);">- return CLI_SUCCESS;</span><br><span style="color: hsl(0, 100%, 40%);">- } else if (a->argc != e->args)</span><br><span style="color: hsl(0, 100%, 40%);">- return CLI_SHOWUSAGE;</span><br><span style="color: hsl(0, 100%, 40%);">- mode = a->argv[2];</span><br><span style="color: hsl(0, 100%, 40%);">- if (!strcmp(mode, old_mode))</span><br><span style="color: hsl(0, 100%, 40%);">- ast_cli(a->fd, "say mode is %s already\n", mode);</span><br><span style="color: hsl(0, 100%, 40%);">- else</span><br><span style="color: hsl(0, 100%, 40%);">- if (say_init_mode(mode) == 0)</span><br><span style="color: hsl(0, 100%, 40%);">- ast_cli(a->fd, "setting say mode from %s to %s\n", old_mode, mode);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return CLI_SUCCESS;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static struct ast_cli_entry cli_playback[] = {</span><br><span style="color: hsl(0, 100%, 40%);">- AST_CLI_DEFINE(__say_cli_init, "Set or show the say mode"),</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> static int playback_exec(struct ast_channel *chan, const char *data)</span><br><span> {</span><br><span> int res = 0;</span><br><span> int mres = 0;</span><br><span> char *tmp;</span><br><span> int option_skip=0;</span><br><span style="color: hsl(0, 100%, 40%);">- int option_say=0;</span><br><span> int option_noanswer = 0;</span><br><span> </span><br><span> AST_DECLARE_APP_ARGS(args,</span><br><span>@@ -464,8 +112,6 @@</span><br><span> if (args.options) {</span><br><span> if (strcasestr(args.options, "skip"))</span><br><span> option_skip = 1;</span><br><span style="color: hsl(0, 100%, 40%);">- if (strcasestr(args.options, "say"))</span><br><span style="color: hsl(0, 100%, 40%);">- option_say = 1;</span><br><span> if (strcasestr(args.options, "noanswer"))</span><br><span> option_noanswer = 1;</span><br><span> }</span><br><span>@@ -484,10 +130,7 @@</span><br><span> </span><br><span> ast_stopstream(chan);</span><br><span> while (!res && (front = strsep(&back, "&"))) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (option_say)</span><br><span style="color: hsl(0, 100%, 40%);">- res = say_full(chan, front, "", ast_channel_language(chan), NULL, -1, -1);</span><br><span style="color: hsl(0, 100%, 40%);">- else</span><br><span style="color: hsl(0, 100%, 40%);">- res = ast_streamfile(chan, front, ast_channel_language(chan));</span><br><span style="color: hsl(120, 100%, 40%);">+ res = ast_streamfile(chan, front, ast_channel_language(chan));</span><br><span> if (!res) {</span><br><span> res = ast_waitstream(chan, "");</span><br><span> ast_stopstream(chan);</span><br><span>@@ -506,71 +149,13 @@</span><br><span> return res;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int reload(void)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_variable *v;</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_flags config_flags = { CONFIG_FLAG_FILEUNCHANGED };</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_config *newcfg;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if ((newcfg = ast_config_load("say.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">- } else if (newcfg == CONFIG_STATUS_FILEINVALID) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(LOG_ERROR, "Config file say.conf is in an invalid format. Aborting.\n");</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (say_cfg) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_config_destroy(say_cfg);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(LOG_NOTICE, "Reloading say.conf\n");</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- say_cfg = newcfg;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (say_cfg) {</span><br><span style="color: hsl(0, 100%, 40%);">- for (v = ast_variable_browse(say_cfg, "general"); v ; v = v->next) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_extension_match(v->name, "mode")) {</span><br><span style="color: hsl(0, 100%, 40%);">- say_init_mode(v->value);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /*! \todo</span><br><span style="color: hsl(0, 100%, 40%);">- * XXX here we should sort rules according to the same order</span><br><span style="color: hsl(0, 100%, 40%);">- * we have in pbx.c so we have the same matching behaviour.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> static int unload_module(void)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- int res;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- res = ast_unregister_application(app);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ast_cli_unregister_multiple(cli_playback, ARRAY_LEN(cli_playback));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (say_cfg)</span><br><span style="color: hsl(0, 100%, 40%);">- ast_config_destroy(say_cfg);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return res;</span><br><span style="color: hsl(120, 100%, 40%);">+ return ast_unregister_application(app);</span><br><span> }</span><br><span> </span><br><span> static int load_module(void)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_variable *v;</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_flags config_flags = { 0 };</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- say_cfg = ast_config_load("say.conf", config_flags);</span><br><span style="color: hsl(0, 100%, 40%);">- if (say_cfg && say_cfg != CONFIG_STATUS_FILEINVALID) {</span><br><span style="color: hsl(0, 100%, 40%);">- for (v = ast_variable_browse(say_cfg, "general"); v ; v = v->next) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_extension_match(v->name, "mode")) {</span><br><span style="color: hsl(0, 100%, 40%);">- say_init_mode(v->value);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ast_cli_register_multiple(cli_playback, ARRAY_LEN(cli_playback));</span><br><span> return ast_register_application_xml(app, playback_exec);</span><br><span> }</span><br><span> </span><br><span>@@ -578,5 +163,4 @@</span><br><span> .support_level = AST_MODULE_SUPPORT_CORE,</span><br><span> .load = load_module,</span><br><span> .unload = unload_module,</span><br><span style="color: hsl(0, 100%, 40%);">- .reload = reload,</span><br><span> );</span><br><span>diff --git a/configs/samples/say.conf.sample b/configs/samples/say.conf.sample</span><br><span>deleted file mode 100644</span><br><span>index de35ee4..0000000</span><br><span>--- a/configs/samples/say.conf.sample</span><br><span>+++ /dev/null</span><br><span>@@ -1,383 +0,0 @@</span><br><span style="color: hsl(0, 100%, 40%);">-;</span><br><span style="color: hsl(0, 100%, 40%);">-; language configuration</span><br><span style="color: hsl(0, 100%, 40%);">-;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-[general]</span><br><span style="color: hsl(0, 100%, 40%);">-mode=old ; method for playing numbers and dates</span><br><span style="color: hsl(0, 100%, 40%);">- ; old - using asterisk core function</span><br><span style="color: hsl(0, 100%, 40%);">- ; new - using this configuration file</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-; The new language routines produce strings of the form</span><br><span style="color: hsl(0, 100%, 40%);">-; prefix:[format:]data</span><br><span style="color: hsl(0, 100%, 40%);">-; that are matched against the rules in this file to produce</span><br><span style="color: hsl(0, 100%, 40%);">-; an output.</span><br><span style="color: hsl(0, 100%, 40%);">-;</span><br><span style="color: hsl(0, 100%, 40%);">-; The data is generally the string to be spelled (either a number,</span><br><span style="color: hsl(0, 100%, 40%);">-; an ascii string or a date/time in the format specified below).</span><br><span style="color: hsl(0, 100%, 40%);">-; It is available, in the right hand side of a rule, as variable ${SAY}.</span><br><span style="color: hsl(0, 100%, 40%);">-;</span><br><span style="color: hsl(0, 100%, 40%);">-; The format is optional and normally used only for date/time.</span><br><span style="color: hsl(0, 100%, 40%);">-; The prefix is used to select the pronunciation - standard</span><br><span style="color: hsl(0, 100%, 40%);">-; prefixes are</span><br><span style="color: hsl(0, 100%, 40%);">-; num used for numbers</span><br><span style="color: hsl(0, 100%, 40%);">-; enum used for enumerations</span><br><span style="color: hsl(0, 100%, 40%);">-; date for dates</span><br><span style="color: hsl(0, 100%, 40%);">-; time for times</span><br><span style="color: hsl(0, 100%, 40%);">-; datetime for dates and times</span><br><span style="color: hsl(0, 100%, 40%);">-; char for character strings</span><br><span style="color: hsl(0, 100%, 40%);">-; phonetic for phonetic strings</span><br><span style="color: hsl(0, 100%, 40%);">-; digit for digit strings</span><br><span style="color: hsl(0, 100%, 40%);">-;</span><br><span style="color: hsl(0, 100%, 40%);">-; but others can be used at will.</span><br><span style="color: hsl(0, 100%, 40%);">-;</span><br><span style="color: hsl(0, 100%, 40%);">-; Processing occurs as follows:</span><br><span style="color: hsl(0, 100%, 40%);">-; If the format is empty, or there is no format, the entire</span><br><span style="color: hsl(0, 100%, 40%);">-; string is matched against one of the pattern on the left hand side.</span><br><span style="color: hsl(0, 100%, 40%);">-; On the first match, the various comma-separated components on the right</span><br><span style="color: hsl(0, 100%, 40%);">-; hand side are pronounced, as follows:</span><br><span style="color: hsl(0, 100%, 40%);">-; + a component starting with a prefix: (i.e. with a ':' in it)</span><br><span style="color: hsl(0, 100%, 40%);">-; is re-processed according to these rules;</span><br><span style="color: hsl(0, 100%, 40%);">-; + a component without a ':' in it is considered a filename and</span><br><span style="color: hsl(0, 100%, 40%);">-; the corresponding file is played.</span><br><span style="color: hsl(0, 100%, 40%);">-;</span><br><span style="color: hsl(0, 100%, 40%);">-; If the format is non-empty, the format is split into its components</span><br><span style="color: hsl(0, 100%, 40%);">-; (individual characters, or filenames in single quotes), and then</span><br><span style="color: hsl(0, 100%, 40%);">-; filenames are played, whereas single characters are used to</span><br><span style="color: hsl(0, 100%, 40%);">-; generate a new string format:pat:data to be processed.</span><br><span style="color: hsl(0, 100%, 40%);">-;</span><br><span style="color: hsl(0, 100%, 40%);">-; DATES/AND TIMES assume that the date info is available in</span><br><span style="color: hsl(0, 100%, 40%);">-; the form YYYYMMDDHHmm.ss-dow-doy</span><br><span style="color: hsl(0, 100%, 40%);">-; with 4 digits for the year, 2 for month, day, hour, minutes, seconds,</span><br><span style="color: hsl(0, 100%, 40%);">-; one digit for the day-of-week, and 3 digits for the day-of-year.</span><br><span style="color: hsl(0, 100%, 40%);">-;</span><br><span style="color: hsl(0, 100%, 40%);">-; Example:</span><br><span style="color: hsl(0, 100%, 40%);">-; datetime::200604172030.00-4-102</span><br><span style="color: hsl(0, 100%, 40%);">-; (typical format for a date) is first matched against the line</span><br><span style="color: hsl(0, 100%, 40%);">-; datetime::. => date:AdBY 'digits/at' IMp:${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">-; which is normally present with the default format for dates.</span><br><span style="color: hsl(0, 100%, 40%);">-; In turn, the format string "AdBY 'digits/at' IMp" results in</span><br><span style="color: hsl(0, 100%, 40%);">-; the sequence</span><br><span style="color: hsl(0, 100%, 40%);">-; date:A:200604172030.00-4-102</span><br><span style="color: hsl(0, 100%, 40%);">-; date:d:200604172030.00-4-102</span><br><span style="color: hsl(0, 100%, 40%);">-; date:B:200604172030.00-4-102</span><br><span style="color: hsl(0, 100%, 40%);">-; date:Y:200604172030.00-4-102</span><br><span style="color: hsl(0, 100%, 40%);">-; digits/at</span><br><span style="color: hsl(0, 100%, 40%);">-; date:I:200604172030.00-4-102</span><br><span style="color: hsl(0, 100%, 40%);">-; date:M:200604172030.00-4-102</span><br><span style="color: hsl(0, 100%, 40%);">-; date:p:200604172030.00-4-102</span><br><span style="color: hsl(0, 100%, 40%);">-;</span><br><span style="color: hsl(0, 100%, 40%);">-;</span><br><span style="color: hsl(0, 100%, 40%);">-; Remember, normally X Z N are special, and the search is</span><br><span style="color: hsl(0, 100%, 40%);">-; case insensitive, so you must use [X] [N] [Z] .. if you</span><br><span style="color: hsl(0, 100%, 40%);">-; want exact match.</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-; We start with the basic rules that might be more-or-less</span><br><span style="color: hsl(0, 100%, 40%);">-; language-independent</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-[digit-base](!) ; base rule for digit strings</span><br><span style="color: hsl(0, 100%, 40%);">- ; XXX incomplete yet</span><br><span style="color: hsl(0, 100%, 40%);">- _digit:[0-9] => digits/${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _digit:[-] => letters/dash</span><br><span style="color: hsl(0, 100%, 40%);">- _digit:[*] => letters/star</span><br><span style="color: hsl(0, 100%, 40%);">- _digit:[@] => letters/at</span><br><span style="color: hsl(0, 100%, 40%);">- _digit:[0-9]. => digit:${SAY:0:1}, digit:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-[date-base](!) ; base rules for dates and times</span><br><span style="color: hsl(0, 100%, 40%);">- ; the 'SAY' variable contains YYYYMMDDHHmm.ss-dow-doy</span><br><span style="color: hsl(0, 100%, 40%);">- ; these rule map the strftime attributes.</span><br><span style="color: hsl(0, 100%, 40%);">- _date:Y:. => num:${SAY:0:4} ; year, 19xx</span><br><span style="color: hsl(0, 100%, 40%);">- _date:[Bbh]:. => digits/mon-$[${SAY:4:2}-1] ; month name, 0..11</span><br><span style="color: hsl(0, 100%, 40%);">- _date:[Aa]:. => digits/day-${SAY:16:1} ; day of week</span><br><span style="color: hsl(0, 100%, 40%);">- _date:[de]:. => num:${SAY:6:2} ; day of month</span><br><span style="color: hsl(0, 100%, 40%);">- _date:[H]:. => digits/oh, num:${SAY:8:2} ; hour (oh one, oh two, ..., oh nine, ten, eleven, ..., twenty-three)</span><br><span style="color: hsl(0, 100%, 40%);">- _date:[I]:. => num:$[${SAY:8:2} % 12] ; hour 0-12</span><br><span style="color: hsl(0, 100%, 40%);">- _date:[M]:. => num:${SAY:10:2} ; minute</span><br><span style="color: hsl(0, 100%, 40%);">- ; XXX too bad the '?' function does not remove the quotes</span><br><span style="color: hsl(0, 100%, 40%);">- ; _date:[pP]:. => digits/$[ ${SAY:10:2} > 12 ? "p-m" :: "a-m"] ; am pm</span><br><span style="color: hsl(0, 100%, 40%);">- _date:[pP]:. => digits/p-m ; am pm</span><br><span style="color: hsl(0, 100%, 40%);">- _date:[S]:. => num:${SAY:13:2} ; seconds</span><br><span style="color: hsl(0, 100%, 40%);">- _date:[Ii]:. => num:$[${SAY:8:2} % 12] ; hour 0-12</span><br><span style="color: hsl(0, 100%, 40%);">- _date:[k]:. => num:${SAY:8:2} ; hour (one, two. three, ...,twenty three</span><br><span style="color: hsl(0, 100%, 40%);">- _date:[m]:. => num:${SAY:4:2} ; month number</span><br><span style="color: hsl(0, 100%, 40%);">- _date:[Q]:. => date:dby ;incompleat ; "today", "yesterday" or ABdY</span><br><span style="color: hsl(0, 100%, 40%);">- _date:[q]:. => date:dby ;incompleat ; "" (for today), "yesterday", weekday, or ABdY</span><br><span style="color: hsl(0, 100%, 40%);">- _date:[R]:. => date:HM${SAY} ; 24 hour time, including minute</span><br><span style="color: hsl(0, 100%, 40%);">- _date:[T]:. => date:HMS${SAY} ; 24 hour, minure, seconds</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-[en-base](!)</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:0. => num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:X => digits/${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:1X => digits/${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]0 => digits/${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9][1-9] => digits/${SAY:0:1}0, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:X00 => num:${SAY:0:1}, digits/hundred</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXX => num:${SAY:0:1}, digits/hundred, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:X000 => num:${SAY:0:1}, digits/thousand</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXX => num:${SAY:0:1}, digits/thousand, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XX000 => num:${SAY:0:2}, digits/thousand</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXX => num:${SAY:0:2}, digits/thousand, num:${SAY:2}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXX000 => num:${SAY:0:3}, digits/thousand</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXX => num:${SAY:0:3}, digits/thousand, num:${SAY:3}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:X000000 => num:${SAY:0:1}, digits/million</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXXX => num:${SAY:0:1}, digits/million, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XX000000 => num:${SAY:0:2}, digits/million</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXXXX => num:${SAY:0:2}, digits/million, num:${SAY:2}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXX000000 => num:${SAY:0:3}, digits/million</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXXXXX => num:${SAY:0:3}, digits/million, num:${SAY:3}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:X000000000 => num:${SAY:0:1}, digits/billion</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXXXXXX => num:${SAY:0:1}, digits/billion, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XX000000000 => num:${SAY:0:2}, digits/billion</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXXXXXXX => num:${SAY:0:2}, digits/billion, num:${SAY:2}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXX000000000 => num:${SAY:0:3}, digits/billion</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXXXXXXXX => num:${SAY:0:3}, digits/billion, num:${SAY:3}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ; enumeration</span><br><span style="color: hsl(0, 100%, 40%);">- _e[n]um:X => digits/h-${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _e[n]um:1X => digits/h-${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _e[n]um:[2-9]0 => digits/h-${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _e[n]um:[2-9][1-9] => num:${SAY:0:1}0, digits/h-${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _e[n]um:[1-9]00 => num:${SAY:0:1}, digits/h-hundred</span><br><span style="color: hsl(0, 100%, 40%);">- _e[n]um:[1-9]XX => num:${SAY:0:1}, digits/h-hundred, enum:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-[en_GB](date-base,digit-base,en-base)</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXX => num:${SAY:0:1}, digits/hundred, vm-and, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-[it](digit-base,date-base)</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:0. => num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:X => digits/${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:1X => digits/${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]0 => digits/${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9][1-9] => digits/${SAY:0:1}0, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:100 => digits/hundred</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:1XX => digits/hundred, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]00 => num:${SAY:0:1}, digits/hundred</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]XX => num:${SAY:0:1}, digits/hundred, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:1000 => digits/thousand</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:1XXX => digits/thousand, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]000 => num:${SAY:0:1}, digits/thousands</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]XXX => num:${SAY:0:1}, digits/thousands, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XX000 => num:${SAY:0:2}, digits/thousands</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXX => num:${SAY:0:2}, digits/thousands, num:${SAY:2}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXX000 => num:${SAY:0:3}, digits/thousands</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXX => num:${SAY:0:3}, digits/thousands, num:${SAY:3}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:1000000 => num:${SAY:0:1}, digits/million</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:1XXXXXX => num:${SAY:0:1}, digits/million, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]000000 => num:${SAY:0:1}, digits/millions</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]XXXXXX => num:${SAY:0:1}, digits/millions, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XX000000 => num:${SAY:0:2}, digits/millions</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXXXX => num:${SAY:0:2}, digits/millions, num:${SAY:2}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXX000000 => num:${SAY:0:3}, digits/millions</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXXXXX => num:${SAY:0:3}, digits/millions, num:${SAY:3}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:X000000000 => num:${SAY:0:1}, digits/billion</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXXXXXX => num:${SAY:0:1}, digits/billion, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XX000000000 => num:${SAY:0:2}, digits/billion</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXXXXXXX => num:${SAY:0:2}, digits/billion, num:${SAY:2}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXX000000000 => num:${SAY:0:3}, digits/billion</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXXXXXXXX => num:${SAY:0:3}, digits/billion, num:${SAY:3}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- _datetime::. => date:AdBY 'digits/at' IMp:${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _date::. => date:AdBY:${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _time::. => date:IMp:${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-[en](en-base,date-base,digit-base)</span><br><span style="color: hsl(0, 100%, 40%);">- _datetime::. => date:AdBY 'digits/at' IMp:${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _date::. => date:AdBY:${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _time::. => date:IMp:${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-[de](date-base,digit-base)</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:0. => num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:X => digits/${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:1X => digits/${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]0 => digits/${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9][1-9] => digits/${SAY:1}-and, digits/${SAY:0:1}0</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:100 => digits/ein, digits/hundred</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:1XX => digits/ein, digits/hundred, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]00 => digits/${SAY:0:1}, digits/hundred</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]XX => digits/${SAY:0:1}, digits/hundred, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:1000 => digits/ein, digits/thousand</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:1XXX => digits/ein, digits/thousand, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]000 => digits/${SAY:0:1}, digits/thousand</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]XXX => digits/${SAY:0:1}, digits/thousand, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XX000 => num:${SAY:0:2}, digits/thousand</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXX => num:${SAY:0:2}, digits/thousand, num:${SAY:2}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXX000 => num:${SAY:0:3}, digits/thousand</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXX => num:${SAY:0:3}, digits/thousand, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:1000000 => digits/eine, digits/million</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:1XXXXXX => digits/eine, digits/million, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]000000 => digits/${SAY:0:1}, digits/millions</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]XXXXXX => digits/${SAY:0:1}, digits/millions, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XX000000 => num:${SAY:0:2}, digits/millions</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXXXX => num:${SAY:0:2}, digits/millions, num:${SAY:2}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXX000000 => num:${SAY:0:3}, digits/millions</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXXXXX => num:${SAY:0:3}, digits/millions, num:${SAY:3}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- _datetime::. => date:AdBY 'digits/at' IMp:${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _date::. => date:AdBY:${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _time::. => date:IMp:${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-[hu](digit-base,date-base)</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:0. => num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:X => digits/${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:1[1-9] => digits/10en, digits/${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:2[1-9] => digits/20on, digits/${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[1-9]0 => digits/${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[3-9][1-9] => digits/${SAY:0:1}0, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXX => num:${SAY:0:1}, digits/hundred, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:X000 => num:${SAY:0:1}, digits/thousand</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXX => num:${SAY:0:1}, digits/thousand, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XX000 => num:${SAY:0:2}, digits/thousand</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXX => num:${SAY:0:2}, digits/thousand, num:${SAY:2}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXX000 => num:${SAY:0:3}, digits/thousand</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXX => num:${SAY:0:3}, digits/thousand, num:${SAY:3}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:X000000 => num:${SAY:0:1}, digits/million</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXXX => num:${SAY:0:1}, digits/million, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XX000000 => num:${SAY:0:2}, digits/million</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXXXX => num:${SAY:0:2}, digits/million, num:${SAY:2}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXX000000 => num:${SAY:0:3}, digits/million</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXXXXX => num:${SAY:0:3}, digits/million, num:${SAY:3}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:X000000000 => num:${SAY:0:1}, digits/billion</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXXXXXX => num:${SAY:0:1}, digits/billion, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XX000000000 => num:${SAY:0:2}, digits/billion</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXXXXXXX => num:${SAY:0:2}, digits/billion, num:${SAY:2}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXX000000000 => num:${SAY:0:3}, digits/billion</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXXXXXXXX => num:${SAY:0:3}, digits/billion, num:${SAY:3}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- _datetime::. => date:YBdA k 'ora' M 'perc':${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _date::. => date:YBdA:${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _time::. => date:k 'ora' M 'perc':${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-[fr](date-base,digit-base)</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:0. => num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:X => digits/${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:1X => digits/${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]0 => digits/${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-6]1 => digits/${SAY:0:1}0, vm-and, digits/${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:71 => digits/60, vm-and, num:1${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:7X => digits/60, num:1${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:9X => digits/80, num:1${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9][1-9] => digits/${SAY:0:1}0, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:100 => digits/hundred</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:1XX => digits/hundred, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]00 => num:${SAY:0:1}, digits/hundred</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]XX => num:${SAY:0:1}, digits/hundred, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:1000 => digits/thousand</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:1XXX => digits/thousand, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]000 => num:${SAY:0:1}, digits/thousand</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]XXX => num:${SAY:0:1}, digits/thousand, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XX000 => num:${SAY:0:2}, digits/thousand</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXX => num:${SAY:0:2}, digits/thousand, num:${SAY:2}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXX000 => num:${SAY:0:3}, digits/thousand</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXX => num:${SAY:0:3}, digits/thousand, num:${SAY:3}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:1000000 => num:${SAY:0:1}, digits/million</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:1XXXXXX => num:${SAY:0:1}, digits/million, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]000000 => num:${SAY:0:1}, digits/million</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]XXXXXX => num:${SAY:0:1}, digits/million, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XX000000 => num:${SAY:0:2}, digits/million</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXXXX => num:${SAY:0:2}, digits/million, num:${SAY:2}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXX000000 => num:${SAY:0:3}, digits/million</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXXXXX => num:${SAY:0:3}, digits/million, num:${SAY:3}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- _datetime::. => date:AdBY 'digits/at' H 'hours' M 'perc':${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _date::. => date:AdBY:${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _time::. => date:H 'hours' M 'perc':${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- _pho[n]e:XXXX => num:${SAY:0:2}, num:${SAY:2:2}</span><br><span style="color: hsl(0, 100%, 40%);">- _pho[n]e:0[1-9]XXXXXXXX => num:${SAY:0:1}, num:${SAY:1:1}, num:${SAY:2:2}, num:${SAY:4:2}, num:${SAY:6:2}, num:${SAY:8:2}</span><br><span style="color: hsl(0, 100%, 40%);">- _pho[n]e:. => digit:${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-[es](date-base,digit-base)</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:0. => num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:X => digits/${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:1X => digits/${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]0 => digits/${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:2[1-9] => digits/20-and, digits/${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[3-9][1-9] => digits/${SAY:0:1}0, vm-and, digits/${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:100 => digits/hundred</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:1XX => digits/100-and, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]00 => digits/${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]XX => digits/${SAY:0:1}00, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:1000 => digits/thousand</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:1XXX => digits/thousand, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]000 => num:${SAY:0:1}, digits/thousand</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]XXX => num:${SAY:0:1}, digits/thousand, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XX000 => num:${SAY:0:2}, digits/thousand</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXX => num:${SAY:0:2}, digits/thousand, num:${SAY:2}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXX000 => num:${SAY:0:3}, digits/thousand</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXX => num:${SAY:0:3}, digits/thousand, num:${SAY:3}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:1000000 => digits/1M, digits/million</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:1XXXXXX => digits/1M, digits/million, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]000000 => num:${SAY:0:1}, digits/millions</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]XXXXXX => num:${SAY:0:1}, digits/millions, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XX000000 => num:${SAY:0:2}, digits/millions</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXXXX => num:${SAY:0:2}, digits/millions, num:${SAY:2}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXX000000 => num:${SAY:0:3}, digits/millions</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXXXXX => num:${SAY:0:3}, digits/millions, num:${SAY:3}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXX000000 => num:${SAY:0:4}, digits/millions</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXXXXXX => num:${SAY:0:4}, digits/millions, num:${SAY:4}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- _datetime::. => date:Ad 'letters/d' B 'letters/d' Y 'digits/at' HMp:${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _date::. => date:Ad 'letters/d' B 'letters/d' Y:${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _time::. => date:HMp:${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-[da](date-base,digit-base)</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:0. => num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:X => digits/${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:1X => digits/${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]0 => digits/${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9][1-9] => digits/${SAY:1}-and, digits/${SAY:0:1}0</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:100 => digits/1N, digits/hundred</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:1XX => digits/1N, digits/hundred, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]00 => digits/${SAY:0:1}, digits/hundred</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]XX => digits/${SAY:0:1}, digits/hundred, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:1000 => digits/1N, digits/thousand</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:1XXX => digits/1N, digits/thousand, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]000 => digits/${SAY:0:1}, digits/thousand</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:[2-9]XXX => digits/${SAY:0:1}, digits/thousand, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XX000 => num:${SAY:0:2}, digits/thousand</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXX => num:${SAY:0:2}, digits/thousand, num:${SAY:2}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXX000 => num:${SAY:0:3}, digits/thousand</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXX => num:${SAY:0:3}, digits/thousand, num:${SAY:3}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:X000000 => digits/${SAY:0:1}, digits/million</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXXX => digits/${SAY:0:1}, digits/million, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XX000000 => num:${SAY:0:2}, digits/millions</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXXXX => num:${SAY:0:2}, digits/millions, num:${SAY:2}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXX000000 => num:${SAY:0:3}, digits/millions</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXXXXX => num:${SAY:0:3}, digits/millions, num:${SAY:3}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:X000000000 => num:${SAY:0:1}, digits/billion</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXXXXXX => num:${SAY:0:1}, digits/billion, num:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XX000000000 => num:${SAY:0:2}, digits/billion</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXXXXXXX => num:${SAY:0:2}, digits/billion, num:${SAY:2}</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXX000000000 => num:${SAY:0:3}, digits/billion</span><br><span style="color: hsl(0, 100%, 40%);">- _[n]um:XXXXXXXXXXXX => num:${SAY:0:3}, digits/billion, num:${SAY:3}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- _datetime::. => date:AdBY 'digits/at' kM:${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _date::. => date:AdBY:${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _time::. => date:HM:${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ; enumeration</span><br><span style="color: hsl(0, 100%, 40%);">- _e[n]um:X => digits/h-${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _e[n]um:1X => digits/h-${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _e[n]um:[2-9]0 => digits/h-${SAY}</span><br><span style="color: hsl(0, 100%, 40%);">- _e[n]um:[2-9][1-9] => digits/${SAY:1}-and, digits/h-${SAY:0:1}0</span><br><span style="color: hsl(0, 100%, 40%);">- _e[n]um:100 => digits/1N, digits/h-hundred</span><br><span style="color: hsl(0, 100%, 40%);">- _e[n]um:1XX => digits/1N, digits/h-hundred, enum:${SAY:1}</span><br><span style="color: hsl(0, 100%, 40%);">- _e[n]um:[2-9]00 => num:${SAY:0:1}, digits/h-hundred</span><br><span style="color: hsl(0, 100%, 40%);">- _e[n]um:[2-9]XX => num:${SAY:0:1}, digits/h-hundred, enum:${SAY:1}</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/16623">change 16623</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/c/asterisk/+/16623"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I3200aa184d97679e4a134ec1de82389203d2a0de </div>
<div style="display:none"> Gerrit-Change-Number: 16623 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Sean Bright <sean@seanbright.com> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>