/* * 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 #include #include #include #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); }