aboutsummaryrefslogtreecommitdiffstats
path: root/spo256/chars.c
diff options
context:
space:
mode:
authorWilliam Harrington <kb0iic@berzerkula.org>2025-01-14 16:06:02 -0600
committerWilliam Harrington <kb0iic@berzerkula.org>2025-01-14 16:06:02 -0600
commit0cc9b20c15460213e488bf5e70963b941482f628 (patch)
treebb0143245583ec846630f39bfa2258dba640ccd7 /spo256/chars.c
parent0e084ade5069756d487b5c948c48b777e37c00c9 (diff)
Add source.
Diffstat (limited to 'spo256/chars.c')
-rw-r--r--spo256/chars.c339
1 files changed, 339 insertions, 0 deletions
diff --git a/spo256/chars.c b/spo256/chars.c
new file mode 100644
index 0000000..e4b2a2a
--- /dev/null
+++ b/spo256/chars.c
@@ -0,0 +1,339 @@
+/*
+ * Character state parser for text-to-speech server.
+ * $Id: chars.c 1.2 Mon, 24 Mar 1997 12:25:37 -0500 dyfet $
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and reuse see product license.
+ */
+
+#include <other/string.h>
+#include <other/config.h>
+#include <std/files.h>
+#include <std/process.h>
+#include "speak.h"
+
+enum
+{
+ CH_IGNORE,
+ CH_PERIOD,
+ CH_QUOTE,
+ CH_ESCAPE,
+ CH_SPACE,
+ CH_ALPHA,
+ CH_NUMERIC,
+ CH_PUNCT,
+};
+
+static uchar map[256];
+static uchar word[256];
+static int cpos = 0;
+static bool init = FALSE;
+static void (*state)(uchar ch);
+static bool quote;
+
+static void s_hex(uchar ch);
+static void s_num(uchar ch);
+static void s_cmd(uchar ch);
+static void s_leadcmd(uchar ch);
+static void s_abbrev(uchar ch);
+static void s_point(uchar ch);
+static void s_word(uchar ch);
+static void s_idle(uchar ch);
+
+static void s_hex(uchar ch)
+{
+ switch(ch)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case 'a':
+ case 'A':
+ case 'b':
+ case 'B':
+ case 'c':
+ case 'C':
+ case 'd':
+ case 'D':
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'F':
+ word[cpos++] = ch;
+ break;
+ default:
+ word[cpos] = 0;
+ number(word);
+ state = s_idle;
+ s_idle(ch);
+ }
+}
+
+static void s_num(uchar ch)
+{
+ switch(map[ch])
+ {
+ case CH_NUMERIC:
+ word[cpos++] = ch;
+ break;
+ default:
+ switch(ch)
+ {
+ case 'e':
+ case '^':
+ word[cpos++] = ch;
+ number(word);
+ cpos = 0;
+ spo_word("raised");
+ spo_word("to");
+ spo_word("the");
+ spo_word("power");
+ break;
+ case ':':
+ case '/':
+ case '.':
+ word[cpos++] = ch;
+ break;
+ case '%':
+ word[cpos] = 0;
+ number(word);
+ state = s_idle;
+ spo_word("percent");
+ break;
+ case 'x':
+ case 'X':
+ if(cpos == 1)
+ {
+ cpos = 0;
+ state = s_hex;
+ break;
+ }
+ default:
+ word[cpos] = 0;
+ number(word);
+ state = s_idle;
+ s_idle(ch);
+ }
+ }
+}
+
+static void s_cmd(uchar ch)
+{
+ if(ch == '>')
+ {
+ word[cpos] = 0;
+ spo_cmd((char *)word);
+ state = s_idle;
+ }
+ else
+ word[cpos++] = ch;
+}
+
+static void s_leadcmd(uchar ch)
+{
+ if(ch == '<')
+ state = s_cmd;
+ else
+ {
+ state = s_idle;
+ s_idle(ch);
+ }
+}
+
+static void s_abbrev(uchar ch)
+{
+ switch(map[ch])
+ {
+ case CH_SPACE:
+ abbrev((char *)word);
+ state = s_idle;
+ break;
+ default:
+ spo_word((char *)word);
+ cpos = 0;
+ spo_word("dot");
+ state = s_word;
+ s_word(ch);
+ }
+}
+
+static void s_point(uchar ch)
+{
+ switch(map[ch])
+ {
+ case CH_ALPHA:
+ state = s_word;
+ case CH_PERIOD:
+ spo_word("dot");
+ break;
+ case CH_NUMERIC:
+ spo_word("point");
+ state = s_num;
+ break;
+ default:
+ state = s_idle;
+ break;
+ }
+}
+
+static void s_word(uchar ch)
+{
+ switch(map[ch])
+ {
+ case CH_PERIOD:
+ if(!cpos)
+ state = s_point;
+ else
+ state = s_abbrev;
+ word[cpos++] = '.';
+ word[cpos] = 0;
+ break;
+ case CH_PUNCT:
+ case CH_ALPHA:
+ case CH_NUMERIC:
+ if(cpos < 255)
+ word[cpos++] = ch;
+ break;
+ case CH_SPACE:
+ word[cpos] = 0;
+ spo_word((char *)word);
+ state = s_idle;
+ break;
+ default:
+ switch(ch)
+ {
+ case '\'':
+ word[cpos++] = ch;
+ break;
+ default:
+ word[cpos] = 0;
+ spo_word((char *)word);
+ spo_pause(P_WORD);
+ state = s_idle;
+ s_idle(ch);
+ }
+ }
+}
+
+static void s_idle(uchar ch)
+{
+ cpos = 0;
+ switch(map[ch])
+ {
+ case CH_NUMERIC:
+ state = s_num;
+ s_num(ch);
+ break;
+ case CH_ALPHA:
+ state = s_word;
+ s_word(ch);
+ break;
+ case CH_ESCAPE:
+ state = s_leadcmd;
+ break;
+ case CH_SPACE:
+ spo_pause(P_WORD);
+ break;
+ case CH_QUOTE:
+ if(quote)
+ {
+ spo_word("end");
+ quote = FALSE;
+ }
+ else
+ quote = TRUE;
+ spo_word("quote");
+ break;
+ default:
+ switch(ch)
+ {
+ case '$':
+ word[0] = '$';
+ cpos = 1;
+ state = s_num;
+ break;
+ case '*':
+ spo_word("times");
+ break;
+ case '/':
+ spo_word("divided");
+ spo_word("by");
+ break;
+ case '+':
+ spo_word("plus");
+ break;
+ case '-':
+ spo_word("minus");
+ break;
+ case '&':
+ spo_word("and");
+ break;
+ case '|':
+ spo_word("or");
+ break;
+ case '~':
+ spo_word("not");
+ break;
+ case ')':
+ spo_word("end");
+ case '(':
+ spo_word("parenthesis");
+ break;
+ case '=':
+ spo_word("equals");
+ break;
+ case '<':
+ spo_word("less");
+ spo_word("than");
+ break;
+ case '>':
+ spo_word("greater");
+ spo_word("than");
+ break;
+ default:
+ spo_pause(P_WORD);
+ }
+ }
+}
+
+void chars(FILE *fp)
+{
+ int i, ch;
+
+ quote = FALSE;
+ state = s_idle;
+
+ if(!init)
+ {
+ for(i = 0; i < 256; ++i)
+ map[i] = CH_IGNORE;
+
+ map[27] = CH_ESCAPE;
+
+ for(i = 33; i < 127; ++i)
+ map[i] = CH_PUNCT;
+
+ map[9] = map[13] = map[10] = map[32] = CH_SPACE;
+ for(i = 48; i < 58; ++i)
+ map[i] = CH_NUMERIC;
+
+ for(i = 0; i < 26; ++i)
+ {
+ map[i + 65] = CH_ALPHA;
+ map[i + 97] = CH_ALPHA;
+ }
+ map['.'] = CH_PERIOD;
+ map['\"'] = CH_QUOTE;
+ }
+
+ while(EOF != (ch = fgetc(fp)))
+ (*state)(ch);
+
+ (*state)(0);
+}