| /* |
| ** This module uses code from the NIST implementation of FIPS-181, |
| ** but the algorythm is CHANGED and I think that I CAN |
| ** copyright it. See copiright notes below. |
| */ |
| |
| /* |
| ** Copyright (c) 1999, 2000, 2001, 2002, 2003 |
| ** Adel I. Mirzazhanov. All rights reserved |
| ** |
| ** Redistribution and use in source and binary forms, with or without |
| ** modification, are permitted provided that the following conditions |
| ** are met: |
| ** |
| ** 1.Redistributions of source code must retain the above copyright notice, |
| ** this list of conditions and the following disclaimer. |
| ** 2.Redistributions in binary form must reproduce the above copyright |
| ** notice, this list of conditions and the following disclaimer in the |
| ** documentation and/or other materials provided with the distribution. |
| ** 3.The name of the author may not be used to endorse or promote products |
| ** derived from this software without specific prior written permission. |
| ** |
| ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS |
| ** OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| ** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| ** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
| ** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
| ** GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| ** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32) && !defined(__WIN32__) |
| #include <strings.h> |
| #endif |
| #include <time.h> |
| #include <sys/types.h> |
| #include "base/rand_util.h" |
| #include "fips181.h" |
| #include "randpass.h" |
| #include "convert.h" |
| |
| struct unit |
| { |
| char unit_code[5]; |
| USHORT flags; |
| }; |
| |
| static struct unit rules[] = |
| { {"a", VOWEL}, |
| {"b", NO_SPECIAL_RULE}, |
| {"c", NO_SPECIAL_RULE}, |
| {"d", NO_SPECIAL_RULE}, |
| {"e", NO_FINAL_SPLIT | VOWEL}, |
| {"f", NO_SPECIAL_RULE}, |
| {"g", NO_SPECIAL_RULE}, |
| {"h", NO_SPECIAL_RULE}, |
| {"i", VOWEL}, |
| {"j", NO_SPECIAL_RULE}, |
| {"k", NO_SPECIAL_RULE}, |
| {"l", NO_SPECIAL_RULE}, |
| {"m", NO_SPECIAL_RULE}, |
| {"n", NO_SPECIAL_RULE}, |
| {"o", VOWEL}, |
| {"p", NO_SPECIAL_RULE}, |
| {"r", NO_SPECIAL_RULE}, |
| {"s", NO_SPECIAL_RULE}, |
| {"t", NO_SPECIAL_RULE}, |
| {"u", VOWEL}, |
| {"v", NO_SPECIAL_RULE}, |
| {"w", NO_SPECIAL_RULE}, |
| {"x", NOT_BEGIN_SYLLABLE}, |
| {"y", ALTERNATE_VOWEL | VOWEL}, |
| {"z", NO_SPECIAL_RULE}, |
| {"ch", NO_SPECIAL_RULE}, |
| {"gh", NO_SPECIAL_RULE}, |
| {"ph", NO_SPECIAL_RULE}, |
| {"rh", NO_SPECIAL_RULE}, |
| {"sh", NO_SPECIAL_RULE}, |
| {"th", NO_SPECIAL_RULE}, |
| {"wh", NO_SPECIAL_RULE}, |
| {"qu", NO_SPECIAL_RULE}, |
| {"ck", NOT_BEGIN_SYLLABLE} |
| }; |
| |
| static int digram[][RULE_SIZE] = |
| { |
| {/* aa */ ILLEGAL_PAIR, |
| /* ab */ ANY_COMBINATION, |
| /* ac */ ANY_COMBINATION, |
| /* ad */ ANY_COMBINATION, |
| /* ae */ ILLEGAL_PAIR, |
| /* af */ ANY_COMBINATION, |
| /* ag */ ANY_COMBINATION, |
| /* ah */ NOT_BEGIN | BREAK | NOT_END, |
| /* ai */ ANY_COMBINATION, |
| /* aj */ ANY_COMBINATION, |
| /* ak */ ANY_COMBINATION, |
| /* al */ ANY_COMBINATION, |
| /* am */ ANY_COMBINATION, |
| /* an */ ANY_COMBINATION, |
| /* ao */ ILLEGAL_PAIR, |
| /* ap */ ANY_COMBINATION, |
| /* ar */ ANY_COMBINATION, |
| /* as */ ANY_COMBINATION, |
| /* at */ ANY_COMBINATION, |
| /* au */ ANY_COMBINATION, |
| /* av */ ANY_COMBINATION, |
| /* aw */ ANY_COMBINATION, |
| /* ax */ ANY_COMBINATION, |
| /* ay */ ANY_COMBINATION, |
| /* az */ ANY_COMBINATION, |
| /* ach */ ANY_COMBINATION, |
| /* agh */ ILLEGAL_PAIR, |
| /* aph */ ANY_COMBINATION, |
| /* arh */ ILLEGAL_PAIR, |
| /* ash */ ANY_COMBINATION, |
| /* ath */ ANY_COMBINATION, |
| /* awh */ ILLEGAL_PAIR, |
| /* aqu */ BREAK | NOT_END, |
| /* ack */ ANY_COMBINATION}, |
| {/* ba */ ANY_COMBINATION, |
| /* bb */ NOT_BEGIN | BREAK | NOT_END, |
| /* bc */ NOT_BEGIN | BREAK | NOT_END, |
| /* bd */ NOT_BEGIN | BREAK | NOT_END, |
| /* be */ ANY_COMBINATION, |
| /* bf */ NOT_BEGIN | BREAK | NOT_END, |
| /* bg */ NOT_BEGIN | BREAK | NOT_END, |
| /* bh */ NOT_BEGIN | BREAK | NOT_END, |
| /* bi */ ANY_COMBINATION, |
| /* bj */ NOT_BEGIN | BREAK | NOT_END, |
| /* bk */ NOT_BEGIN | BREAK | NOT_END, |
| /* bl */ BEGIN | SUFFIX | NOT_END, |
| /* bm */ NOT_BEGIN | BREAK | NOT_END, |
| /* bn */ NOT_BEGIN | BREAK | NOT_END, |
| /* bo */ ANY_COMBINATION, |
| /* bp */ NOT_BEGIN | BREAK | NOT_END, |
| /* br */ BEGIN | END, |
| /* bs */ NOT_BEGIN, |
| /* bt */ NOT_BEGIN | BREAK | NOT_END, |
| /* bu */ ANY_COMBINATION, |
| /* bv */ NOT_BEGIN | BREAK | NOT_END, |
| /* bw */ NOT_BEGIN | BREAK | NOT_END, |
| /* bx */ ILLEGAL_PAIR, |
| /* by */ ANY_COMBINATION, |
| /* bz */ NOT_BEGIN | BREAK | NOT_END, |
| /* bch */ NOT_BEGIN | BREAK | NOT_END, |
| /* bgh */ ILLEGAL_PAIR, |
| /* bph */ NOT_BEGIN | BREAK | NOT_END, |
| /* brh */ ILLEGAL_PAIR, |
| /* bsh */ NOT_BEGIN | BREAK | NOT_END, |
| /* bth */ NOT_BEGIN | BREAK | NOT_END, |
| /* bwh */ ILLEGAL_PAIR, |
| /* bqu */ NOT_BEGIN | BREAK | NOT_END, |
| /* bck */ ILLEGAL_PAIR }, |
| {/* ca */ ANY_COMBINATION, |
| /* cb */ NOT_BEGIN | BREAK | NOT_END, |
| /* cc */ NOT_BEGIN | BREAK | NOT_END, |
| /* cd */ NOT_BEGIN | BREAK | NOT_END, |
| /* ce */ ANY_COMBINATION, |
| /* cf */ NOT_BEGIN | BREAK | NOT_END, |
| /* cg */ NOT_BEGIN | BREAK | NOT_END, |
| /* ch */ NOT_BEGIN | BREAK | NOT_END, |
| /* ci */ ANY_COMBINATION, |
| /* cj */ NOT_BEGIN | BREAK | NOT_END, |
| /* ck */ NOT_BEGIN | BREAK | NOT_END, |
| /* cl */ SUFFIX | NOT_END, |
| /* cm */ NOT_BEGIN | BREAK | NOT_END, |
| /* cn */ NOT_BEGIN | BREAK | NOT_END, |
| /* co */ ANY_COMBINATION, |
| /* cp */ NOT_BEGIN | BREAK | NOT_END, |
| /* cr */ NOT_END, |
| /* cs */ NOT_BEGIN | END, |
| /* ct */ NOT_BEGIN | PREFIX, |
| /* cu */ ANY_COMBINATION, |
| /* cv */ NOT_BEGIN | BREAK | NOT_END, |
| /* cw */ NOT_BEGIN | BREAK | NOT_END, |
| /* cx */ ILLEGAL_PAIR, |
| /* cy */ ANY_COMBINATION, |
| /* cz */ NOT_BEGIN | BREAK | NOT_END, |
| /* cch */ ILLEGAL_PAIR, |
| /* cgh */ ILLEGAL_PAIR, |
| /* cph */ NOT_BEGIN | BREAK | NOT_END, |
| /* crh */ ILLEGAL_PAIR, |
| /* csh */ NOT_BEGIN | BREAK | NOT_END, |
| /* cth */ NOT_BEGIN | BREAK | NOT_END, |
| /* cwh */ ILLEGAL_PAIR, |
| /* cqu */ NOT_BEGIN | SUFFIX | NOT_END, |
| /* cck */ ILLEGAL_PAIR}, |
| {/* da */ ANY_COMBINATION, |
| /* db */ NOT_BEGIN | BREAK | NOT_END, |
| /* dc */ NOT_BEGIN | BREAK | NOT_END, |
| /* dd */ NOT_BEGIN, |
| /* de */ ANY_COMBINATION, |
| /* df */ NOT_BEGIN | BREAK | NOT_END, |
| /* dg */ NOT_BEGIN | BREAK | NOT_END, |
| /* dh */ NOT_BEGIN | BREAK | NOT_END, |
| /* di */ ANY_COMBINATION, |
| /* dj */ NOT_BEGIN | BREAK | NOT_END, |
| /* dk */ NOT_BEGIN | BREAK | NOT_END, |
| /* dl */ NOT_BEGIN | BREAK | NOT_END, |
| /* dm */ NOT_BEGIN | BREAK | NOT_END, |
| /* dn */ NOT_BEGIN | BREAK | NOT_END, |
| /* do */ ANY_COMBINATION, |
| /* dp */ NOT_BEGIN | BREAK | NOT_END, |
| /* dr */ BEGIN | NOT_END, |
| /* ds */ NOT_BEGIN | END, |
| /* dt */ NOT_BEGIN | BREAK | NOT_END, |
| /* du */ ANY_COMBINATION, |
| /* dv */ NOT_BEGIN | BREAK | NOT_END, |
| /* dw */ NOT_BEGIN | BREAK | NOT_END, |
| /* dx */ ILLEGAL_PAIR, |
| /* dy */ ANY_COMBINATION, |
| /* dz */ NOT_BEGIN | BREAK | NOT_END, |
| /* dch */ NOT_BEGIN | BREAK | NOT_END, |
| /* dgh */ NOT_BEGIN | BREAK | NOT_END, |
| /* dph */ NOT_BEGIN | BREAK | NOT_END, |
| /* drh */ ILLEGAL_PAIR, |
| /* dsh */ NOT_BEGIN | NOT_END, |
| /* dth */ NOT_BEGIN | PREFIX, |
| /* dwh */ ILLEGAL_PAIR, |
| /* dqu */ NOT_BEGIN | BREAK | NOT_END, |
| /* dck */ ILLEGAL_PAIR }, |
| {/* ea */ ANY_COMBINATION, |
| /* eb */ ANY_COMBINATION, |
| /* ec */ ANY_COMBINATION, |
| /* ed */ ANY_COMBINATION, |
| /* ee */ ANY_COMBINATION, |
| /* ef */ ANY_COMBINATION, |
| /* eg */ ANY_COMBINATION, |
| /* eh */ NOT_BEGIN | BREAK | NOT_END, |
| /* ei */ NOT_END, |
| /* ej */ ANY_COMBINATION, |
| /* ek */ ANY_COMBINATION, |
| /* el */ ANY_COMBINATION, |
| /* em */ ANY_COMBINATION, |
| /* en */ ANY_COMBINATION, |
| /* eo */ BREAK, |
| /* ep */ ANY_COMBINATION, |
| /* er */ ANY_COMBINATION, |
| /* es */ ANY_COMBINATION, |
| /* et */ ANY_COMBINATION, |
| /* eu */ ANY_COMBINATION, |
| /* ev */ ANY_COMBINATION, |
| /* ew */ ANY_COMBINATION, |
| /* ex */ ANY_COMBINATION, |
| /* ey */ ANY_COMBINATION, |
| /* ez */ ANY_COMBINATION, |
| /* ech */ ANY_COMBINATION, |
| /* egh */ NOT_BEGIN | BREAK | NOT_END, |
| /* eph */ ANY_COMBINATION, |
| /* erh */ ILLEGAL_PAIR, |
| /* esh */ ANY_COMBINATION, |
| /* eth */ ANY_COMBINATION, |
| /* ewh */ ILLEGAL_PAIR, |
| /* equ */ BREAK | NOT_END, |
| /* eck */ ANY_COMBINATION }, |
| {/* fa */ ANY_COMBINATION, |
| /* fb */ NOT_BEGIN | BREAK | NOT_END, |
| /* fc */ NOT_BEGIN | BREAK | NOT_END, |
| /* fd */ NOT_BEGIN | BREAK | NOT_END, |
| /* fe */ ANY_COMBINATION, |
| /* ff */ NOT_BEGIN, |
| /* fg */ NOT_BEGIN | BREAK | NOT_END, |
| /* fh */ NOT_BEGIN | BREAK | NOT_END, |
| /* fi */ ANY_COMBINATION, |
| /* fj */ NOT_BEGIN | BREAK | NOT_END, |
| /* fk */ NOT_BEGIN | BREAK | NOT_END, |
| /* fl */ BEGIN | SUFFIX | NOT_END, |
| /* fm */ NOT_BEGIN | BREAK | NOT_END, |
| /* fn */ NOT_BEGIN | BREAK | NOT_END, |
| /* fo */ ANY_COMBINATION, |
| /* fp */ NOT_BEGIN | BREAK | NOT_END, |
| /* fr */ BEGIN | NOT_END, |
| /* fs */ NOT_BEGIN, |
| /* ft */ NOT_BEGIN, |
| /* fu */ ANY_COMBINATION, |
| /* fv */ NOT_BEGIN | BREAK | NOT_END, |
| /* fw */ NOT_BEGIN | BREAK | NOT_END, |
| /* fx */ ILLEGAL_PAIR, |
| /* fy */ NOT_BEGIN, |
| /* fz */ NOT_BEGIN | BREAK | NOT_END, |
| /* fch */ NOT_BEGIN | BREAK | NOT_END, |
| /* fgh */ NOT_BEGIN | BREAK | NOT_END, |
| /* fph */ NOT_BEGIN | BREAK | NOT_END, |
| /* frh */ ILLEGAL_PAIR, |
| /* fsh */ NOT_BEGIN | BREAK | NOT_END, |
| /* fth */ NOT_BEGIN | BREAK | NOT_END, |
| /* fwh */ ILLEGAL_PAIR, |
| /* fqu */ NOT_BEGIN | BREAK | NOT_END, |
| /* fck */ ILLEGAL_PAIR }, |
| {/* ga */ ANY_COMBINATION, |
| /* gb */ NOT_BEGIN | BREAK | NOT_END, |
| /* gc */ NOT_BEGIN | BREAK | NOT_END, |
| /* gd */ NOT_BEGIN | BREAK | NOT_END, |
| /* ge */ ANY_COMBINATION, |
| /* gf */ NOT_BEGIN | BREAK | NOT_END, |
| /* gg */ NOT_BEGIN, |
| /* gh */ NOT_BEGIN | BREAK | NOT_END, |
| /* gi */ ANY_COMBINATION, |
| /* gj */ NOT_BEGIN | BREAK | NOT_END, |
| /* gk */ ILLEGAL_PAIR, |
| /* gl */ BEGIN | SUFFIX | NOT_END, |
| /* gm */ NOT_BEGIN | BREAK | NOT_END, |
| /* gn */ NOT_BEGIN | BREAK | NOT_END, |
| /* go */ ANY_COMBINATION, |
| /* gp */ NOT_BEGIN | BREAK | NOT_END, |
| /* gr */ BEGIN | NOT_END, |
| /* gs */ NOT_BEGIN | END, |
| /* gt */ NOT_BEGIN | BREAK | NOT_END, |
| /* gu */ ANY_COMBINATION, |
| /* gv */ NOT_BEGIN | BREAK | NOT_END, |
| /* gw */ NOT_BEGIN | BREAK | NOT_END, |
| /* gx */ ILLEGAL_PAIR, |
| /* gy */ NOT_BEGIN, |
| /* gz */ NOT_BEGIN | BREAK | NOT_END, |
| /* gch */ NOT_BEGIN | BREAK | NOT_END, |
| /* ggh */ ILLEGAL_PAIR, |
| /* gph */ NOT_BEGIN | BREAK | NOT_END, |
| /* grh */ ILLEGAL_PAIR, |
| /* gsh */ NOT_BEGIN, |
| /* gth */ NOT_BEGIN, |
| /* gwh */ ILLEGAL_PAIR, |
| /* gqu */ NOT_BEGIN | BREAK | NOT_END, |
| /* gck */ ILLEGAL_PAIR }, |
| {/* ha */ ANY_COMBINATION, |
| /* hb */ NOT_BEGIN | BREAK | NOT_END, |
| /* hc */ NOT_BEGIN | BREAK | NOT_END, |
| /* hd */ NOT_BEGIN | BREAK | NOT_END, |
| /* he */ ANY_COMBINATION, |
| /* hf */ NOT_BEGIN | BREAK | NOT_END, |
| /* hg */ NOT_BEGIN | BREAK | NOT_END, |
| /* hh */ ILLEGAL_PAIR, |
| /* hi */ ANY_COMBINATION, |
| /* hj */ NOT_BEGIN | BREAK | NOT_END, |
| /* hk */ NOT_BEGIN | BREAK | NOT_END, |
| /* hl */ NOT_BEGIN | BREAK | NOT_END, |
| /* hm */ NOT_BEGIN | BREAK | NOT_END, |
| /* hn */ NOT_BEGIN | BREAK | NOT_END, |
| /* ho */ ANY_COMBINATION, |
| /* hp */ NOT_BEGIN | BREAK | NOT_END, |
| /* hr */ NOT_BEGIN | BREAK | NOT_END, |
| /* hs */ NOT_BEGIN | BREAK | NOT_END, |
| /* ht */ NOT_BEGIN | BREAK | NOT_END, |
| /* hu */ ANY_COMBINATION, |
| /* hv */ NOT_BEGIN | BREAK | NOT_END, |
| /* hw */ NOT_BEGIN | BREAK | NOT_END, |
| /* hx */ ILLEGAL_PAIR, |
| /* hy */ ANY_COMBINATION, |
| /* hz */ NOT_BEGIN | BREAK | NOT_END, |
| /* hch */ NOT_BEGIN | BREAK | NOT_END, |
| /* hgh */ NOT_BEGIN | BREAK | NOT_END, |
| /* hph */ NOT_BEGIN | BREAK | NOT_END, |
| /* hrh */ ILLEGAL_PAIR, |
| /* hsh */ NOT_BEGIN | BREAK | NOT_END, |
| /* hth */ NOT_BEGIN | BREAK | NOT_END, |
| /* hwh */ ILLEGAL_PAIR, |
| /* hqu */ NOT_BEGIN | BREAK | NOT_END, |
| /* hck */ ILLEGAL_PAIR }, |
| {/* ia */ ANY_COMBINATION, |
| /* ib */ ANY_COMBINATION, |
| /* ic */ ANY_COMBINATION, |
| /* id */ ANY_COMBINATION, |
| /* ie */ NOT_BEGIN, |
| /* if */ ANY_COMBINATION, |
| /* ig */ ANY_COMBINATION, |
| /* ih */ NOT_BEGIN | BREAK | NOT_END, |
| /* ii */ ILLEGAL_PAIR, |
| /* ij */ ANY_COMBINATION, |
| /* ik */ ANY_COMBINATION, |
| /* il */ ANY_COMBINATION, |
| /* im */ ANY_COMBINATION, |
| /* in */ ANY_COMBINATION, |
| /* io */ BREAK, |
| /* ip */ ANY_COMBINATION, |
| /* ir */ ANY_COMBINATION, |
| /* is */ ANY_COMBINATION, |
| /* it */ ANY_COMBINATION, |
| /* iu */ NOT_BEGIN | BREAK | NOT_END, |
| /* iv */ ANY_COMBINATION, |
| /* iw */ NOT_BEGIN | BREAK | NOT_END, |
| /* ix */ ANY_COMBINATION, |
| /* iy */ NOT_BEGIN | BREAK | NOT_END, |
| /* iz */ ANY_COMBINATION, |
| /* ich */ ANY_COMBINATION, |
| /* igh */ NOT_BEGIN, |
| /* iph */ ANY_COMBINATION, |
| /* irh */ ILLEGAL_PAIR, |
| /* ish */ ANY_COMBINATION, |
| /* ith */ ANY_COMBINATION, |
| /* iwh */ ILLEGAL_PAIR, |
| /* iqu */ BREAK | NOT_END, |
| /* ick */ ANY_COMBINATION }, |
| {/* ja */ ANY_COMBINATION, |
| /* jb */ NOT_BEGIN | BREAK | NOT_END, |
| /* jc */ NOT_BEGIN | BREAK | NOT_END, |
| /* jd */ NOT_BEGIN | BREAK | NOT_END, |
| /* je */ ANY_COMBINATION, |
| /* jf */ NOT_BEGIN | BREAK | NOT_END, |
| /* jg */ ILLEGAL_PAIR, |
| /* jh */ NOT_BEGIN | BREAK | NOT_END, |
| /* ji */ ANY_COMBINATION, |
| /* jj */ ILLEGAL_PAIR, |
| /* jk */ NOT_BEGIN | BREAK | NOT_END, |
| /* jl */ NOT_BEGIN | BREAK | NOT_END, |
| /* jm */ NOT_BEGIN | BREAK | NOT_END, |
| /* jn */ NOT_BEGIN | BREAK | NOT_END, |
| /* jo */ ANY_COMBINATION, |
| /* jp */ NOT_BEGIN | BREAK | NOT_END, |
| /* jr */ NOT_BEGIN | BREAK | NOT_END, |
| /* js */ NOT_BEGIN | BREAK | NOT_END, |
| /* jt */ NOT_BEGIN | BREAK | NOT_END, |
| /* ju */ ANY_COMBINATION, |
| /* jv */ NOT_BEGIN | BREAK | NOT_END, |
| /* jw */ NOT_BEGIN | BREAK | NOT_END, |
| /* jx */ ILLEGAL_PAIR, |
| /* jy */ NOT_BEGIN, |
| /* jz */ NOT_BEGIN | BREAK | NOT_END, |
| /* jch */ NOT_BEGIN | BREAK | NOT_END, |
| /* jgh */ NOT_BEGIN | BREAK | NOT_END, |
| /* jph */ NOT_BEGIN | BREAK | NOT_END, |
| /* jrh */ ILLEGAL_PAIR, |
| /* jsh */ NOT_BEGIN | BREAK | NOT_END, |
| /* jth */ NOT_BEGIN | BREAK | NOT_END, |
| /* jwh */ ILLEGAL_PAIR, |
| /* jqu */ NOT_BEGIN | BREAK | NOT_END, |
| /* jck */ ILLEGAL_PAIR }, |
| {/* ka */ ANY_COMBINATION, |
| /* kb */ NOT_BEGIN | BREAK | NOT_END, |
| /* kc */ NOT_BEGIN | BREAK | NOT_END, |
| /* kd */ NOT_BEGIN | BREAK | NOT_END, |
| /* ke */ ANY_COMBINATION, |
| /* kf */ NOT_BEGIN | BREAK | NOT_END, |
| /* kg */ NOT_BEGIN | BREAK | NOT_END, |
| /* kh */ NOT_BEGIN | BREAK | NOT_END, |
| /* ki */ ANY_COMBINATION, |
| /* kj */ NOT_BEGIN | BREAK | NOT_END, |
| /* kk */ NOT_BEGIN | BREAK | NOT_END, |
| /* kl */ SUFFIX | NOT_END, |
| /* km */ NOT_BEGIN | BREAK | NOT_END, |
| /* kn */ BEGIN | SUFFIX | NOT_END, |
| /* ko */ ANY_COMBINATION, |
| /* kp */ NOT_BEGIN | BREAK | NOT_END, |
| /* kr */ SUFFIX | NOT_END, |
| /* ks */ NOT_BEGIN | END, |
| /* kt */ NOT_BEGIN | BREAK | NOT_END, |
| /* ku */ ANY_COMBINATION, |
| /* kv */ NOT_BEGIN | BREAK | NOT_END, |
| /* kw */ NOT_BEGIN | BREAK | NOT_END, |
| /* kx */ ILLEGAL_PAIR, |
| /* ky */ NOT_BEGIN, |
| /* kz */ NOT_BEGIN | BREAK | NOT_END, |
| /* kch */ NOT_BEGIN | BREAK | NOT_END, |
| /* kgh */ NOT_BEGIN | BREAK | NOT_END, |
| /* kph */ NOT_BEGIN | PREFIX, |
| /* krh */ ILLEGAL_PAIR, |
| /* ksh */ NOT_BEGIN, |
| /* kth */ NOT_BEGIN | BREAK | NOT_END, |
| /* kwh */ ILLEGAL_PAIR, |
| /* kqu */ NOT_BEGIN | BREAK | NOT_END, |
| /* kck */ ILLEGAL_PAIR }, |
| {/* la */ ANY_COMBINATION, |
| /* lb */ NOT_BEGIN | PREFIX, |
| /* lc */ NOT_BEGIN | BREAK | NOT_END, |
| /* ld */ NOT_BEGIN | PREFIX, |
| /* le */ ANY_COMBINATION, |
| /* lf */ NOT_BEGIN | PREFIX, |
| /* lg */ NOT_BEGIN | PREFIX, |
| /* lh */ NOT_BEGIN | BREAK | NOT_END, |
| /* li */ ANY_COMBINATION, |
| /* lj */ NOT_BEGIN | PREFIX, |
| /* lk */ NOT_BEGIN | PREFIX, |
| /* ll */ NOT_BEGIN | PREFIX, |
| /* lm */ NOT_BEGIN | PREFIX, |
| /* ln */ NOT_BEGIN | BREAK | NOT_END, |
| /* lo */ ANY_COMBINATION, |
| /* lp */ NOT_BEGIN | PREFIX, |
| /* lr */ NOT_BEGIN | BREAK | NOT_END, |
| /* ls */ NOT_BEGIN, |
| /* lt */ NOT_BEGIN | PREFIX, |
| /* lu */ ANY_COMBINATION, |
| /* lv */ NOT_BEGIN | PREFIX, |
| /* lw */ NOT_BEGIN | BREAK | NOT_END, |
| /* lx */ ILLEGAL_PAIR, |
| /* ly */ ANY_COMBINATION, |
| /* lz */ NOT_BEGIN | BREAK | NOT_END, |
| /* lch */ NOT_BEGIN | PREFIX, |
| /* lgh */ NOT_BEGIN | BREAK | NOT_END, |
| /* lph */ NOT_BEGIN | PREFIX, |
| /* lrh */ ILLEGAL_PAIR, |
| /* lsh */ NOT_BEGIN | PREFIX, |
| /* lth */ NOT_BEGIN | PREFIX, |
| /* lwh */ ILLEGAL_PAIR, |
| /* lqu */ NOT_BEGIN | BREAK | NOT_END, |
| /* lck */ ILLEGAL_PAIR }, |
| {/* ma */ ANY_COMBINATION, |
| /* mb */ NOT_BEGIN | BREAK | NOT_END, |
| /* mc */ NOT_BEGIN | BREAK | NOT_END, |
| /* md */ NOT_BEGIN | BREAK | NOT_END, |
| /* me */ ANY_COMBINATION, |
| /* mf */ NOT_BEGIN | BREAK | NOT_END, |
| /* mg */ NOT_BEGIN | BREAK | NOT_END, |
| /* mh */ NOT_BEGIN | BREAK | NOT_END, |
| /* mi */ ANY_COMBINATION, |
| /* mj */ NOT_BEGIN | BREAK | NOT_END, |
| /* mk */ NOT_BEGIN | BREAK | NOT_END, |
| /* ml */ NOT_BEGIN | BREAK | NOT_END, |
| /* mm */ NOT_BEGIN, |
| /* mn */ NOT_BEGIN | BREAK | NOT_END, |
| /* mo */ ANY_COMBINATION, |
| /* mp */ NOT_BEGIN, |
| /* mr */ NOT_BEGIN | BREAK | NOT_END, |
| /* ms */ NOT_BEGIN, |
| /* mt */ NOT_BEGIN, |
| /* mu */ ANY_COMBINATION, |
| /* mv */ NOT_BEGIN | BREAK | NOT_END, |
| /* mw */ NOT_BEGIN | BREAK | NOT_END, |
| /* mx */ ILLEGAL_PAIR, |
| /* my */ ANY_COMBINATION, |
| /* mz */ NOT_BEGIN | BREAK | NOT_END, |
| /* mch */ NOT_BEGIN | PREFIX, |
| /* mgh */ NOT_BEGIN | BREAK | NOT_END, |
| /* mph */ NOT_BEGIN, |
| /* mrh */ ILLEGAL_PAIR, |
| /* msh */ NOT_BEGIN, |
| /* mth */ NOT_BEGIN, |
| /* mwh */ ILLEGAL_PAIR, |
| /* mqu */ NOT_BEGIN | BREAK | NOT_END, |
| /* mck */ ILLEGAL_PAIR }, |
| {/* na */ ANY_COMBINATION, |
| /* nb */ NOT_BEGIN | BREAK | NOT_END, |
| /* nc */ NOT_BEGIN | BREAK | NOT_END, |
| /* nd */ NOT_BEGIN, |
| /* ne */ ANY_COMBINATION, |
| /* nf */ NOT_BEGIN | BREAK | NOT_END, |
| /* ng */ NOT_BEGIN | PREFIX, |
| /* nh */ NOT_BEGIN | BREAK | NOT_END, |
| /* ni */ ANY_COMBINATION, |
| /* nj */ NOT_BEGIN | BREAK | NOT_END, |
| /* nk */ NOT_BEGIN | PREFIX, |
| /* nl */ NOT_BEGIN | BREAK | NOT_END, |
| /* nm */ NOT_BEGIN | BREAK | NOT_END, |
| /* nn */ NOT_BEGIN, |
| /* no */ ANY_COMBINATION, |
| /* np */ NOT_BEGIN | BREAK | NOT_END, |
| /* nr */ NOT_BEGIN | BREAK | NOT_END, |
| /* ns */ NOT_BEGIN, |
| /* nt */ NOT_BEGIN, |
| /* nu */ ANY_COMBINATION, |
| /* nv */ NOT_BEGIN | BREAK | NOT_END, |
| /* nw */ NOT_BEGIN | BREAK | NOT_END, |
| /* nx */ ILLEGAL_PAIR, |
| /* ny */ NOT_BEGIN, |
| /* nz */ NOT_BEGIN | BREAK | NOT_END, |
| /* nch */ NOT_BEGIN | PREFIX, |
| /* ngh */ NOT_BEGIN | BREAK | NOT_END, |
| /* nph */ NOT_BEGIN | PREFIX, |
| /* nrh */ ILLEGAL_PAIR, |
| /* nsh */ NOT_BEGIN, |
| /* nth */ NOT_BEGIN, |
| /* nwh */ ILLEGAL_PAIR, |
| /* nqu */ NOT_BEGIN | BREAK | NOT_END, |
| /* nck */ NOT_BEGIN | PREFIX }, |
| {/* oa */ ANY_COMBINATION, |
| /* ob */ ANY_COMBINATION, |
| /* oc */ ANY_COMBINATION, |
| /* od */ ANY_COMBINATION, |
| /* oe */ ILLEGAL_PAIR, |
| /* of */ ANY_COMBINATION, |
| /* og */ ANY_COMBINATION, |
| /* oh */ NOT_BEGIN | BREAK | NOT_END, |
| /* oi */ ANY_COMBINATION, |
| /* oj */ ANY_COMBINATION, |
| /* ok */ ANY_COMBINATION, |
| /* ol */ ANY_COMBINATION, |
| /* om */ ANY_COMBINATION, |
| /* on */ ANY_COMBINATION, |
| /* oo */ ANY_COMBINATION, |
| /* op */ ANY_COMBINATION, |
| /* or */ ANY_COMBINATION, |
| /* os */ ANY_COMBINATION, |
| /* ot */ ANY_COMBINATION, |
| /* ou */ ANY_COMBINATION, |
| /* ov */ ANY_COMBINATION, |
| /* ow */ ANY_COMBINATION, |
| /* ox */ ANY_COMBINATION, |
| /* oy */ ANY_COMBINATION, |
| /* oz */ ANY_COMBINATION, |
| /* och */ ANY_COMBINATION, |
| /* ogh */ NOT_BEGIN, |
| /* oph */ ANY_COMBINATION, |
| /* orh */ ILLEGAL_PAIR, |
| /* osh */ ANY_COMBINATION, |
| /* oth */ ANY_COMBINATION, |
| /* owh */ ILLEGAL_PAIR, |
| /* oqu */ BREAK | NOT_END, |
| /* ock */ ANY_COMBINATION }, |
| {/* pa */ ANY_COMBINATION, |
| /* pb */ NOT_BEGIN | BREAK | NOT_END, |
| /* pc */ NOT_BEGIN | BREAK | NOT_END, |
| /* pd */ NOT_BEGIN | BREAK | NOT_END, |
| /* pe */ ANY_COMBINATION, |
| /* pf */ NOT_BEGIN | BREAK | NOT_END, |
| /* pg */ NOT_BEGIN | BREAK | NOT_END, |
| /* ph */ NOT_BEGIN | BREAK | NOT_END, |
| /* pi */ ANY_COMBINATION, |
| /* pj */ NOT_BEGIN | BREAK | NOT_END, |
| /* pk */ NOT_BEGIN | BREAK | NOT_END, |
| /* pl */ SUFFIX | NOT_END, |
| /* pm */ NOT_BEGIN | BREAK | NOT_END, |
| /* pn */ NOT_BEGIN | BREAK | NOT_END, |
| /* po */ ANY_COMBINATION, |
| /* pp */ NOT_BEGIN | PREFIX, |
| /* pr */ NOT_END, |
| /* ps */ NOT_BEGIN | END, |
| /* pt */ NOT_BEGIN | END, |
| /* pu */ NOT_BEGIN | END, |
| /* pv */ NOT_BEGIN | BREAK | NOT_END, |
| /* pw */ NOT_BEGIN | BREAK | NOT_END, |
| /* px */ ILLEGAL_PAIR, |
| /* py */ ANY_COMBINATION, |
| /* pz */ NOT_BEGIN | BREAK | NOT_END, |
| /* pch */ NOT_BEGIN | BREAK | NOT_END, |
| /* pgh */ NOT_BEGIN | BREAK | NOT_END, |
| /* pph */ NOT_BEGIN | BREAK | NOT_END, |
| /* prh */ ILLEGAL_PAIR, |
| /* psh */ NOT_BEGIN | BREAK | NOT_END, |
| /* pth */ NOT_BEGIN | BREAK | NOT_END, |
| /* pwh */ ILLEGAL_PAIR, |
| /* pqu */ NOT_BEGIN | BREAK | NOT_END, |
| /* pck */ ILLEGAL_PAIR }, |
| {/* ra */ ANY_COMBINATION, |
| /* rb */ NOT_BEGIN | PREFIX, |
| /* rc */ NOT_BEGIN | PREFIX, |
| /* rd */ NOT_BEGIN | PREFIX, |
| /* re */ ANY_COMBINATION, |
| /* rf */ NOT_BEGIN | PREFIX, |
| /* rg */ NOT_BEGIN | PREFIX, |
| /* rh */ NOT_BEGIN | BREAK | NOT_END, |
| /* ri */ ANY_COMBINATION, |
| /* rj */ NOT_BEGIN | PREFIX, |
| /* rk */ NOT_BEGIN | PREFIX, |
| /* rl */ NOT_BEGIN | PREFIX, |
| /* rm */ NOT_BEGIN | PREFIX, |
| /* rn */ NOT_BEGIN | PREFIX, |
| /* ro */ ANY_COMBINATION, |
| /* rp */ NOT_BEGIN | PREFIX, |
| /* rr */ NOT_BEGIN | PREFIX, |
| /* rs */ NOT_BEGIN | PREFIX, |
| /* rt */ NOT_BEGIN | PREFIX, |
| /* ru */ ANY_COMBINATION, |
| /* rv */ NOT_BEGIN | PREFIX, |
| /* rw */ NOT_BEGIN | BREAK | NOT_END, |
| /* rx */ ILLEGAL_PAIR, |
| /* ry */ ANY_COMBINATION, |
| /* rz */ NOT_BEGIN | PREFIX, |
| /* rch */ NOT_BEGIN | PREFIX, |
| /* rgh */ NOT_BEGIN | BREAK | NOT_END, |
| /* rph */ NOT_BEGIN | PREFIX, |
| /* rrh */ ILLEGAL_PAIR, |
| /* rsh */ NOT_BEGIN | PREFIX, |
| /* rth */ NOT_BEGIN | PREFIX, |
| /* rwh */ ILLEGAL_PAIR, |
| /* rqu */ NOT_BEGIN | PREFIX | NOT_END, |
| /* rck */ NOT_BEGIN | PREFIX }, |
| {/* sa */ ANY_COMBINATION, |
| /* sb */ NOT_BEGIN | BREAK | NOT_END, |
| /* sc */ NOT_END, |
| /* sd */ NOT_BEGIN | BREAK | NOT_END, |
| /* se */ ANY_COMBINATION, |
| /* sf */ NOT_BEGIN | BREAK | NOT_END, |
| /* sg */ NOT_BEGIN | BREAK | NOT_END, |
| /* sh */ NOT_BEGIN | BREAK | NOT_END, |
| /* si */ ANY_COMBINATION, |
| /* sj */ NOT_BEGIN | BREAK | NOT_END, |
| /* sk */ ANY_COMBINATION, |
| /* sl */ BEGIN | SUFFIX | NOT_END, |
| /* sm */ SUFFIX | NOT_END, |
| /* sn */ PREFIX | SUFFIX | NOT_END, |
| /* so */ ANY_COMBINATION, |
| /* sp */ ANY_COMBINATION, |
| /* sr */ NOT_BEGIN | NOT_END, |
| /* ss */ NOT_BEGIN | PREFIX, |
| /* st */ ANY_COMBINATION, |
| /* su */ ANY_COMBINATION, |
| /* sv */ NOT_BEGIN | BREAK | NOT_END, |
| /* sw */ BEGIN | SUFFIX | NOT_END, |
| /* sx */ ILLEGAL_PAIR, |
| /* sy */ ANY_COMBINATION, |
| /* sz */ NOT_BEGIN | BREAK | NOT_END, |
| /* sch */ BEGIN | SUFFIX | NOT_END, |
| /* sgh */ NOT_BEGIN | BREAK | NOT_END, |
| /* sph */ NOT_BEGIN | BREAK | NOT_END, |
| /* srh */ ILLEGAL_PAIR, |
| /* ssh */ NOT_BEGIN | BREAK | NOT_END, |
| /* sth */ NOT_BEGIN | BREAK | NOT_END, |
| /* swh */ ILLEGAL_PAIR, |
| /* squ */ SUFFIX | NOT_END, |
| /* sck */ NOT_BEGIN }, |
| {/* ta */ ANY_COMBINATION, |
| /* tb */ NOT_BEGIN | BREAK | NOT_END, |
| /* tc */ NOT_BEGIN | BREAK | NOT_END, |
| /* td */ NOT_BEGIN | BREAK | NOT_END, |
| /* te */ ANY_COMBINATION, |
| /* tf */ NOT_BEGIN | BREAK | NOT_END, |
| /* tg */ NOT_BEGIN | BREAK | NOT_END, |
| /* th */ NOT_BEGIN | BREAK | NOT_END, |
| /* ti */ ANY_COMBINATION, |
| /* tj */ NOT_BEGIN | BREAK | NOT_END, |
| /* tk */ NOT_BEGIN | BREAK | NOT_END, |
| /* tl */ NOT_BEGIN | BREAK | NOT_END, |
| /* tm */ NOT_BEGIN | BREAK | NOT_END, |
| /* tn */ NOT_BEGIN | BREAK | NOT_END, |
| /* to */ ANY_COMBINATION, |
| /* tp */ NOT_BEGIN | BREAK | NOT_END, |
| /* tr */ NOT_END, |
| /* ts */ NOT_BEGIN | END, |
| /* tt */ NOT_BEGIN | PREFIX, |
| /* tu */ ANY_COMBINATION, |
| /* tv */ NOT_BEGIN | BREAK | NOT_END, |
| /* tw */ BEGIN | SUFFIX | NOT_END, |
| /* tx */ ILLEGAL_PAIR, |
| /* ty */ ANY_COMBINATION, |
| /* tz */ NOT_BEGIN | BREAK | NOT_END, |
| /* tch */ NOT_BEGIN, |
| /* tgh */ NOT_BEGIN | BREAK | NOT_END, |
| /* tph */ NOT_BEGIN | END, |
| /* trh */ ILLEGAL_PAIR, |
| /* tsh */ NOT_BEGIN | END, |
| /* tth */ NOT_BEGIN | BREAK | NOT_END, |
| /* twh */ ILLEGAL_PAIR, |
| /* tqu */ NOT_BEGIN | BREAK | NOT_END, |
| /* tck */ ILLEGAL_PAIR }, |
| {/* ua */ NOT_BEGIN | BREAK | NOT_END, |
| /* ub */ ANY_COMBINATION, |
| /* uc */ ANY_COMBINATION, |
| /* ud */ ANY_COMBINATION, |
| /* ue */ NOT_BEGIN, |
| /* uf */ ANY_COMBINATION, |
| /* ug */ ANY_COMBINATION, |
| /* uh */ NOT_BEGIN | BREAK | NOT_END, |
| /* ui */ NOT_BEGIN | BREAK | NOT_END, |
| /* uj */ ANY_COMBINATION, |
| /* uk */ ANY_COMBINATION, |
| /* ul */ ANY_COMBINATION, |
| /* um */ ANY_COMBINATION, |
| /* un */ ANY_COMBINATION, |
| /* uo */ NOT_BEGIN | BREAK, |
| /* up */ ANY_COMBINATION, |
| /* ur */ ANY_COMBINATION, |
| /* us */ ANY_COMBINATION, |
| /* ut */ ANY_COMBINATION, |
| /* uu */ ILLEGAL_PAIR, |
| /* uv */ ANY_COMBINATION, |
| /* uw */ NOT_BEGIN | BREAK | NOT_END, |
| /* ux */ ANY_COMBINATION, |
| /* uy */ NOT_BEGIN | BREAK | NOT_END, |
| /* uz */ ANY_COMBINATION, |
| /* uch */ ANY_COMBINATION, |
| /* ugh */ NOT_BEGIN | PREFIX, |
| /* uph */ ANY_COMBINATION, |
| /* urh */ ILLEGAL_PAIR, |
| /* ush */ ANY_COMBINATION, |
| /* uth */ ANY_COMBINATION, |
| /* uwh */ ILLEGAL_PAIR, |
| /* uqu */ BREAK | NOT_END, |
| /* uck */ ANY_COMBINATION }, |
| {/* va */ ANY_COMBINATION, |
| /* vb */ NOT_BEGIN | BREAK | NOT_END, |
| /* vc */ NOT_BEGIN | BREAK | NOT_END, |
| /* vd */ NOT_BEGIN | BREAK | NOT_END, |
| /* ve */ ANY_COMBINATION, |
| /* vf */ NOT_BEGIN | BREAK | NOT_END, |
| /* vg */ NOT_BEGIN | BREAK | NOT_END, |
| /* vh */ NOT_BEGIN | BREAK | NOT_END, |
| /* vi */ ANY_COMBINATION, |
| /* vj */ NOT_BEGIN | BREAK | NOT_END, |
| /* vk */ NOT_BEGIN | BREAK | NOT_END, |
| /* vl */ NOT_BEGIN | BREAK | NOT_END, |
| /* vm */ NOT_BEGIN | BREAK | NOT_END, |
| /* vn */ NOT_BEGIN | BREAK | NOT_END, |
| /* vo */ ANY_COMBINATION, |
| /* vp */ NOT_BEGIN | BREAK | NOT_END, |
| /* vr */ NOT_BEGIN | BREAK | NOT_END, |
| /* vs */ NOT_BEGIN | BREAK | NOT_END, |
| /* vt */ NOT_BEGIN | BREAK | NOT_END, |
| /* vu */ ANY_COMBINATION, |
| /* vv */ NOT_BEGIN | BREAK | NOT_END, |
| /* vw */ NOT_BEGIN | BREAK | NOT_END, |
| /* vx */ ILLEGAL_PAIR, |
| /* vy */ NOT_BEGIN, |
| /* vz */ NOT_BEGIN | BREAK | NOT_END, |
| /* vch */ NOT_BEGIN | BREAK | NOT_END, |
| /* vgh */ NOT_BEGIN | BREAK | NOT_END, |
| /* vph */ NOT_BEGIN | BREAK | NOT_END, |
| /* vrh */ ILLEGAL_PAIR, |
| /* vsh */ NOT_BEGIN | BREAK | NOT_END, |
| /* vth */ NOT_BEGIN | BREAK | NOT_END, |
| /* vwh */ ILLEGAL_PAIR, |
| /* vqu */ NOT_BEGIN | BREAK | NOT_END, |
| /* vck */ ILLEGAL_PAIR }, |
| {/* wa */ ANY_COMBINATION, |
| /* wb */ NOT_BEGIN | PREFIX, |
| /* wc */ NOT_BEGIN | BREAK | NOT_END, |
| /* wd */ NOT_BEGIN | PREFIX | END, |
| /* we */ ANY_COMBINATION, |
| /* wf */ NOT_BEGIN | PREFIX, |
| /* wg */ NOT_BEGIN | PREFIX | END, |
| /* wh */ NOT_BEGIN | BREAK | NOT_END, |
| /* wi */ ANY_COMBINATION, |
| /* wj */ NOT_BEGIN | BREAK | NOT_END, |
| /* wk */ NOT_BEGIN | PREFIX, |
| /* wl */ NOT_BEGIN | PREFIX | SUFFIX, |
| /* wm */ NOT_BEGIN | PREFIX, |
| /* wn */ NOT_BEGIN | PREFIX, |
| /* wo */ ANY_COMBINATION, |
| /* wp */ NOT_BEGIN | PREFIX, |
| /* wr */ BEGIN | SUFFIX | NOT_END, |
| /* ws */ NOT_BEGIN | PREFIX, |
| /* wt */ NOT_BEGIN | PREFIX, |
| /* wu */ ANY_COMBINATION, |
| /* wv */ NOT_BEGIN | PREFIX, |
| /* ww */ NOT_BEGIN | BREAK | NOT_END, |
| /* wx */ NOT_BEGIN | PREFIX, |
| /* wy */ ANY_COMBINATION, |
| /* wz */ NOT_BEGIN | PREFIX, |
| /* wch */ NOT_BEGIN, |
| /* wgh */ NOT_BEGIN | BREAK | NOT_END, |
| /* wph */ NOT_BEGIN, |
| /* wrh */ ILLEGAL_PAIR, |
| /* wsh */ NOT_BEGIN, |
| /* wth */ NOT_BEGIN, |
| /* wwh */ ILLEGAL_PAIR, |
| /* wqu */ NOT_BEGIN | BREAK | NOT_END, |
| /* wck */ NOT_BEGIN }, |
| {/* xa */ NOT_BEGIN, |
| /* xb */ NOT_BEGIN | BREAK | NOT_END, |
| /* xc */ NOT_BEGIN | BREAK | NOT_END, |
| /* xd */ NOT_BEGIN | BREAK | NOT_END, |
| /* xe */ NOT_BEGIN, |
| /* xf */ NOT_BEGIN | BREAK | NOT_END, |
| /* xg */ NOT_BEGIN | BREAK | NOT_END, |
| /* xh */ NOT_BEGIN | BREAK | NOT_END, |
| /* xi */ NOT_BEGIN, |
| /* xj */ NOT_BEGIN | BREAK | NOT_END, |
| /* xk */ NOT_BEGIN | BREAK | NOT_END, |
| /* xl */ NOT_BEGIN | BREAK | NOT_END, |
| /* xm */ NOT_BEGIN | BREAK | NOT_END, |
| /* xn */ NOT_BEGIN | BREAK | NOT_END, |
| /* xo */ NOT_BEGIN, |
| /* xp */ NOT_BEGIN | BREAK | NOT_END, |
| /* xr */ NOT_BEGIN | BREAK | NOT_END, |
| /* xs */ NOT_BEGIN | BREAK | NOT_END, |
| /* xt */ NOT_BEGIN | BREAK | NOT_END, |
| /* xu */ NOT_BEGIN, |
| /* xv */ NOT_BEGIN | BREAK | NOT_END, |
| /* xw */ NOT_BEGIN | BREAK | NOT_END, |
| /* xx */ ILLEGAL_PAIR, |
| /* xy */ NOT_BEGIN, |
| /* xz */ NOT_BEGIN | BREAK | NOT_END, |
| /* xch */ NOT_BEGIN | BREAK | NOT_END, |
| /* xgh */ NOT_BEGIN | BREAK | NOT_END, |
| /* xph */ NOT_BEGIN | BREAK | NOT_END, |
| /* xrh */ ILLEGAL_PAIR, |
| /* xsh */ NOT_BEGIN | BREAK | NOT_END, |
| /* xth */ NOT_BEGIN | BREAK | NOT_END, |
| /* xwh */ ILLEGAL_PAIR, |
| /* xqu */ NOT_BEGIN | BREAK | NOT_END, |
| /* xck */ ILLEGAL_PAIR }, |
| {/* ya */ ANY_COMBINATION, |
| /* yb */ NOT_BEGIN, |
| /* yc */ NOT_BEGIN | NOT_END, |
| /* yd */ NOT_BEGIN, |
| /* ye */ ANY_COMBINATION, |
| /* yf */ NOT_BEGIN | NOT_END, |
| /* yg */ NOT_BEGIN, |
| /* yh */ NOT_BEGIN | BREAK | NOT_END, |
| /* yi */ BEGIN | NOT_END, |
| /* yj */ NOT_BEGIN | NOT_END, |
| /* yk */ NOT_BEGIN, |
| /* yl */ NOT_BEGIN | NOT_END, |
| /* ym */ NOT_BEGIN, |
| /* yn */ NOT_BEGIN, |
| /* yo */ ANY_COMBINATION, |
| /* yp */ NOT_BEGIN, |
| /* yr */ NOT_BEGIN | BREAK | NOT_END, |
| /* ys */ NOT_BEGIN, |
| /* yt */ NOT_BEGIN, |
| /* yu */ ANY_COMBINATION, |
| /* yv */ NOT_BEGIN | NOT_END, |
| /* yw */ NOT_BEGIN | BREAK | NOT_END, |
| /* yx */ NOT_BEGIN, |
| /* yy */ ILLEGAL_PAIR, |
| /* yz */ NOT_BEGIN, |
| /* ych */ NOT_BEGIN | BREAK | NOT_END, |
| /* ygh */ NOT_BEGIN | BREAK | NOT_END, |
| /* yph */ NOT_BEGIN | BREAK | NOT_END, |
| /* yrh */ ILLEGAL_PAIR, |
| /* ysh */ NOT_BEGIN | BREAK | NOT_END, |
| /* yth */ NOT_BEGIN | BREAK | NOT_END, |
| /* ywh */ ILLEGAL_PAIR, |
| /* yqu */ NOT_BEGIN | BREAK | NOT_END, |
| /* yck */ ILLEGAL_PAIR }, |
| {/* za */ ANY_COMBINATION, |
| /* zb */ NOT_BEGIN | BREAK | NOT_END, |
| /* zc */ NOT_BEGIN | BREAK | NOT_END, |
| /* zd */ NOT_BEGIN | BREAK | NOT_END, |
| /* ze */ ANY_COMBINATION, |
| /* zf */ NOT_BEGIN | BREAK | NOT_END, |
| /* zg */ NOT_BEGIN | BREAK | NOT_END, |
| /* zh */ NOT_BEGIN | BREAK | NOT_END, |
| /* zi */ ANY_COMBINATION, |
| /* zj */ NOT_BEGIN | BREAK | NOT_END, |
| /* zk */ NOT_BEGIN | BREAK | NOT_END, |
| /* zl */ NOT_BEGIN | BREAK | NOT_END, |
| /* zm */ NOT_BEGIN | BREAK | NOT_END, |
| /* zn */ NOT_BEGIN | BREAK | NOT_END, |
| /* zo */ ANY_COMBINATION, |
| /* zp */ NOT_BEGIN | BREAK | NOT_END, |
| /* zr */ NOT_BEGIN | NOT_END, |
| /* zs */ NOT_BEGIN | BREAK | NOT_END, |
| /* zt */ NOT_BEGIN, |
| /* zu */ ANY_COMBINATION, |
| /* zv */ NOT_BEGIN | BREAK | NOT_END, |
| /* zw */ SUFFIX | NOT_END, |
| /* zx */ ILLEGAL_PAIR, |
| /* zy */ ANY_COMBINATION, |
| /* zz */ NOT_BEGIN, |
| /* zch */ NOT_BEGIN | BREAK | NOT_END, |
| /* zgh */ NOT_BEGIN | BREAK | NOT_END, |
| /* zph */ NOT_BEGIN | BREAK | NOT_END, |
| /* zrh */ ILLEGAL_PAIR, |
| /* zsh */ NOT_BEGIN | BREAK | NOT_END, |
| /* zth */ NOT_BEGIN | BREAK | NOT_END, |
| /* zwh */ ILLEGAL_PAIR, |
| /* zqu */ NOT_BEGIN | BREAK | NOT_END, |
| /* zck */ ILLEGAL_PAIR }, |
| {/* cha */ ANY_COMBINATION, |
| /* chb */ NOT_BEGIN | BREAK | NOT_END, |
| /* chc */ NOT_BEGIN | BREAK | NOT_END, |
| /* chd */ NOT_BEGIN | BREAK | NOT_END, |
| /* che */ ANY_COMBINATION, |
| /* chf */ NOT_BEGIN | BREAK | NOT_END, |
| /* chg */ NOT_BEGIN | BREAK | NOT_END, |
| /* chh */ NOT_BEGIN | BREAK | NOT_END, |
| /* chi */ ANY_COMBINATION, |
| /* chj */ NOT_BEGIN | BREAK | NOT_END, |
| /* chk */ NOT_BEGIN | BREAK | NOT_END, |
| /* chl */ NOT_BEGIN | BREAK | NOT_END, |
| /* chm */ NOT_BEGIN | BREAK | NOT_END, |
| /* chn */ NOT_BEGIN | BREAK | NOT_END, |
| /* cho */ ANY_COMBINATION, |
| /* chp */ NOT_BEGIN | BREAK | NOT_END, |
| /* chr */ NOT_END, |
| /* chs */ NOT_BEGIN | BREAK | NOT_END, |
| /* cht */ NOT_BEGIN | BREAK | NOT_END, |
| /* chu */ ANY_COMBINATION, |
| /* chv */ NOT_BEGIN | BREAK | NOT_END, |
| /* chw */ NOT_BEGIN | NOT_END, |
| /* chx */ ILLEGAL_PAIR, |
| /* chy */ ANY_COMBINATION, |
| /* chz */ NOT_BEGIN | BREAK | NOT_END, |
| /* chch */ ILLEGAL_PAIR, |
| /* chgh */ NOT_BEGIN | BREAK | NOT_END, |
| /* chph */ NOT_BEGIN | BREAK | NOT_END, |
| /* chrh */ ILLEGAL_PAIR, |
| /* chsh */ NOT_BEGIN | BREAK | NOT_END, |
| /* chth */ NOT_BEGIN | BREAK | NOT_END, |
| /* chwh */ ILLEGAL_PAIR, |
| /* chqu */ NOT_BEGIN | BREAK | NOT_END, |
| /* chck */ ILLEGAL_PAIR }, |
| {/* gha */ ANY_COMBINATION, |
| /* ghb */ NOT_BEGIN | BREAK | PREFIX | NOT_END, |
| /* ghc */ NOT_BEGIN | BREAK | PREFIX | NOT_END, |
| /* ghd */ NOT_BEGIN | BREAK | PREFIX | NOT_END, |
| /* ghe */ ANY_COMBINATION, |
| /* ghf */ NOT_BEGIN | BREAK | PREFIX | NOT_END, |
| /* ghg */ NOT_BEGIN | BREAK | PREFIX | NOT_END, |
| /* ghh */ NOT_BEGIN | BREAK | PREFIX | NOT_END, |
| /* ghi */ BEGIN | NOT_END, |
| /* ghj */ NOT_BEGIN | BREAK | PREFIX | NOT_END, |
| /* ghk */ NOT_BEGIN | BREAK | PREFIX | NOT_END, |
| /* ghl */ NOT_BEGIN | BREAK | PREFIX | NOT_END, |
| /* ghm */ NOT_BEGIN | BREAK | PREFIX | NOT_END, |
| /* ghn */ NOT_BEGIN | BREAK | PREFIX | NOT_END, |
| /* gho */ BEGIN | NOT_END, |
| /* ghp */ NOT_BEGIN | BREAK | NOT_END, |
| /* ghr */ NOT_BEGIN | BREAK | PREFIX | NOT_END, |
| /* ghs */ NOT_BEGIN | PREFIX, |
| /* ght */ NOT_BEGIN | PREFIX, |
| /* ghu */ NOT_BEGIN | BREAK | PREFIX | NOT_END, |
| /* ghv */ NOT_BEGIN | BREAK | PREFIX | NOT_END, |
| /* ghw */ NOT_BEGIN | BREAK | PREFIX | NOT_END, |
| /* ghx */ ILLEGAL_PAIR, |
| /* ghy */ NOT_BEGIN | BREAK | PREFIX | NOT_END, |
| /* ghz */ NOT_BEGIN | BREAK | PREFIX | NOT_END, |
| /* ghch */ NOT_BEGIN | BREAK | PREFIX | NOT_END, |
| /* ghgh */ ILLEGAL_PAIR, |
| /* ghph */ NOT_BEGIN | BREAK | PREFIX | NOT_END, |
| /* ghrh */ ILLEGAL_PAIR, |
| /* ghsh */ NOT_BEGIN | BREAK | PREFIX | NOT_END, |
| /* ghth */ NOT_BEGIN | BREAK | PREFIX | NOT_END, |
| /* ghwh */ ILLEGAL_PAIR, |
| /* ghqu */ NOT_BEGIN | BREAK | PREFIX | NOT_END, |
| /* ghck */ ILLEGAL_PAIR }, |
| {/* pha */ ANY_COMBINATION, |
| /* phb */ NOT_BEGIN | BREAK | NOT_END, |
| /* phc */ NOT_BEGIN | BREAK | NOT_END, |
| /* phd */ NOT_BEGIN | BREAK | NOT_END, |
| /* phe */ ANY_COMBINATION, |
| /* phf */ NOT_BEGIN | BREAK | NOT_END, |
| /* phg */ NOT_BEGIN | BREAK | NOT_END, |
| /* phh */ NOT_BEGIN | BREAK | NOT_END, |
| /* phi */ ANY_COMBINATION, |
| /* phj */ NOT_BEGIN | BREAK | NOT_END, |
| /* phk */ NOT_BEGIN | BREAK | NOT_END, |
| /* phl */ BEGIN | SUFFIX | NOT_END, |
| /* phm */ NOT_BEGIN | BREAK | NOT_END, |
| /* phn */ NOT_BEGIN | BREAK | NOT_END, |
| /* pho */ ANY_COMBINATION, |
| /* php */ NOT_BEGIN | BREAK | NOT_END, |
| /* phr */ NOT_END, |
| /* phs */ NOT_BEGIN, |
| /* pht */ NOT_BEGIN, |
| /* phu */ ANY_COMBINATION, |
| /* phv */ NOT_BEGIN | NOT_END, |
| /* phw */ NOT_BEGIN | NOT_END, |
| /* phx */ ILLEGAL_PAIR, |
| /* phy */ NOT_BEGIN, |
| /* phz */ NOT_BEGIN | BREAK | NOT_END, |
| /* phch */ NOT_BEGIN | BREAK | NOT_END, |
| /* phgh */ NOT_BEGIN | BREAK | NOT_END, |
| /* phph */ ILLEGAL_PAIR, |
| /* phrh */ ILLEGAL_PAIR, |
| /* phsh */ NOT_BEGIN | BREAK | NOT_END, |
| /* phth */ NOT_BEGIN | BREAK | NOT_END, |
| /* phwh */ ILLEGAL_PAIR, |
| /* phqu */ NOT_BEGIN | BREAK | NOT_END, |
| /* phck */ ILLEGAL_PAIR }, |
| {/* rha */ BEGIN | NOT_END, |
| /* rhb */ ILLEGAL_PAIR, |
| /* rhc */ ILLEGAL_PAIR, |
| /* rhd */ ILLEGAL_PAIR, |
| /* rhe */ BEGIN | NOT_END, |
| /* rhf */ ILLEGAL_PAIR, |
| /* rhg */ ILLEGAL_PAIR, |
| /* rhh */ ILLEGAL_PAIR, |
| /* rhi */ BEGIN | NOT_END, |
| /* rhj */ ILLEGAL_PAIR, |
| /* rhk */ ILLEGAL_PAIR, |
| /* rhl */ ILLEGAL_PAIR, |
| /* rhm */ ILLEGAL_PAIR, |
| /* rhn */ ILLEGAL_PAIR, |
| /* rho */ BEGIN | NOT_END, |
| /* rhp */ ILLEGAL_PAIR, |
| /* rhr */ ILLEGAL_PAIR, |
| /* rhs */ ILLEGAL_PAIR, |
| /* rht */ ILLEGAL_PAIR, |
| /* rhu */ BEGIN | NOT_END, |
| /* rhv */ ILLEGAL_PAIR, |
| /* rhw */ ILLEGAL_PAIR, |
| /* rhx */ ILLEGAL_PAIR, |
| /* rhy */ BEGIN | NOT_END, |
| /* rhz */ ILLEGAL_PAIR, |
| /* rhch */ ILLEGAL_PAIR, |
| /* rhgh */ ILLEGAL_PAIR, |
| /* rhph */ ILLEGAL_PAIR, |
| /* rhrh */ ILLEGAL_PAIR, |
| /* rhsh */ ILLEGAL_PAIR, |
| /* rhth */ ILLEGAL_PAIR, |
| /* rhwh */ ILLEGAL_PAIR, |
| /* rhqu */ ILLEGAL_PAIR, |
| /* rhck */ ILLEGAL_PAIR }, |
| {/* sha */ ANY_COMBINATION, |
| /* shb */ NOT_BEGIN | BREAK | NOT_END, |
| /* shc */ NOT_BEGIN | BREAK | NOT_END, |
| /* shd */ NOT_BEGIN | BREAK | NOT_END, |
| /* she */ ANY_COMBINATION, |
| /* shf */ NOT_BEGIN | BREAK | NOT_END, |
| /* shg */ NOT_BEGIN | BREAK | NOT_END, |
| /* shh */ ILLEGAL_PAIR, |
| /* shi */ ANY_COMBINATION, |
| /* shj */ NOT_BEGIN | BREAK | NOT_END, |
| /* shk */ NOT_BEGIN, |
| /* shl */ BEGIN | SUFFIX | NOT_END, |
| /* shm */ BEGIN | SUFFIX | NOT_END, |
| /* shn */ BEGIN | SUFFIX | NOT_END, |
| /* sho */ ANY_COMBINATION, |
| /* shp */ NOT_BEGIN, |
| /* shr */ BEGIN | SUFFIX | NOT_END, |
| /* shs */ NOT_BEGIN | BREAK | NOT_END, |
| /* sht */ SUFFIX, |
| /* shu */ ANY_COMBINATION, |
| /* shv */ NOT_BEGIN | BREAK | NOT_END, |
| /* shw */ SUFFIX | NOT_END, |
| /* shx */ ILLEGAL_PAIR, |
| /* shy */ ANY_COMBINATION, |
| /* shz */ NOT_BEGIN | BREAK | NOT_END, |
| /* shch */ NOT_BEGIN | BREAK | NOT_END, |
| /* shgh */ NOT_BEGIN | BREAK | NOT_END, |
| /* shph */ NOT_BEGIN | BREAK | NOT_END, |
| /* shrh */ ILLEGAL_PAIR, |
| /* shsh */ ILLEGAL_PAIR, |
| /* shth */ NOT_BEGIN | BREAK | NOT_END, |
| /* shwh */ ILLEGAL_PAIR, |
| /* shqu */ NOT_BEGIN | BREAK | NOT_END, |
| /* shck */ ILLEGAL_PAIR }, |
| {/* tha */ ANY_COMBINATION, |
| /* thb */ NOT_BEGIN | BREAK | NOT_END, |
| /* thc */ NOT_BEGIN | BREAK | NOT_END, |
| /* thd */ NOT_BEGIN | BREAK | NOT_END, |
| /* the */ ANY_COMBINATION, |
| /* thf */ NOT_BEGIN | BREAK | NOT_END, |
| /* thg */ NOT_BEGIN | BREAK | NOT_END, |
| /* thh */ NOT_BEGIN | BREAK | NOT_END, |
| /* thi */ ANY_COMBINATION, |
| /* thj */ NOT_BEGIN | BREAK | NOT_END, |
| /* thk */ NOT_BEGIN | BREAK | NOT_END, |
| /* thl */ NOT_BEGIN | BREAK | NOT_END, |
| /* thm */ NOT_BEGIN | BREAK | NOT_END, |
| /* thn */ NOT_BEGIN | BREAK | NOT_END, |
| /* tho */ ANY_COMBINATION, |
| /* thp */ NOT_BEGIN | BREAK | NOT_END, |
| /* thr */ NOT_END, |
| /* ths */ NOT_BEGIN | END, |
| /* tht */ NOT_BEGIN | BREAK | NOT_END, |
| /* thu */ ANY_COMBINATION, |
| /* thv */ NOT_BEGIN | BREAK | NOT_END, |
| /* thw */ SUFFIX | NOT_END, |
| /* thx */ ILLEGAL_PAIR, |
| /* thy */ ANY_COMBINATION, |
| /* thz */ NOT_BEGIN | BREAK | NOT_END, |
| /* thch */ NOT_BEGIN | BREAK | NOT_END, |
| /* thgh */ NOT_BEGIN | BREAK | NOT_END, |
| /* thph */ NOT_BEGIN | BREAK | NOT_END, |
| /* thrh */ ILLEGAL_PAIR, |
| /* thsh */ NOT_BEGIN | BREAK | NOT_END, |
| /* thth */ ILLEGAL_PAIR, |
| /* thwh */ ILLEGAL_PAIR, |
| /* thqu */ NOT_BEGIN | BREAK | NOT_END, |
| /* thck */ ILLEGAL_PAIR }, |
| {/* wha */ BEGIN | NOT_END, |
| /* whb */ ILLEGAL_PAIR, |
| /* whc */ ILLEGAL_PAIR, |
| /* whd */ ILLEGAL_PAIR, |
| /* whe */ BEGIN | NOT_END, |
| /* whf */ ILLEGAL_PAIR, |
| /* whg */ ILLEGAL_PAIR, |
| /* whh */ ILLEGAL_PAIR, |
| /* whi */ BEGIN | NOT_END, |
| /* whj */ ILLEGAL_PAIR, |
| /* whk */ ILLEGAL_PAIR, |
| /* whl */ ILLEGAL_PAIR, |
| /* whm */ ILLEGAL_PAIR, |
| /* whn */ ILLEGAL_PAIR, |
| /* who */ BEGIN | NOT_END, |
| /* whp */ ILLEGAL_PAIR, |
| /* whr */ ILLEGAL_PAIR, |
| /* whs */ ILLEGAL_PAIR, |
| /* wht */ ILLEGAL_PAIR, |
| /* whu */ ILLEGAL_PAIR, |
| /* whv */ ILLEGAL_PAIR, |
| /* whw */ ILLEGAL_PAIR, |
| /* whx */ ILLEGAL_PAIR, |
| /* why */ BEGIN | NOT_END, |
| /* whz */ ILLEGAL_PAIR, |
| /* whch */ ILLEGAL_PAIR, |
| /* whgh */ ILLEGAL_PAIR, |
| /* whph */ ILLEGAL_PAIR, |
| /* whrh */ ILLEGAL_PAIR, |
| /* whsh */ ILLEGAL_PAIR, |
| /* whth */ ILLEGAL_PAIR, |
| /* whwh */ ILLEGAL_PAIR, |
| /* whqu */ ILLEGAL_PAIR, |
| /* whck */ ILLEGAL_PAIR }, |
| {/* qua */ ANY_COMBINATION, |
| /* qub */ ILLEGAL_PAIR, |
| /* quc */ ILLEGAL_PAIR, |
| /* qud */ ILLEGAL_PAIR, |
| /* que */ ANY_COMBINATION, |
| /* quf */ ILLEGAL_PAIR, |
| /* qug */ ILLEGAL_PAIR, |
| /* quh */ ILLEGAL_PAIR, |
| /* qui */ ANY_COMBINATION, |
| /* quj */ ILLEGAL_PAIR, |
| /* quk */ ILLEGAL_PAIR, |
| /* qul */ ILLEGAL_PAIR, |
| /* qum */ ILLEGAL_PAIR, |
| /* qun */ ILLEGAL_PAIR, |
| /* quo */ ANY_COMBINATION, |
| /* qup */ ILLEGAL_PAIR, |
| /* qur */ ILLEGAL_PAIR, |
| /* qus */ ILLEGAL_PAIR, |
| /* qut */ ILLEGAL_PAIR, |
| /* quu */ ILLEGAL_PAIR, |
| /* quv */ ILLEGAL_PAIR, |
| /* quw */ ILLEGAL_PAIR, |
| /* qux */ ILLEGAL_PAIR, |
| /* quy */ ILLEGAL_PAIR, |
| /* quz */ ILLEGAL_PAIR, |
| /* quch */ ILLEGAL_PAIR, |
| /* qugh */ ILLEGAL_PAIR, |
| /* quph */ ILLEGAL_PAIR, |
| /* qurh */ ILLEGAL_PAIR, |
| /* qush */ ILLEGAL_PAIR, |
| /* quth */ ILLEGAL_PAIR, |
| /* quwh */ ILLEGAL_PAIR, |
| /* ququ */ ILLEGAL_PAIR, |
| /* quck */ ILLEGAL_PAIR }, |
| {/* cka */ NOT_BEGIN | BREAK | NOT_END, |
| /* ckb */ NOT_BEGIN | BREAK | NOT_END, |
| /* ckc */ NOT_BEGIN | BREAK | NOT_END, |
| /* ckd */ NOT_BEGIN | BREAK | NOT_END, |
| /* cke */ NOT_BEGIN | BREAK | NOT_END, |
| /* ckf */ NOT_BEGIN | BREAK | NOT_END, |
| /* ckg */ NOT_BEGIN | BREAK | NOT_END, |
| /* ckh */ NOT_BEGIN | BREAK | NOT_END, |
| /* cki */ NOT_BEGIN | BREAK | NOT_END, |
| /* ckj */ NOT_BEGIN | BREAK | NOT_END, |
| /* ckk */ NOT_BEGIN | BREAK | NOT_END, |
| /* ckl */ NOT_BEGIN | BREAK | NOT_END, |
| /* ckm */ NOT_BEGIN | BREAK | NOT_END, |
| /* ckn */ NOT_BEGIN | BREAK | NOT_END, |
| /* cko */ NOT_BEGIN | BREAK | NOT_END, |
| /* ckp */ NOT_BEGIN | BREAK | NOT_END, |
| /* ckr */ NOT_BEGIN | BREAK | NOT_END, |
| /* cks */ NOT_BEGIN, |
| /* ckt */ NOT_BEGIN | BREAK | NOT_END, |
| /* cku */ NOT_BEGIN | BREAK | NOT_END, |
| /* ckv */ NOT_BEGIN | BREAK | NOT_END, |
| /* ckw */ NOT_BEGIN | BREAK | NOT_END, |
| /* ckx */ ILLEGAL_PAIR, |
| /* cky */ NOT_BEGIN, |
| /* ckz */ NOT_BEGIN | BREAK | NOT_END, |
| /* ckch */ NOT_BEGIN | BREAK | NOT_END, |
| /* ckgh */ NOT_BEGIN | BREAK | NOT_END, |
| /* ckph */ NOT_BEGIN | BREAK | NOT_END, |
| /* ckrh */ ILLEGAL_PAIR, |
| /* cksh */ NOT_BEGIN | BREAK | NOT_END, |
| /* ckth */ NOT_BEGIN | BREAK | NOT_END, |
| /* ckwh */ ILLEGAL_PAIR, |
| /* ckqu */ NOT_BEGIN | BREAK | NOT_END, |
| /* ckck */ ILLEGAL_PAIR} |
| }; |
| |
| /* |
| ** gen_pron_pass will generate a Random word and place it in the |
| ** buffer word. Also, the hyphenated word will be placed into |
| ** the buffer hyphenated_word. Both word and hyphenated_word must |
| ** be pre-allocated. The words generated will have sizes between |
| ** minlen and maxlen. If restrict is TRUE, words will not be generated that |
| ** appear as login names or as entries in the on-line dictionary. |
| ** This algorithm was initially worded out by Morrie Gasser in 1975. |
| ** Any changes here are minimal so that as many word combinations |
| ** can be produced as possible (and thus keep the words Random). |
| ** The seed is used on first use of the routine. |
| ** The length of the unhyphenated word is returned, or -1 if there |
| ** were an error (length settings are wrong or dictionary checking |
| ** could not be done. |
| */ |
| int |
| gen_pron_pass (char *word, char *hyphenated_word, USHORT minlen, |
| USHORT maxlen, unsigned int pass_mode) |
| { |
| |
| int pwlen; |
| |
| /* |
| * Check for minlen>maxlen. This is an error. |
| * and a length of 0. |
| */ |
| if (minlen > maxlen || minlen > APG_MAX_PASSWORD_LENGTH || |
| maxlen > APG_MAX_PASSWORD_LENGTH) |
| return (-1); |
| /* |
| * Check for zero length words. This is technically not an error, |
| * so we take the short cut and return a null word and a length of 0. |
| */ |
| if (maxlen == 0) |
| { |
| word[0] = '\0'; |
| hyphenated_word[0] = '\0'; |
| return (0); |
| } |
| |
| /* |
| * Find password. |
| */ |
| pwlen = gen_word (word, hyphenated_word, base::RandInt(minlen, maxlen), |
| pass_mode); |
| return (pwlen); |
| } |
| |
| |
| /* |
| * This is the routine that returns a Random word -- as |
| * yet unchecked against the passwd file or the dictionary. |
| * It collects Random syllables until a predetermined |
| * word length is found. If a retry threshold is reached, |
| * another word is tried. Given that the Random number |
| * generator is uniformly distributed, eventually a word |
| * will be found if the retry limit is adequately large enough. |
| */ |
| int |
| gen_word (char *word, char *hyphenated_word, USHORT pwlen, unsigned int pass_mode) |
| { |
| USHORT word_length; |
| USHORT syllable_length; |
| char *new_syllable; |
| char *syllable_for_hyph; |
| USHORT *syllable_units; |
| USHORT word_size; |
| USHORT word_place; |
| USHORT *word_units; |
| USHORT syllable_size; |
| UINT tries; |
| int ch_flag = FALSE; |
| int dsd = 0; |
| |
| /* |
| * Keep count of retries. |
| */ |
| tries = 0; |
| |
| /* |
| * The length of the word in characters. |
| */ |
| word_length = 0; |
| |
| /* |
| * The length of the word in character units (each of which is one or |
| * two characters long. |
| */ |
| word_size = 0; |
| |
| /* |
| * Initialize the array storing the word units. Since we know the |
| * length of the word, we only need one of that length. This method is |
| * preferable to a static array, since it allows us flexibility in |
| * choosing arbitrarily long word lengths. Since a word can contain one |
| * syllable, we should make syllable_units, the array holding the |
| * analogous units for an individual syllable, the same length. No |
| * explicit rule limits the length of syllables, but digram rules and |
| * heuristics do so indirectly. |
| */ |
| if ( (word_units = (USHORT *) calloc (sizeof (USHORT), pwlen+1))==NULL || |
| (syllable_units = (USHORT *) calloc (sizeof (USHORT), pwlen+1))==NULL || |
| (new_syllable = (char *) calloc (sizeof (USHORT), pwlen+1)) ==NULL || |
| (syllable_for_hyph = (char *) calloc (sizeof(char), 20))==NULL) |
| return(-1); |
| |
| /* |
| * Find syllables until the entire word is constructed. |
| */ |
| while (word_length < pwlen) |
| { |
| /* |
| * Get the syllable and find its length. |
| */ |
| (void) gen_syllable (new_syllable, pwlen - word_length, syllable_units, &syllable_size); |
| syllable_length = (USHORT) strlen (new_syllable); |
| |
| /* |
| * Append the syllable units to the word units. |
| */ |
| for (word_place = 0; word_place <= syllable_size; word_place++) |
| word_units[word_size + word_place] = syllable_units[word_place]; |
| word_size += syllable_size + 1; |
| |
| /* |
| * If the word has been improperly formed, throw out |
| * the syllable. The checks performed here are those |
| * that must be formed on a word basis. The other |
| * tests are performed entirely within the syllable. |
| * Otherwise, append the syllable to the word and |
| * append the syllable to the hyphenated version of |
| * the word. |
| */ |
| if (improper_word (word_units, word_size) || |
| ((word_length == 0) && have_initial_y (syllable_units, syllable_size)) || |
| ((word_length + syllable_length == pwlen) && have_final_split (syllable_units, syllable_size))) |
| word_size -= syllable_size + 1; |
| else |
| { |
| if (word_length == 0) |
| { |
| /* |
| ** Modify syllable for numeric or capital symbols required |
| ** Should be done after word quality check. |
| */ |
| dsd = base::RandInt(0, 1); |
| if ( ((pass_mode & S_NB) > 0) && (syllable_length == 1) && dsd == 0) |
| { |
| numerize(new_syllable); |
| ch_flag = TRUE; |
| } |
| if ( ((pass_mode & S_SS) > 0) && (syllable_length == 1) && (dsd == 1)) |
| { |
| specialize(new_syllable); |
| ch_flag = TRUE; |
| } |
| if ( ( (pass_mode & S_CL) > 0) && (ch_flag != TRUE)) |
| capitalize(new_syllable); |
| ch_flag = FALSE; |
| /**/ |
| (void) strcpy (word, new_syllable); |
| if (syllable_length == 1) |
| { |
| symb2name(new_syllable, syllable_for_hyph); |
| (void) strcpy (hyphenated_word, syllable_for_hyph); |
| } |
| else |
| { |
| (void) strcpy (hyphenated_word, new_syllable); |
| } |
| (void)memset ( (void *)new_syllable, 0, (size_t)(pwlen * sizeof(USHORT)+1)); |
| (void)memset ( (void *)syllable_for_hyph, 0, 20); |
| } |
| else |
| { |
| /* |
| ** Modify syllable for numeric or capital symbols required |
| ** Should be done after word quality check. |
| */ |
| dsd = base::RandInt(0, 1); |
| if ( ((pass_mode & S_NB) > 0) && (syllable_length == 1) && (dsd == 0)) |
| { |
| numerize(new_syllable); |
| ch_flag = TRUE; |
| } |
| if ( ( (pass_mode & S_SS) > 0) && (syllable_length == 1) && (dsd == 1)) |
| { |
| specialize(new_syllable); |
| ch_flag = TRUE; |
| } |
| if ( ( (pass_mode & S_CL) > 0) && (ch_flag != TRUE)) |
| capitalize(new_syllable); |
| ch_flag = FALSE; |
| /**/ |
| (void) strcat (word, new_syllable); |
| (void) strcat (hyphenated_word, "-"); |
| if (syllable_length == 1) |
| { |
| symb2name(new_syllable, syllable_for_hyph); |
| (void) strcat (hyphenated_word, syllable_for_hyph); |
| } |
| else |
| { |
| (void) strcat (hyphenated_word, new_syllable); |
| } |
| (void)memset ( (void *)new_syllable, 0, (size_t)(pwlen * sizeof(USHORT)+1)); |
| (void)memset ( (void *)syllable_for_hyph, 0, 20); |
| } |
| word_length += syllable_length; |
| } |
| |
| /* |
| * Keep track of the times we have tried to get |
| * syllables. If we have exceeded the threshold, |
| * reinitialize the pwlen and word_size variables, clear |
| * out the word arrays, and start from scratch. |
| */ |
| tries++; |
| if (tries > MAX_RETRIES) |
| { |
| word_length = 0; |
| word_size = 0; |
| tries = 0; |
| (void) strcpy (word, ""); |
| (void) strcpy (hyphenated_word, ""); |
| } |
| } |
| |
| /* |
| * The units arrays and syllable storage are internal to this |
| * routine. Since the caller has no need for them, we |
| * release the space. |
| */ |
| free ((char *) new_syllable); |
| free ((char *) syllable_units); |
| free ((char *) word_units); |
| free ((char *) syllable_for_hyph); |
| |
| return ((int) word_length); |
| } |
| |
| |
| |
| /* |
| * Check that the word does not contain illegal combinations |
| * that may span syllables. Specifically, these are: |
| * 1. An illegal pair of units between syllables. |
| * 2. Three consecutive vowel units. |
| * 3. Three consecutive consonant units. |
| * The checks are made against units (1 or 2 letters), not against |
| * the individual letters, so three consecutive units can have |
| * the length of 6 at most. |
| */ |
| boolean |
| improper_word (USHORT *units, USHORT word_size) |
| { |
| USHORT unit_count; |
| boolean failure; |
| |
| failure = FALSE; |
| |
| for (unit_count = 0; !failure && (unit_count < word_size); |
| unit_count++) |
| { |
| /* |
| * Check for ILLEGAL_PAIR. This should have been caught |
| * for units within a syllable, but in some cases it |
| * would have gone unnoticed for units between syllables |
| * (e.g., when saved_unit's in gen_syllable() were not |
| * used). |
| */ |
| if ((unit_count != 0) && |
| (digram[units[unit_count - 1]][units[unit_count]] & |
| ILLEGAL_PAIR)) |
| failure = TRUE; |
| |
| /* |
| * Check for consecutive vowels or consonants. Because |
| * the initial y of a syllable is treated as a consonant |
| * rather than as a vowel, we exclude y from the first |
| * vowel in the vowel test. The only problem comes when |
| * y ends a syllable and two other vowels start the next, |
| * like fly-oint. Since such words are still |
| * pronounceable, we accept this. |
| */ |
| if (!failure && (unit_count >= 2)) |
| { |
| /* |
| * Vowel check. |
| */ |
| if ((((rules[units[unit_count - 2]].flags & VOWEL) && |
| !(rules[units[unit_count - 2]].flags & |
| ALTERNATE_VOWEL)) && |
| (rules[units[unit_count - 1]].flags & VOWEL) && |
| (rules[units[unit_count]].flags & VOWEL)) || |
| /* |
| * Consonant check. |
| */ |
| (!(rules[units[unit_count - 2]].flags & VOWEL) && |
| !(rules[units[unit_count - 1]].flags & VOWEL) && |
| !(rules[units[unit_count]].flags & VOWEL))) |
| failure = TRUE; |
| } |
| } |
| |
| return (failure); |
| } |
| |
| |
| /* |
| * Treating y as a vowel is sometimes a problem. Some words |
| * get formed that look irregular. One special group is when |
| * y starts a word and is the only vowel in the first syllable. |
| * The word ycl is one example. We discard words like these. |
| */ |
| boolean |
| have_initial_y (USHORT *units, USHORT unit_size) |
| { |
| USHORT unit_count; |
| USHORT vowel_count; |
| USHORT normal_vowel_count; |
| |
| vowel_count = 0; |
| normal_vowel_count = 0; |
| |
| for (unit_count = 0; unit_count <= unit_size; unit_count++) |
| /* |
| * Count vowels. |
| */ |
| if (rules[units[unit_count]].flags & VOWEL) |
| { |
| vowel_count++; |
| |
| /* |
| * Count the vowels that are not: 1. y, 2. at the start of |
| * the word. |
| */ |
| if (!(rules[units[unit_count]].flags & ALTERNATE_VOWEL) || |
| (unit_count != 0)) |
| normal_vowel_count++; |
| } |
| |
| return ((vowel_count <= 1) && (normal_vowel_count == 0)); |
| } |
| |
| |
| /* |
| * Besides the problem with the letter y, there is one with |
| * a silent e at the end of words, like face or nice. We |
| * allow this silent e, but we do not allow it as the only |
| * vowel at the end of the word or syllables like ble will |
| * be generated. |
| */ |
| boolean |
| have_final_split (USHORT *units, USHORT unit_size) |
| { |
| USHORT unit_count; |
| USHORT vowel_count; |
| |
| vowel_count = 0; |
| |
| /* |
| * Count all the vowels in the word. |
| */ |
| for (unit_count = 0; unit_count <= unit_size; unit_count++) |
| if (rules[units[unit_count]].flags & VOWEL) |
| vowel_count++; |
| |
| /* |
| * Return TRUE iff the only vowel was e, found at the end if the |
| * word. |
| */ |
| return ((vowel_count == 1) && |
| (rules[units[unit_size]].flags & NO_FINAL_SPLIT)); |
| } |
| |
| |
| /* |
| * Generate next unit to password, making sure that it follows |
| * these rules: |
| * 1. Each syllable must contain exactly 1 or 2 consecutive |
| * vowels, where y is considered a vowel. |
| * 2. Syllable end is determined as follows: |
| * a. Vowel is generated and previous unit is a |
| * consonant and syllable already has a vowel. In |
| * this case, new syllable is started and already |
| * contains a vowel. |
| * b. A pair determined to be a "break" pair is encountered. |
| * In this case new syllable is started with second unit |
| * of this pair. |
| * c. End of password is encountered. |
| * d. "begin" pair is encountered legally. New syllable is |
| * started with this pair. |
| * e. "end" pair is legally encountered. New syllable has |
| * nothing yet. |
| * 3. Try generating another unit if: |
| * a. third consecutive vowel and not y. |
| * b. "break" pair generated but no vowel yet in current |
| * or previous 2 units are "not_end". |
| * c. "begin" pair generated but no vowel in syllable |
| * preceding begin pair, or both previous 2 pairs are |
| * designated "not_end". |
| * d. "end" pair generated but no vowel in current syllable |
| * or in "end" pair. |
| * e. "not_begin" pair generated but new syllable must |
| * begin (because previous syllable ended as defined in |
| * 2 above). |
| * f. vowel is generated and 2a is satisfied, but no syllable |
| * break is possible in previous 3 pairs. |
| * g. Second and third units of syllable must begin, and |
| * first unit is "alternate_vowel". |
| */ |
| char * |
| gen_syllable (char *syllable, USHORT pwlen, USHORT *units_in_syllable, |
| USHORT *syllable_length) |
| { |
| USHORT unit = 0; |
| SHORT current_unit = 0; |
| USHORT vowel_count = 0; |
| boolean rule_broken; |
| boolean want_vowel; |
| boolean want_another_unit; |
| UINT tries = 0; |
| USHORT last_unit = 0; |
| SHORT length_left = 0; |
| USHORT hold_saved_unit = 0; |
| static USHORT saved_unit; |
| static USHORT saved_pair[2]; |
| |
| /* |
| * This is needed if the saved_unit is tries and the syllable then |
| * discarded because of the retry limit. Since the saved_unit is OK and |
| * fits in nicely with the preceding syllable, we will always use it. |
| */ |
| hold_saved_unit = saved_unit; |
| |
| /* |
| * Loop until valid syllable is found. |
| */ |
| do |
| { |
| /* |
| * Try for a new syllable. Initialize all pertinent |
| * syllable variables. |
| */ |
| tries = 0; |
| saved_unit = hold_saved_unit; |
| (void) strcpy (syllable, ""); |
| vowel_count = 0; |
| current_unit = 0; |
| length_left = (short int) pwlen; |
| want_another_unit = TRUE; |
| |
| /* |
| * This loop finds all the units for the syllable. |
| */ |
| do |
| { |
| want_vowel = FALSE; |
| |
| /* |
| * This loop continues until a valid unit is found for the |
| * current position within the syllable. |
| */ |
| do |
| { |
| /* |
| * If there are saved_unit's from the previous |
| * syllable, use them up first. |
| */ |
| if (saved_unit != 0) |
| { |
| /* |
| * If there were two saved units, the first is |
| * guaranteed (by checks performed in the previous |
| * syllable) to be valid. We ignore the checks |
| * and place it in this syllable manually. |
| */ |
| if (saved_unit == 2) |
| { |
| units_in_syllable[0] = saved_pair[1]; |
| if (rules[saved_pair[1]].flags & VOWEL) |
| vowel_count++; |
| current_unit++; |
| (void) strcpy (syllable, rules[saved_pair[1]].unit_code); |
| length_left -= (short) strlen (syllable); |
| } |
| |
| /* |
| * The unit becomes the last unit checked in the |
| * previous syllable. |
| */ |
| unit = saved_pair[0]; |
| |
| /* |
| * The saved units have been used. Do not try to |
| * reuse them in this syllable (unless this particular |
| * syllable is rejected at which point we start to rebuild |
| * it with these same saved units. |
| */ |
| saved_unit = 0; |
| } |
| else |
| /* |
| * If we don't have to scoff the saved units, |
| * we generate a Random one. If we know it has |
| * to be a vowel, we get one rather than looping |
| * through until one shows up. |
| */ |
| if (want_vowel) |
| unit = random_unit (VOWEL); |
| else |
| unit = random_unit (NO_SPECIAL_RULE); |
| length_left -= (short int) strlen (rules[unit].unit_code); |
| |
| /* |
| * Prevent having a word longer than expected. |
| */ |
| if (length_left < 0) |
| rule_broken = TRUE; |
| else |
| rule_broken = FALSE; |
| |
| /* |
| * First unit of syllable. This is special because the |
| * digram tests require 2 units and we don't have that yet. |
| * Nevertheless, we can perform some checks. |
| */ |
| if (current_unit == 0) |
| { |
| /* |
| * If the shouldn't begin a syllable, don't |
| * use it. |
| */ |
| if (rules[unit].flags & NOT_BEGIN_SYLLABLE) |
| rule_broken = TRUE; |
| else |
| /* |
| * If this is the last unit of a word, |
| * we have a one unit syllable. Since each |
| * syllable must have a vowel, we make sure |
| * the unit is a vowel. Otherwise, we |
| * discard it. |
| */ |
| if (length_left == 0) |
| { |
| if (rules[unit].flags & VOWEL) |
| want_another_unit = FALSE; |
| else |
| rule_broken = TRUE; |
| } |
| } |
| else |
| { |
| /* |
| * There are some digram tests that are |
| * universally true. We test them out. |
| */ |
| |
| /* |
| * Reject ILLEGAL_PAIRS of units. |
| */ |
| if ((ALLOWED (ILLEGAL_PAIR)) || |
| |
| /* |
| * Reject units that will be split between syllables |
| * when the syllable has no vowels in it. |
| */ |
| (ALLOWED (BREAK) && (vowel_count == 0)) || |
| |
| /* |
| * Reject a unit that will end a syllable when no |
| * previous unit was a vowel and neither is this one. |
| */ |
| (ALLOWED (END) && (vowel_count == 0) && |
| !(rules[unit].flags & VOWEL))) |
| rule_broken = TRUE; |
| |
| if (current_unit == 1) |
| { |
| /* |
| * Reject the unit if we are at te starting digram of |
| * a syllable and it does not fit. |
| */ |
| if (ALLOWED (NOT_BEGIN)) |
| rule_broken = TRUE; |
| } |
| else |
| { |
| /* |
| * We are not at the start of a syllable. |
| * Save the previous unit for later tests. |
| */ |
| last_unit = units_in_syllable[current_unit - 1]; |
| |
| /* |
| * Do not allow syllables where the first letter is y |
| * and the next pair can begin a syllable. This may |
| * lead to splits where y is left alone in a syllable. |
| * Also, the combination does not sound to good even |
| * if not split. |
| */ |
| if (((current_unit == 2) && |
| (ALLOWED (BEGIN)) && |
| (rules[units_in_syllable[0]].flags & |
| ALTERNATE_VOWEL)) || |
| |
| /* |
| * If this is the last unit of a word, we should |
| * reject any digram that cannot end a syllable. |
| */ |
| (ALLOWED (NOT_END) && |
| (length_left == 0)) || |
| |
| /* |
| * Reject the unit if the digram it forms wants |
| * to break the syllable, but the resulting |
| * digram that would end the syllable is not |
| * allowed to end a syllable. |
| */ |
| (ALLOWED (BREAK) && |
| (digram[units_in_syllable |
| [current_unit - 2]] |
| [last_unit] & |
| NOT_END)) || |
| |
| /* |
| * Reject the unit if the digram it forms |
| * expects a vowel preceding it and there is |
| * none. |
| */ |
| (ALLOWED (PREFIX) && |
| !(rules[units_in_syllable |
| [current_unit - 2]].flags & |
| VOWEL))) |
| rule_broken = TRUE; |
| |
| /* |
| * The following checks occur when the current unit |
| * is a vowel and we are not looking at a word ending |
| * with an e. |
| */ |
| if (!rule_broken && |
| (rules[unit].flags & VOWEL) && |
| ((length_left > 0) || |
| !(rules[last_unit].flags & |
| NO_FINAL_SPLIT))) |
| { |
| /* |
| * Don't allow 3 consecutive vowels in a |
| * syllable. Although some words formed like this |
| * are OK, like beau, most are not. |
| */ |
| if ((vowel_count > 1) && |
| (rules[last_unit].flags & VOWEL)) |
| rule_broken = TRUE; |
| else |
| /* |
| * Check for the case of |
| * vowels-consonants-vowel, which is only |
| * legal if the last vowel is an e and we are |
| * the end of the word (wich is not |
| * happening here due to a previous check. |
| */ |
| if ((vowel_count != 0) && |
| !(rules[last_unit].flags & VOWEL)) |
| { |
| /* |
| * Try to save the vowel for the next |
| * syllable, but if the syllable left here |
| * is not proper (i.e., the resulting last |
| * digram cannot legally end it), just |
| * discard it and try for another. |
| */ |
| if (digram[units_in_syllable |
| [current_unit - 2]] |
| [last_unit] & |
| NOT_END) |
| rule_broken = TRUE; |
| else |
| { |
| saved_unit = 1; |
| saved_pair[0] = unit; |
| want_another_unit = FALSE; |
| } |
| } |
| } |
| } |
| |
| /* |
| * The unit picked and the digram formed are legal. |
| * We now determine if we can end the syllable. It may, |
| * in some cases, mean the last unit(s) may be deferred to |
| * the next syllable. We also check here to see if the |
| * digram formed expects a vowel to follow. |
| */ |
| if (!rule_broken && want_another_unit) |
| { |
| /* |
| * This word ends in a silent e. |
| */ |
| /******/ if (((vowel_count != 0) && |
| (rules[unit].flags & NO_FINAL_SPLIT) && |
| (length_left == 0) && |
| !(rules[last_unit].flags & VOWEL)) || |
| |
| /* |
| * This syllable ends either because the digram |
| * is an END pair or we would otherwise exceed |
| * the length of the word. |
| */ |
| (ALLOWED (END) || (length_left == 0))) |
| { |
| want_another_unit = FALSE; |
| } |
| else |
| /* |
| * Since we have a vowel in the syllable |
| * already, if the digram calls for the end of the |
| * syllable, we can legally split it off. We also |
| * make sure that we are not at the end of the |
| * dangerous because that syllable may not have |
| * vowels, or it may not be a legal syllable end, |
| * and the retrying mechanism will loop infinitely |
| * with the same digram. |
| */ |
| if ((vowel_count != 0) && (length_left > 0)) |
| { |
| /* |
| * If we must begin a syllable, we do so if |
| * the only vowel in THIS syllable is not part |
| * of the digram we are pushing to the next |
| * syllable. |
| */ |
| if (ALLOWED (BEGIN) && |
| (current_unit > 1) && |
| !((vowel_count == 1) && |
| (rules[last_unit].flags & VOWEL))) |
| { |
| saved_unit = 2; |
| saved_pair[0] = unit; |
| saved_pair[1] = last_unit; |
| want_another_unit = FALSE; |
| } |
| else |
| if (ALLOWED (BREAK)) |
| { |
| saved_unit = 1; |
| saved_pair[0] = unit; |
| want_another_unit = FALSE; |
| } |
| } |
| else |
| if (ALLOWED (SUFFIX)) |
| { |
| want_vowel = TRUE; |
| } |
| } |
| } |
| /********/ |
| tries++; |
| |
| /* |
| * If this unit was illegal, redetermine the amount of |
| * letters left to go in the word. |
| */ |
| if (rule_broken) |
| length_left += (short int) strlen (rules[unit].unit_code); |
| } |
| while (rule_broken && (tries <= MAX_RETRIES)); |
| |
| /* |
| * The unit fit OK. |
| */ |
| if (tries <= MAX_RETRIES) |
| { |
| /* |
| * If the unit were a vowel, count it in. |
| * However, if the unit were a y and appear |
| * at the start of the syllable, treat it |
| * like a constant (so that words like year can |
| * appear and not conflict with the 3 consecutive |
| * vowel rule. |
| */ |
| if ((rules[unit].flags & VOWEL) && |
| ((current_unit > 0) || |
| !(rules[unit].flags & ALTERNATE_VOWEL))) |
| vowel_count++; |
| |
| /* |
| * If a unit or units were to be saved, we must |
| * adjust the syllable formed. Otherwise, we |
| * append the current unit to the syllable. |
| */ |
| switch (saved_unit) |
| { |
| case 0: |
| units_in_syllable[current_unit] = unit; |
| (void) strcat (syllable, rules[unit].unit_code); |
| break; |
| case 1: |
| current_unit--; |
| break; |
| case 2: |
| (void) strcpy (&syllable[strlen (syllable) - |
| strlen (rules[last_unit].unit_code)],""); |
| length_left += (short int) strlen (rules[last_unit].unit_code); |
| current_unit -= 2; |
| break; |
| } |
| } |
| else |
| /* |
| * Whoops! Too many tries. We set rule_broken so we can |
| * loop in the outer loop and try another syllable. |
| */ |
| rule_broken = TRUE; |
| |
| /* |
| * ...and the syllable length grows. |
| */ |
| *syllable_length = current_unit; |
| |
| current_unit++; |
| } |
| while ((tries <= MAX_RETRIES) && want_another_unit); |
| } |
| while (rule_broken || |
| illegal_placement (units_in_syllable, *syllable_length)); |
| |
| return (syllable); |
| } |
| |
| |
| /* |
| * This routine goes through an individual syllable and checks |
| * for illegal combinations of letters that go beyond looking |
| * at digrams. We look at things like 3 consecutive vowels or |
| * consonants, or syllables with consonants between vowels (unless |
| * one of them is the final silent e). |
| */ |
| boolean |
| illegal_placement (USHORT *units, USHORT pwlen) |
| { |
| USHORT vowel_count; |
| USHORT unit_count; |
| boolean failure; |
| |
| vowel_count = 0; |
| failure = FALSE; |
| |
| for (unit_count = 0; !failure && (unit_count <= pwlen); |
| unit_count++) |
| { |
| if (unit_count >= 1) |
| { |
| /* |
| * Don't allow vowels to be split with consonants in |
| * a single syllable. If we find such a combination |
| * (except for the silent e) we have to discard the |
| * syllable). |
| */ |
| if ((!(rules[units[unit_count - 1]].flags & VOWEL) && |
| (rules[units[unit_count]].flags & VOWEL) && |
| !((rules[units[unit_count]].flags & NO_FINAL_SPLIT) && |
| (unit_count == pwlen)) && (vowel_count != 0)) || |
| /* |
| * Perform these checks when we have at least 3 units. |
| */ |
| ((unit_count >= 2) && |
| |
| /* |
| * Disallow 3 consecutive consonants. |
| */ |
| ((!(rules[units[unit_count - 2]].flags & VOWEL) && |
| !(rules[units[unit_count - 1]].flags & |
| VOWEL) && |
| !(rules[units[unit_count]].flags & |
| VOWEL)) || |
| |
| /* |
| * Disallow 3 consecutive vowels, where the first is |
| * not a y. |
| */ |
| (((rules[units[unit_count - 2]].flags & |
| VOWEL) && |
| !((rules[units[0]].flags & |
| ALTERNATE_VOWEL) && |
| (unit_count == 2))) && |
| (rules[units[unit_count - 1]].flags & |
| VOWEL) && |
| (rules[units[unit_count]].flags & |
| VOWEL))))) |
| failure = TRUE; |
| } |
| |
| /* |
| * Count the vowels in the syllable. As mentioned somewhere |
| * above, exclude the initial y of a syllable. Instead, |
| * treat it as a consonant. |
| */ |
| if ((rules[units[unit_count]].flags & VOWEL) && |
| !((rules[units[0]].flags & ALTERNATE_VOWEL) && |
| (unit_count == 0) && (pwlen != 0))) |
| vowel_count++; |
| } |
| |
| return (failure); |
| } |
| |
| |
| |
| /* |
| * This is the standard Random unit generating routine for |
| * gen_syllable(). It does not reference the digrams, but |
| * assumes that it contains 34 units in a particular order. |
| * This routine attempts to return unit indexes with a distribution |
| * approaching that of the distribution of the 34 units in |
| * English. In order to do this, a Random number (supposedly |
| * uniformly distributed) is used to do a table lookup into an |
| * array containing unit indices. There are 211 entries in |
| * the array for the random_unit entry point. The probability |
| * of a particular unit being generated is equal to the |
| * fraction of those 211 entries that contain that unit index. |
| * For example, the letter `a' is unit number 1. Since unit |
| * index 1 appears 10 times in the array, the probability of |
| * selecting an `a' is 10/211. |
| * |
| * Changes may be made to the digram table without affect to this |
| * procedure providing the letter-to-number correspondence of |
| * the units does not change. Likewise, the distribution of the |
| * 34 units may be altered (and the array size may be changed) |
| * in this procedure without affecting the digram table or any other |
| * programs using the Random_word subroutine. |
| */ |
| static USHORT numbers[] = |
| { |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 1, 1, 1, 1, 1, 1, 1, 1, |
| 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, |
| 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, |
| 5, 5, 5, 5, 5, 5, 5, 5, |
| 6, 6, 6, 6, 6, 6, 6, 6, |
| 7, 7, 7, 7, 7, 7, |
| 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, |
| 9, 9, 9, 9, 9, 9, 9, 9, |
| 10, 10, 10, 10, 10, 10, 10, 10, |
| 11, 11, 11, 11, 11, 11, |
| 12, 12, 12, 12, 12, 12, |
| 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, |
| 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, |
| 15, 15, 15, 15, 15, 15, |
| 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, |
| 17, 17, 17, 17, 17, 17, 17, 17, |
| 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, |
| 19, 19, 19, 19, 19, 19, |
| 20, 20, 20, 20, 20, 20, 20, 20, |
| 21, 21, 21, 21, 21, 21, 21, 21, |
| 22, |
| 23, 23, 23, 23, 23, 23, 23, 23, |
| 24, |
| 25, |
| 26, |
| 27, |
| 28, |
| 29, 29, |
| 30, |
| 31, |
| 32, |
| 33 |
| }; |
| |
| |
| /* |
| * This structure has a typical English frequency of vowels. |
| * The value of an entry is the vowel position (a=0, e=4, i=8, |
| * o=14, u=19, y=23) in the rules array. The number of times |
| * the value appears is the frequency. Thus, the letter "a" |
| * is assumed to appear 2/12 = 1/6 of the time. This array |
| * may be altered if better data is obtained. The routines that |
| * use vowel_numbers will adjust to the size difference |
| automatically. |
| */ |
| static USHORT vowel_numbers[] = |
| { |
| 0, 0, 4, 4, 4, 8, 8, 14, 14, 19, 19, 23 |
| }; |
| |
| |
| /* |
| * Select a unit (a letter or a consonant group). If a vowel is |
| * expected, use the vowel_numbers array rather than looping through |
| * the numbers array until a vowel is found. |
| */ |
| USHORT |
| random_unit (USHORT type) |
| { |
| USHORT number; |
| |
| /* |
| * Sometimes, we are asked to explicitly get a vowel (i.e., if |
| * a digram pair expects one following it). This is a shortcut |
| * to do that and avoid looping with rejected consonants. |
| */ |
| if (type & VOWEL) |
| number = vowel_numbers[ |
| base::RandInt(0, (sizeof (vowel_numbers) / sizeof (USHORT))-1)]; |
| else |
| /* |
| * Get any letter according to the English distribution. |
| */ |
| number = numbers[ |
| base::RandInt(0, (sizeof (numbers) / sizeof (USHORT))-1)]; |
| return (number); |
| } |