Annotation of coherent/b/kernel/FWB/words.c, revision 1.1

1.1     ! root        1: /*-----------------------------------------------------------------------------
        !             2:        Talking BIOS device driver for the AT&T PC6300.
        !             3:        Copyright (C) Karl Dahlke 1987
        !             4:        This software may be freely used and distributed
        !             5:        for any non-profit purpose.
        !             6:  *-----------------------------------------------------------------------------
        !             7:  */
        !             8: 
        !             9: /* words.c: look up words in replacement table */
        !            10: 
        !            11: #include "speech.h"
        !            12: 
        !            13: #define isvowel(c) vowels[(c) - 'a']
        !            14: 
        !            15: /* several English suffixes are recognized.
        !            16:  * If present, the suffix may be removed, revealing the root word.
        !            17:  * We then look up the root word in the replacement table,
        !            18:  * and reapply the suffix.
        !            19:  * Thus you only need correct the pronunciation of the singular or present
        !            20:  * tense form of the word, and all regular conjugates are also corrected.
        !            21:  * The first array defines 10 suffixes.
        !            22:  * Additional arrays determine whether the final e or y is dropped,
        !            23:  * whether the final consonent is doubled, the length of the suffix, etc. */
        !            24: static char sufshorten[] = {0,1,2,2,3,4,2,1,3,2,2};
        !            25: static char suftab[] = "s   es  ies ing ing ing d   ed  ed  ied ";
        !            26: static char sufdrop[] = "  y  e   y";
        !            27: static char sufadd[] = {1,2,3,3,4,3,1,3,2,3};
        !            28: static char sufdouble[] = {0,0,0,0,1,0,0,1,0,0};
        !            29: 
        !            30: static char vowels[26] = {1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0};
        !            31: static short wdlen; /* length of word being spoken */
        !            32: 
        !            33: /* word replacement table */
        !            34: static char *wdreptbl;
        !            35: short sdwdrepreq = 5000; /* patchable */
        !            36: static short wdreplen, wdrepmax;
        !            37: 
        !            38: /* macro definition table */
        !            39: static char *mactbl;
        !            40: short sdmacreq = 5000; /* patchable */
        !            41: static short maclen, macmax;
        !            42: 
        !            43: 
        !            44: /* allocate word replacement table and macro definition table */
        !            45: sdtblload()
        !            46: {
        !            47: static char defreptbl[8];
        !            48: static char defmactbl[8];
        !            49: 
        !            50: if(wdreptbl = kalloc(sdwdrepreq)) {
        !            51: wdrepmax = sdwdrepreq; /* able to allocate requested amount */
        !            52: } else {
        !            53: wdreptbl = defreptbl;
        !            54: wdrepmax = 8;
        !            55: }
        !            56: wdreplen = 0;
        !            57: *wdreptbl = 0;
        !            58: 
        !            59: if(mactbl = kalloc(sdmacreq)) {
        !            60: macmax = sdmacreq; /* able to allocate requested amount */
        !            61: } else {
        !            62: mactbl = defmactbl;
        !            63: macmax = 8;
        !            64: }
        !            65: maclen = 0;
        !            66: *mactbl = 0;
        !            67: } /* sdtblload */
        !            68: 
        !            69: /* speak the current word in the active control structure */
        !            70: sdtextw()
        !            71: {
        !            72: if(sdc->rdflag && !sdc->onesymb)
        !            73: drainset(sdc);
        !            74: sdtext(sdw);
        !            75: } /* sdtextw */
        !            76: 
        !            77: /* speak current character */
        !            78: curchar(sayit, asword)
        !            79: {
        !            80: register char c;
        !            81: register i;
        !            82: char *t;
        !            83: static char ctrlstr[] = "controal x";
        !            84: /* phonetic alphabet, words for letters to avoid ambiguity.
        !            85:  * important when you need to know exactly which letter  (e.g. m or n)
        !            86:  * such as variables for equations or programs
        !            87:  * words taken from the NATO standard, established in the 1960's
        !            88:  * 10 bytes per entry.  */
        !            89: static char wfl[] = "\
        !            90: al fa~~~~~brohvo~~~~charlie~~~\
        !            91: delta~~~~~eko~~~~~~~foxtrot~~~\
        !            92: gawlf~~~~~hoatel~~~~india~~~~~\
        !            93: juleyet~~~killo~~~~~liema~~~~~\
        !            94: mike~~~~~~noavember~oscar~~~~~\
        !            95: popa~~~~~~kebeck~~~~roamio~~~~\
        !            96: seeara~~~~tango~~~~~uniform~~~\
        !            97: victor~~~~wiskey~~~~x ray~~~~~\
        !            98: yangkey~~~zoolu~~~~~\
        !            99: ";
        !           100: 
        !           101: sdw[0] = 0;
        !           102: cursor_set();
        !           103: c = getc();
        !           104: 
        !           105: if(c == '\07') {
        !           106: if(!sdsession && sdnoises) { sdsound(3); return; }
        !           107: t = "bell";
        !           108: goto copywd;
        !           109: }
        !           110: if(c == '\r') {
        !           111: if(!sdsession && sdnoises) { sdcrsnd(); return; }
        !           112: if(sdc->rdflag) return;
        !           113: t = "line";
        !           114: goto copywd;
        !           115: }
        !           116: if(c == '\12') {
        !           117: t = "feed";
        !           118: goto copywd;
        !           119: }
        !           120: 
        !           121: if(c && c < 27) {
        !           122: ctrlstr[9] = c|0x40;
        !           123: t = ctrlstr;
        !           124: 
        !           125: copywd:
        !           126: i = strlen(t);
        !           127: memcpy(sdw, t, ++i);
        !           128: if(sayit) sdtextw();
        !           129: return;
        !           130: }
        !           131: 
        !           132: i = c;
        !           133: if(c) i -= 26;
        !           134: if(c >= '0') {
        !           135: if(c <= '9') goto onelet;
        !           136: i -= 10;
        !           137: }
        !           138: if(c >= 'A') {
        !           139: if(c <= 'Z') goto onelet;
        !           140: i -= 26;
        !           141: }
        !           142: if(c >= 'a') {
        !           143: if(c <= 'z') goto onelet;
        !           144: i -= 26;
        !           145: }
        !           146: 
        !           147: t = sdc->punctab + 10*i;
        !           148: goto copywd10;
        !           149: 
        !           150: onelet:
        !           151: sdw[0] = c | 0x20;
        !           152: sdw[1] = 0;
        !           153: if(asword && c > '9') {
        !           154: t = wfl + 10*(sdw[0] - 'a');
        !           155: copywd10:
        !           156: for(i=0; i<10; ++i)
        !           157: if((sdw[i] = t[i]) == '~') break;
        !           158: sdw[i] = 0;
        !           159: }
        !           160: if(sayit) sdtextw();
        !           161: } /* curchar */
        !           162: 
        !           163: /* read text until EOF or newline or end of symbol */
        !           164: reading()
        !           165: {
        !           166: short i;
        !           167: char c, past_eof, waspunct;
        !           168: 
        !           169: cursor_copy();
        !           170: past_eof = waspunct = 0;
        !           171: 
        !           172: /* skip whitespace */
        !           173: while(getc() == ' ')
        !           174: if(incptr()) { stopread(); return; }
        !           175: 
        !           176: c = getc();
        !           177: if(isdigit(c)) {
        !           178: for(i=0; i<WORDLEN; ++i) {
        !           179: sdw[i] = c;
        !           180: if(incptr()) { past_eof = 1; break; }
        !           181: c = getc();
        !           182: if(!isdigit(c)) break;
        !           183: }
        !           184: if(i < WORDLEN) ++i;
        !           185: sdw[i] = 0;
        !           186: goto spkbuf;
        !           187: } /* end number */
        !           188: 
        !           189: c |= 0x20;
        !           190: if(isalnum(c)) {
        !           191: for(i=0; i<WORDLEN; ++i) {
        !           192: sdw[i] = c;
        !           193: if(incptr()) { past_eof = 1; break; }
        !           194: c = getc() | 0x20;
        !           195: if(!islower(c)) break;
        !           196: }
        !           197: if(i < WORDLEN) ++i;
        !           198: sdw[i] = 0;
        !           199: 
        !           200: wdlen = i;
        !           201: wdexpand();
        !           202: 
        !           203: spkbuf:
        !           204: sdtextw();
        !           205: endword:
        !           206: if(past_eof ||
        !           207: sdc->onesymb && (waspunct || !isalnum(getc())) ||
        !           208: sdc->oneline && waspunct == 2) {
        !           209: stopread();
        !           210: decptr();
        !           211: }
        !           212: cursor_set();
        !           213: return;
        !           214: } /* end word */
        !           215: 
        !           216: /* it's a symbol */
        !           217: waspunct = 1;
        !           218: curchar(0, 0);
        !           219: if(getc() == '\r') waspunct = 2;
        !           220: 
        !           221: if(sdw[0]) { /* string to be spoken */
        !           222: /* check for an entire line of the symbol */
        !           223: c = getc();
        !           224: i = 1;
        !           225: while(!(past_eof = incptr()) && getc() == c) ++i;
        !           226: if(i > 4) { /* too  many, just give count */
        !           227: static char repeat[] = "length xxxxx";
        !           228: int n = i;
        !           229: for(i=4; i>=0; --i) { repeat[i+7] = n%10 + '0'; n /= 10; }
        !           230: for(i=0; i<4; ++i) if(repeat[i+7] != '0') break;
        !           231: memcpy(repeat+7, repeat+7+i, 5);
        !           232: 
        !           233: /* curchar() was called in setup mode, 
        !           234:  * just tack this repeat modifyier on the end of sdw[] */
        !           235: n = strlen(sdw);
        !           236: sdw[n++] = ' ';
        !           237: memcpy(sdw+n, repeat, 14);
        !           238: goto spkbuf;
        !           239: }
        !           240: 
        !           241: cursor_copy();
        !           242: sdtextw();
        !           243: }
        !           244: 
        !           245: past_eof = incptr();
        !           246: goto endword;
        !           247: } /* reading */
        !           248: 
        !           249: /* find word in lookup table, or check for acronym */
        !           250: static wdexpand()
        !           251: {
        !           252: short foundit;
        !           253: short root;
        !           254: 
        !           255: if(lookup()) return; /* word replaced */
        !           256: 
        !           257: if(root = mkroot()) {
        !           258: wdlen -= sufshorten[root];
        !           259: foundit = lookup();
        !           260: reconst(root);
        !           261: if(foundit) return;
        !           262: }
        !           263: 
        !           264: acron();
        !           265: } /* wdexpand */
        !           266: 
        !           267: /* extract the root word */
        !           268: static mkroot()
        !           269: {
        !           270: char l0, l1, l2, l3, l4; /* letters */
        !           271: short l;
        !           272: 
        !           273: l = wdlen - 5;
        !           274: if(l < 0) return 0; /* word too short to safely "rootinize" */
        !           275: l4 = sdw[l+4];
        !           276: l3 = sdw[l+3];
        !           277: l2 = sdw[l+2];
        !           278: l1 = sdw[l+1];
        !           279: l0 = sdw[l+0];
        !           280: if(l4 == 's') { /* possible plural */
        !           281: if(l3 == 's' || l3 == 'i' || l3 == 'a' || l3 == 'u') return 0;
        !           282: if(l3 == 'e') {
        !           283: if(l2 == 'i') {
        !           284: sdw[l+2] = 'y';
        !           285: sdw[l+3] = 0;
        !           286: return 3;
        !           287: }
        !           288: if(l2 == 's' || l2 == 'h' || l2 == 'z') {
        !           289: sdw[l+3] = 0;
        !           290: return 2;
        !           291: }
        !           292: }
        !           293: /* normal plural */
        !           294: sdw[l+4] = 0;
        !           295: return 1;
        !           296: } /* end final s */
        !           297: 
        !           298: if(l == 0) return 0; /* too short */
        !           299: 
        !           300: if(l4 == 'g') { /* possible present progressive */
        !           301: if(l3 != 'n' || l2 != 'i') return 0;
        !           302: if(!isvowel(l1)) {
        !           303: if(l1 == l0) { sdw[l+1] = 0; return 5; }
        !           304: if(isvowel(l0) &&  l0 < 'w' && !isvowel(sdw[l-1])) {
        !           305: sdw[l+2] = 'e';
        !           306: sdw[l+3] = 0;
        !           307: return 6;
        !           308: }
        !           309: }
        !           310: sdw[l+2] = 0;
        !           311: return 4;
        !           312: } /* end ing */
        !           313: 
        !           314: if(l4 == 'd') { /* possible past tense */
        !           315: if(l3 != 'e') return 0;
        !           316: if(l2 == 'i') {
        !           317: sdw[l+2] = 'y';
        !           318: sdw[l+3] = 0;
        !           319: return 10;
        !           320: }
        !           321: if(!isvowel(l2)) {
        !           322: if(l2 == l1) { sdw[l+2] = 0; return 8; }
        !           323: if(isvowel(l1) && l1 < 'w' && !isvowel(l0)) {
        !           324: sdw[l+4] = 0;
        !           325: return 7;
        !           326: }
        !           327: }
        !           328: sdw[l+3] = 0;
        !           329: return 9;
        !           330: } /* end final ed */
        !           331: 
        !           332: return 0;
        !           333: } /* mkroot */
        !           334: 
        !           335: /* reconstruct word based on root and removed suffixes */
        !           336: static reconst(root)
        !           337: {
        !           338: register char *t;
        !           339: register i;
        !           340: char c;
        !           341: 
        !           342: if(root--) {
        !           343: t = sdw + wdlen-1;
        !           344: wdlen += sufadd[root];
        !           345: if(sufdouble[root]) c = *t, *++t = c;
        !           346: if(sufdrop[root] == *t) --t, --wdlen;
        !           347: for(i=4*root; i<4*root+4; ++i)
        !           348: *++t = suftab[i];
        !           349: sdw[wdlen] = 0;
        !           350: } /* a real root */
        !           351: } /* reconst */
        !           352: 
        !           353: static char *sublookup(w, length)
        !           354: char *w;
        !           355: short length;
        !           356: {
        !           357: register char *t;
        !           358: register short n;
        !           359: short i;
        !           360: 
        !           361: /* loop over words in the table */
        !           362: for(t = wdreptbl; n = *t; t += n+2 + t[n+1]) {
        !           363: /* check length and first letter */
        !           364: if(n != length) continue;
        !           365: if(t[1] != *w) continue;
        !           366: /* run strncmp */
        !           367: for(i=1; i<n; ++i)
        !           368: if(t[i+1] != sdw[i]) break;
        !           369: if(i < n) continue;
        !           370: return t; /* match */
        !           371: }
        !           372: return 0; /* no match */
        !           373: } /* sublookup */
        !           374: 
        !           375: /* lookup in macro table, similar to sublookup */
        !           376: char *submlookup(mset, key)
        !           377: char mset, key; /* active macro set and key */
        !           378: {
        !           379: register char *t;
        !           380: register short n;
        !           381: 
        !           382: /* loop over defined macros */
        !           383: for(t=mactbl; n = *t; t += n) {
        !           384: if(t[1] != mset) continue;
        !           385: if(t[2] != key) continue;
        !           386: return t;
        !           387: } /* end loop */
        !           388: 
        !           389: return 0; /* macro not defined */
        !           390: } /* submlookup */
        !           391: 
        !           392: /* look up word in pronounciation table */
        !           393: static lookup()
        !           394: {
        !           395: char *t;
        !           396: 
        !           397: if(!(t = sublookup(sdw, wdlen))) return 0;
        !           398: 
        !           399: t += wdlen+1;
        !           400: wdlen = *t++;
        !           401: memcpy(sdw, t, wdlen);
        !           402: sdw[wdlen] = 0;
        !           403: return 1;
        !           404: } /* lookup */
        !           405: 
        !           406: /* if it is an acronym, insert blanks to pronounce letters */
        !           407: static acron()
        !           408: {
        !           409: register i, j;
        !           410: /* legal english three letter initial consonent clusters */
        !           411: static char iclu[] = "chrchlphrphlsclschscrshlshrshwsphsplsprstrthrthw~";
        !           412: 
        !           413: /* any vowels in the first four letters? */
        !           414: for(j=0,i=0; i<4; ++i) {
        !           415: if(sdw[i] == 0) break;
        !           416: j += isvowel(sdw[i]);
        !           417: }
        !           418: if(j == 0 || j ==  4 || j == wdlen)
        !           419: goto insert;
        !           420: 
        !           421: if(j != 1 || wdlen < 4 || !isvowel(sdw[3])) return;
        !           422: 
        !           423: for(i=0; iclu[i] != '~'; i+=3) {
        !           424: if(iclu[i] != sdw[0]) continue;
        !           425: if(iclu[i+1] != sdw[1]) continue;
        !           426: if(iclu[i+2] != sdw[2]) continue;
        !           427: return;
        !           428: }
        !           429: 
        !           430: insert:
        !           431: /* doesn't look very english, insert blanks */
        !           432: i = wdlen-1;
        !           433: wdlen = j = i + i + 1;
        !           434: while(i >= 0) {
        !           435: sdw[j--] = ' ';
        !           436: sdw[j--] = sdw[i--];
        !           437: }
        !           438: sdw[wdlen] = 0;
        !           439: } /* acron */
        !           440: 
        !           441: stopread()
        !           442: {
        !           443: sdc->rdflag = sdc->onesymb = 0;
        !           444: } /* stopread */
        !           445: 
        !           446: /* add a word to the pronunciation table */
        !           447: addword(s)
        !           448: char *s;
        !           449: {
        !           450: char c;
        !           451: char *t;
        !           452: short i;
        !           453: 
        !           454: i = stringcheck(s, 0);
        !           455: c = s[0];
        !           456: if(isdigit(c) || i == 3) return 3;
        !           457: if(!c) return 0; /* blank line */
        !           458: 
        !           459: if(islower(c)) {
        !           460: /* word replacement */
        !           461: 
        !           462: /* first remove the old definition */
        !           463: for(i=0; s[i] && s[i] != ' '; ++i)  ;
        !           464: c = i;
        !           465: if(t = sublookup(s, c)) {
        !           466: i = c + t[c+1] + 2;
        !           467: wdreplen -= i;
        !           468: memcpy(t, t+i, wdreplen - (t-wdreptbl) + 1);
        !           469: }
        !           470: 
        !           471: if(s[c]) {
        !           472: i = strlen(s);
        !           473: if(wdreplen + i >= wdrepmax-1)
        !           474: return 4; /* not enough room */
        !           475: t = wdreptbl + wdreplen;
        !           476: memcpy(t+1, s, i);
        !           477: t[++i] = 0;
        !           478: wdreplen += i;
        !           479: *t = c;
        !           480: t[c+1] = i-c-2;
        !           481: }
        !           482: return 0;
        !           483: } /* end word replacement */
        !           484: 
        !           485: /* punctuation replacement */
        !           486: if(c > 'a') c -= 26;
        !           487: if(c > 'A') c -= 26;
        !           488: if(c > '0') c -= 10;
        !           489: c -= ' ';
        !           490: c += 6;
        !           491: 
        !           492: for(++s; *s; ++s)
        !           493: if(*s != ' ') break;
        !           494: if(!*s) return 3;
        !           495: 
        !           496: t = sdc->punctab + 10*c;
        !           497: for(i=0; i<10; ++i) {
        !           498: if(!s[i]) break;
        !           499: t[i] = s[i];
        !           500: }
        !           501: if(s[i]) return 4;
        !           502: 
        !           503: while(i < 10)
        !           504: t[i++] = '~';
        !           505: 
        !           506: return 0;
        !           507: } /* addword */
        !           508: 
        !           509: static stringcheck(s, macro)
        !           510: char *s;
        !           511: {
        !           512: short i, j;
        !           513: char c, wasblank, macless;
        !           514: 
        !           515: wasblank = 1;
        !           516: macless = 0;
        !           517: for(i=j=0; c = s[i]; ++i) {
        !           518: if(!macless) {
        !           519: if(isupper(c)) c |= 0x20;
        !           520: if(c == '\t') c = ' ';
        !           521: }
        !           522: s[j++] = c;
        !           523: if(macless) continue;
        !           524: if(macro && c == '<') { macless = 1; continue; }
        !           525: if(c == ' ') {
        !           526: if(wasblank) --j;
        !           527: wasblank = 1;
        !           528: continue;
        !           529: }
        !           530: wasblank = 0;
        !           531: if(c & 0x80 || c < ' ') return 3;
        !           532: if(c == '.' && j == 2 && s[0] == '#') continue; /* ok */
        !           533: if(j != 1 && !isalnum(c)) return 3;
        !           534: }
        !           535: if(wasblank && j && !macro) --j;
        !           536: s[j] = 0;
        !           537: 
        !           538: return (macro && !macless) ? 3 : 0;
        !           539: } /* stringcheck */
        !           540: 
        !           541: keybind(s, macro)
        !           542: char *s;
        !           543: {
        !           544: char c;
        !           545: char *t;
        !           546: struct SDCMD *cmdp;
        !           547: char altkey, ctrlkey, shiftkey;
        !           548: short i, keynum;
        !           549: static alpha_alt[] = {
        !           550: 0,30,48,46,32,18,33,34,35,23,36,37,38,50,49,24,25,16,19,31,20,22,47,17,45,21,44};
        !           551: static char pad_cmd[] = {
        !           552: 83,0,82,79,80,81,75,0,77,71,72,73};
        !           553: 
        !           554: i = stringcheck(s, macro);
        !           555: if(i == 3) return 3;
        !           556: c = *s++;
        !           557: if(!c) return 0; /* blank line */
        !           558: 
        !           559: keynum = 0;
        !           560: altkey = 0;
        !           561: ctrlkey = 0;
        !           562: shiftkey = 0;
        !           563: 
        !           564: switch(c) {
        !           565: case '@': /* alt key */
        !           566: altkey = 1;
        !           567: if(*s == 'f' && isdigit(s[1])) { ++s; goto fnkey; }
        !           568: goto letter;
        !           569: 
        !           570: case '+':
        !           571: shiftkey = 1;
        !           572: if(*s++ != 'f') return 3;
        !           573: /* fall through to function key */
        !           574: 
        !           575: case 'f': /* function key */
        !           576: fnkey:
        !           577: c = *s;
        !           578: while(isdigit(c)) {
        !           579: keynum = 10*keynum + c -'0';
        !           580: c = *++s;
        !           581: }
        !           582: if(keynum <= 0 || keynum > 10) return 3;
        !           583: keynum += 0x3a;
        !           584: if(shiftkey) keynum += 0x19;
        !           585: if(ctrlkey) keynum += 0x23;
        !           586: if(altkey) keynum += 0x2d;
        !           587: break;
        !           588: 
        !           589: case '#': /* number pad */
        !           590: c = *s++;
        !           591: if(c < '.' || c > '9') return 3;
        !           592: keynum = pad_cmd[c-'.'];
        !           593: if(!keynum) return 3;
        !           594: break;
        !           595: 
        !           596: case '^': /* control key */
        !           597: ctrlkey = 1;
        !           598: if(*s == 'f' && isdigit(s[1])) { ++s; goto fnkey; }
        !           599: letter:
        !           600: c = *s++;
        !           601: if(!islower(c)) return 3;
        !           602: c -= '`';
        !           603: if(altkey)
        !           604: keynum = alpha_alt[c];
        !           605: else keynum = c + 119;
        !           606: break;
        !           607: 
        !           608: default: return 3;
        !           609: } /* end switch on first char */
        !           610: 
        !           611: if(*s == ' ') ++s;
        !           612: 
        !           613: if(*s == '<') { /* macro */
        !           614: ++s;
        !           615: c = 10*sdsession + sdc->macsel;
        !           616: if(t = submlookup(c, keynum)) {
        !           617: /* drop old definition */
        !           618: i = *t;
        !           619: maclen -= i;
        !           620: memcpy(t, t+i, maclen - (t-mactbl) + 1);
        !           621: }
        !           622: 
        !           623: if(*s) { /* add new definition */
        !           624: i = strlen(s);
        !           625: if(maclen+i+4 >= macmax) return 4;
        !           626: t = mactbl + maclen;
        !           627: memcpy(t+3, s, i+1);
        !           628: t[1] = c;
        !           629: t[2] = keynum;
        !           630: i += 3;
        !           631: *t = i;
        !           632: maclen += i;
        !           633: }
        !           634: return 0;
        !           635: } /* end macro */
        !           636: 
        !           637: if(!*s) { /* unbind key */
        !           638: sdc->keymap[keynum] = 0;
        !           639: return 0;
        !           640: }
        !           641: 
        !           642: /* look for this command designator */
        !           643: cmdp = &sdcmds[1];
        !           644: while(*(t = cmdp->brief)) {
        !           645: for(i=0; s[i]; ++i)
        !           646: if(s[i] != t[i]) break;
        !           647: if(!(s[i] | t[i])) {
        !           648: sdc->keymap[keynum] = cmdp - sdcmds;
        !           649: return 0; /* key binding successful */
        !           650: }
        !           651: ++cmdp;
        !           652: } /* end loop through speech functions */
        !           653: 
        !           654: return 3; /* no such function */
        !           655: } /* keybind */
        !           656: 
        !           657: /* expand macro or simply place the key on the input queue */
        !           658: mexpand(session, key, xcmd)
        !           659: short key, xcmd;
        !           660: {
        !           661: struct SDCONTROL *o = sdcontrol[session];
        !           662: char *t;
        !           663: short n;
        !           664: 
        !           665: if(xcmd) {
        !           666: n = 10*session + o->macsel;
        !           667: if(t = submlookup(n, xcmd)) {
        !           668: n = *t;
        !           669: n -= 3, t += 3;
        !           670: while(n--) {
        !           671: /* warning!! MSDOS input expects shorts, not chars.
        !           672:  * The high byte is suppose to contain status bits, indicating
        !           673:  * shift/control/whatever.  I hope command.com, or whatever program
        !           674:  * is reading this input, does not really need these bits when
        !           675:  * the characters are simple ASCII. */
        !           676: #ifdef MSDOS
        !           677: if((*o->dev_in)(*t++)) {
        !           678: if(!session) sdsound(3);
        !           679: return;
        !           680: }
        !           681: #else
        !           682: (*o->dev_in)(*t++);
        !           683: #endif
        !           684: } /* end pushing macro onto input queue */
        !           685: return;
        !           686: } /* is macro defined */
        !           687: }
        !           688: 
        !           689: #ifdef MSDOS
        !           690: if((*o->dev_in)(key)) {
        !           691: if(!session) sdsound(3);
        !           692: }
        !           693: #else
        !           694: (*o->dev_in)(key);
        !           695: #endif
        !           696: } /* mexpand */
        !           697: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.