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