1 /* 2 ** This module uses code from the NIST implementation of FIPS-181, 3 ** but the algorythm is CHANGED and I think that I CAN 4 ** copyright it. See copiright notes below. 5 */ 6 7 /* 8 ** Copyright (c) 1999, 2000, 2001, 2002, 2003 9 ** Adel I. Mirzazhanov. All rights reserved 10 ** 11 ** Redistribution and use in source and binary forms, with or without 12 ** modification, are permitted provided that the following conditions 13 ** are met: 14 ** 15 ** 1.Redistributions of source code must retain the above copyright notice, 16 ** this list of conditions and the following disclaimer. 17 ** 2.Redistributions in binary form must reproduce the above copyright 18 ** notice, this list of conditions and the following disclaimer in the 19 ** documentation and/or other materials provided with the distribution. 20 ** 3.The name of the author may not be used to endorse or promote products 21 ** derived from this software without specific prior written permission. 22 ** 23 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 24 ** OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 25 ** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 ** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 27 ** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 29 ** GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30 ** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 31 ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32) && !defined(__WIN32__) 41 #include <strings.h> 42 #endif 43 #include <time.h> 44 #include <sys/types.h> 45 #include "base/rand_util.h" 46 #include "fips181.h" 47 #include "randpass.h" 48 #include "convert.h" 49 50 struct unit 51 { 52 char unit_code[5]; 53 USHORT flags; 54 }; 55 56 static struct unit rules[] = 57 { {"a", VOWEL}, 58 {"b", NO_SPECIAL_RULE}, 59 {"c", NO_SPECIAL_RULE}, 60 {"d", NO_SPECIAL_RULE}, 61 {"e", NO_FINAL_SPLIT | VOWEL}, 62 {"f", NO_SPECIAL_RULE}, 63 {"g", NO_SPECIAL_RULE}, 64 {"h", NO_SPECIAL_RULE}, 65 {"i", VOWEL}, 66 {"j", NO_SPECIAL_RULE}, 67 {"k", NO_SPECIAL_RULE}, 68 {"l", NO_SPECIAL_RULE}, 69 {"m", NO_SPECIAL_RULE}, 70 {"n", NO_SPECIAL_RULE}, 71 {"o", VOWEL}, 72 {"p", NO_SPECIAL_RULE}, 73 {"r", NO_SPECIAL_RULE}, 74 {"s", NO_SPECIAL_RULE}, 75 {"t", NO_SPECIAL_RULE}, 76 {"u", VOWEL}, 77 {"v", NO_SPECIAL_RULE}, 78 {"w", NO_SPECIAL_RULE}, 79 {"x", NOT_BEGIN_SYLLABLE}, 80 {"y", ALTERNATE_VOWEL | VOWEL}, 81 {"z", NO_SPECIAL_RULE}, 82 {"ch", NO_SPECIAL_RULE}, 83 {"gh", NO_SPECIAL_RULE}, 84 {"ph", NO_SPECIAL_RULE}, 85 {"rh", NO_SPECIAL_RULE}, 86 {"sh", NO_SPECIAL_RULE}, 87 {"th", NO_SPECIAL_RULE}, 88 {"wh", NO_SPECIAL_RULE}, 89 {"qu", NO_SPECIAL_RULE}, 90 {"ck", NOT_BEGIN_SYLLABLE} 91 }; 92 93 static int digram[][RULE_SIZE] = 94 { 95 {/* aa */ ILLEGAL_PAIR, 96 /* ab */ ANY_COMBINATION, 97 /* ac */ ANY_COMBINATION, 98 /* ad */ ANY_COMBINATION, 99 /* ae */ ILLEGAL_PAIR, 100 /* af */ ANY_COMBINATION, 101 /* ag */ ANY_COMBINATION, 102 /* ah */ NOT_BEGIN | BREAK | NOT_END, 103 /* ai */ ANY_COMBINATION, 104 /* aj */ ANY_COMBINATION, 105 /* ak */ ANY_COMBINATION, 106 /* al */ ANY_COMBINATION, 107 /* am */ ANY_COMBINATION, 108 /* an */ ANY_COMBINATION, 109 /* ao */ ILLEGAL_PAIR, 110 /* ap */ ANY_COMBINATION, 111 /* ar */ ANY_COMBINATION, 112 /* as */ ANY_COMBINATION, 113 /* at */ ANY_COMBINATION, 114 /* au */ ANY_COMBINATION, 115 /* av */ ANY_COMBINATION, 116 /* aw */ ANY_COMBINATION, 117 /* ax */ ANY_COMBINATION, 118 /* ay */ ANY_COMBINATION, 119 /* az */ ANY_COMBINATION, 120 /* ach */ ANY_COMBINATION, 121 /* agh */ ILLEGAL_PAIR, 122 /* aph */ ANY_COMBINATION, 123 /* arh */ ILLEGAL_PAIR, 124 /* ash */ ANY_COMBINATION, 125 /* ath */ ANY_COMBINATION, 126 /* awh */ ILLEGAL_PAIR, 127 /* aqu */ BREAK | NOT_END, 128 /* ack */ ANY_COMBINATION}, 129 {/* ba */ ANY_COMBINATION, 130 /* bb */ NOT_BEGIN | BREAK | NOT_END, 131 /* bc */ NOT_BEGIN | BREAK | NOT_END, 132 /* bd */ NOT_BEGIN | BREAK | NOT_END, 133 /* be */ ANY_COMBINATION, 134 /* bf */ NOT_BEGIN | BREAK | NOT_END, 135 /* bg */ NOT_BEGIN | BREAK | NOT_END, 136 /* bh */ NOT_BEGIN | BREAK | NOT_END, 137 /* bi */ ANY_COMBINATION, 138 /* bj */ NOT_BEGIN | BREAK | NOT_END, 139 /* bk */ NOT_BEGIN | BREAK | NOT_END, 140 /* bl */ BEGIN | SUFFIX | NOT_END, 141 /* bm */ NOT_BEGIN | BREAK | NOT_END, 142 /* bn */ NOT_BEGIN | BREAK | NOT_END, 143 /* bo */ ANY_COMBINATION, 144 /* bp */ NOT_BEGIN | BREAK | NOT_END, 145 /* br */ BEGIN | END, 146 /* bs */ NOT_BEGIN, 147 /* bt */ NOT_BEGIN | BREAK | NOT_END, 148 /* bu */ ANY_COMBINATION, 149 /* bv */ NOT_BEGIN | BREAK | NOT_END, 150 /* bw */ NOT_BEGIN | BREAK | NOT_END, 151 /* bx */ ILLEGAL_PAIR, 152 /* by */ ANY_COMBINATION, 153 /* bz */ NOT_BEGIN | BREAK | NOT_END, 154 /* bch */ NOT_BEGIN | BREAK | NOT_END, 155 /* bgh */ ILLEGAL_PAIR, 156 /* bph */ NOT_BEGIN | BREAK | NOT_END, 157 /* brh */ ILLEGAL_PAIR, 158 /* bsh */ NOT_BEGIN | BREAK | NOT_END, 159 /* bth */ NOT_BEGIN | BREAK | NOT_END, 160 /* bwh */ ILLEGAL_PAIR, 161 /* bqu */ NOT_BEGIN | BREAK | NOT_END, 162 /* bck */ ILLEGAL_PAIR }, 163 {/* ca */ ANY_COMBINATION, 164 /* cb */ NOT_BEGIN | BREAK | NOT_END, 165 /* cc */ NOT_BEGIN | BREAK | NOT_END, 166 /* cd */ NOT_BEGIN | BREAK | NOT_END, 167 /* ce */ ANY_COMBINATION, 168 /* cf */ NOT_BEGIN | BREAK | NOT_END, 169 /* cg */ NOT_BEGIN | BREAK | NOT_END, 170 /* ch */ NOT_BEGIN | BREAK | NOT_END, 171 /* ci */ ANY_COMBINATION, 172 /* cj */ NOT_BEGIN | BREAK | NOT_END, 173 /* ck */ NOT_BEGIN | BREAK | NOT_END, 174 /* cl */ SUFFIX | NOT_END, 175 /* cm */ NOT_BEGIN | BREAK | NOT_END, 176 /* cn */ NOT_BEGIN | BREAK | NOT_END, 177 /* co */ ANY_COMBINATION, 178 /* cp */ NOT_BEGIN | BREAK | NOT_END, 179 /* cr */ NOT_END, 180 /* cs */ NOT_BEGIN | END, 181 /* ct */ NOT_BEGIN | PREFIX, 182 /* cu */ ANY_COMBINATION, 183 /* cv */ NOT_BEGIN | BREAK | NOT_END, 184 /* cw */ NOT_BEGIN | BREAK | NOT_END, 185 /* cx */ ILLEGAL_PAIR, 186 /* cy */ ANY_COMBINATION, 187 /* cz */ NOT_BEGIN | BREAK | NOT_END, 188 /* cch */ ILLEGAL_PAIR, 189 /* cgh */ ILLEGAL_PAIR, 190 /* cph */ NOT_BEGIN | BREAK | NOT_END, 191 /* crh */ ILLEGAL_PAIR, 192 /* csh */ NOT_BEGIN | BREAK | NOT_END, 193 /* cth */ NOT_BEGIN | BREAK | NOT_END, 194 /* cwh */ ILLEGAL_PAIR, 195 /* cqu */ NOT_BEGIN | SUFFIX | NOT_END, 196 /* cck */ ILLEGAL_PAIR}, 197 {/* da */ ANY_COMBINATION, 198 /* db */ NOT_BEGIN | BREAK | NOT_END, 199 /* dc */ NOT_BEGIN | BREAK | NOT_END, 200 /* dd */ NOT_BEGIN, 201 /* de */ ANY_COMBINATION, 202 /* df */ NOT_BEGIN | BREAK | NOT_END, 203 /* dg */ NOT_BEGIN | BREAK | NOT_END, 204 /* dh */ NOT_BEGIN | BREAK | NOT_END, 205 /* di */ ANY_COMBINATION, 206 /* dj */ NOT_BEGIN | BREAK | NOT_END, 207 /* dk */ NOT_BEGIN | BREAK | NOT_END, 208 /* dl */ NOT_BEGIN | BREAK | NOT_END, 209 /* dm */ NOT_BEGIN | BREAK | NOT_END, 210 /* dn */ NOT_BEGIN | BREAK | NOT_END, 211 /* do */ ANY_COMBINATION, 212 /* dp */ NOT_BEGIN | BREAK | NOT_END, 213 /* dr */ BEGIN | NOT_END, 214 /* ds */ NOT_BEGIN | END, 215 /* dt */ NOT_BEGIN | BREAK | NOT_END, 216 /* du */ ANY_COMBINATION, 217 /* dv */ NOT_BEGIN | BREAK | NOT_END, 218 /* dw */ NOT_BEGIN | BREAK | NOT_END, 219 /* dx */ ILLEGAL_PAIR, 220 /* dy */ ANY_COMBINATION, 221 /* dz */ NOT_BEGIN | BREAK | NOT_END, 222 /* dch */ NOT_BEGIN | BREAK | NOT_END, 223 /* dgh */ NOT_BEGIN | BREAK | NOT_END, 224 /* dph */ NOT_BEGIN | BREAK | NOT_END, 225 /* drh */ ILLEGAL_PAIR, 226 /* dsh */ NOT_BEGIN | NOT_END, 227 /* dth */ NOT_BEGIN | PREFIX, 228 /* dwh */ ILLEGAL_PAIR, 229 /* dqu */ NOT_BEGIN | BREAK | NOT_END, 230 /* dck */ ILLEGAL_PAIR }, 231 {/* ea */ ANY_COMBINATION, 232 /* eb */ ANY_COMBINATION, 233 /* ec */ ANY_COMBINATION, 234 /* ed */ ANY_COMBINATION, 235 /* ee */ ANY_COMBINATION, 236 /* ef */ ANY_COMBINATION, 237 /* eg */ ANY_COMBINATION, 238 /* eh */ NOT_BEGIN | BREAK | NOT_END, 239 /* ei */ NOT_END, 240 /* ej */ ANY_COMBINATION, 241 /* ek */ ANY_COMBINATION, 242 /* el */ ANY_COMBINATION, 243 /* em */ ANY_COMBINATION, 244 /* en */ ANY_COMBINATION, 245 /* eo */ BREAK, 246 /* ep */ ANY_COMBINATION, 247 /* er */ ANY_COMBINATION, 248 /* es */ ANY_COMBINATION, 249 /* et */ ANY_COMBINATION, 250 /* eu */ ANY_COMBINATION, 251 /* ev */ ANY_COMBINATION, 252 /* ew */ ANY_COMBINATION, 253 /* ex */ ANY_COMBINATION, 254 /* ey */ ANY_COMBINATION, 255 /* ez */ ANY_COMBINATION, 256 /* ech */ ANY_COMBINATION, 257 /* egh */ NOT_BEGIN | BREAK | NOT_END, 258 /* eph */ ANY_COMBINATION, 259 /* erh */ ILLEGAL_PAIR, 260 /* esh */ ANY_COMBINATION, 261 /* eth */ ANY_COMBINATION, 262 /* ewh */ ILLEGAL_PAIR, 263 /* equ */ BREAK | NOT_END, 264 /* eck */ ANY_COMBINATION }, 265 {/* fa */ ANY_COMBINATION, 266 /* fb */ NOT_BEGIN | BREAK | NOT_END, 267 /* fc */ NOT_BEGIN | BREAK | NOT_END, 268 /* fd */ NOT_BEGIN | BREAK | NOT_END, 269 /* fe */ ANY_COMBINATION, 270 /* ff */ NOT_BEGIN, 271 /* fg */ NOT_BEGIN | BREAK | NOT_END, 272 /* fh */ NOT_BEGIN | BREAK | NOT_END, 273 /* fi */ ANY_COMBINATION, 274 /* fj */ NOT_BEGIN | BREAK | NOT_END, 275 /* fk */ NOT_BEGIN | BREAK | NOT_END, 276 /* fl */ BEGIN | SUFFIX | NOT_END, 277 /* fm */ NOT_BEGIN | BREAK | NOT_END, 278 /* fn */ NOT_BEGIN | BREAK | NOT_END, 279 /* fo */ ANY_COMBINATION, 280 /* fp */ NOT_BEGIN | BREAK | NOT_END, 281 /* fr */ BEGIN | NOT_END, 282 /* fs */ NOT_BEGIN, 283 /* ft */ NOT_BEGIN, 284 /* fu */ ANY_COMBINATION, 285 /* fv */ NOT_BEGIN | BREAK | NOT_END, 286 /* fw */ NOT_BEGIN | BREAK | NOT_END, 287 /* fx */ ILLEGAL_PAIR, 288 /* fy */ NOT_BEGIN, 289 /* fz */ NOT_BEGIN | BREAK | NOT_END, 290 /* fch */ NOT_BEGIN | BREAK | NOT_END, 291 /* fgh */ NOT_BEGIN | BREAK | NOT_END, 292 /* fph */ NOT_BEGIN | BREAK | NOT_END, 293 /* frh */ ILLEGAL_PAIR, 294 /* fsh */ NOT_BEGIN | BREAK | NOT_END, 295 /* fth */ NOT_BEGIN | BREAK | NOT_END, 296 /* fwh */ ILLEGAL_PAIR, 297 /* fqu */ NOT_BEGIN | BREAK | NOT_END, 298 /* fck */ ILLEGAL_PAIR }, 299 {/* ga */ ANY_COMBINATION, 300 /* gb */ NOT_BEGIN | BREAK | NOT_END, 301 /* gc */ NOT_BEGIN | BREAK | NOT_END, 302 /* gd */ NOT_BEGIN | BREAK | NOT_END, 303 /* ge */ ANY_COMBINATION, 304 /* gf */ NOT_BEGIN | BREAK | NOT_END, 305 /* gg */ NOT_BEGIN, 306 /* gh */ NOT_BEGIN | BREAK | NOT_END, 307 /* gi */ ANY_COMBINATION, 308 /* gj */ NOT_BEGIN | BREAK | NOT_END, 309 /* gk */ ILLEGAL_PAIR, 310 /* gl */ BEGIN | SUFFIX | NOT_END, 311 /* gm */ NOT_BEGIN | BREAK | NOT_END, 312 /* gn */ NOT_BEGIN | BREAK | NOT_END, 313 /* go */ ANY_COMBINATION, 314 /* gp */ NOT_BEGIN | BREAK | NOT_END, 315 /* gr */ BEGIN | NOT_END, 316 /* gs */ NOT_BEGIN | END, 317 /* gt */ NOT_BEGIN | BREAK | NOT_END, 318 /* gu */ ANY_COMBINATION, 319 /* gv */ NOT_BEGIN | BREAK | NOT_END, 320 /* gw */ NOT_BEGIN | BREAK | NOT_END, 321 /* gx */ ILLEGAL_PAIR, 322 /* gy */ NOT_BEGIN, 323 /* gz */ NOT_BEGIN | BREAK | NOT_END, 324 /* gch */ NOT_BEGIN | BREAK | NOT_END, 325 /* ggh */ ILLEGAL_PAIR, 326 /* gph */ NOT_BEGIN | BREAK | NOT_END, 327 /* grh */ ILLEGAL_PAIR, 328 /* gsh */ NOT_BEGIN, 329 /* gth */ NOT_BEGIN, 330 /* gwh */ ILLEGAL_PAIR, 331 /* gqu */ NOT_BEGIN | BREAK | NOT_END, 332 /* gck */ ILLEGAL_PAIR }, 333 {/* ha */ ANY_COMBINATION, 334 /* hb */ NOT_BEGIN | BREAK | NOT_END, 335 /* hc */ NOT_BEGIN | BREAK | NOT_END, 336 /* hd */ NOT_BEGIN | BREAK | NOT_END, 337 /* he */ ANY_COMBINATION, 338 /* hf */ NOT_BEGIN | BREAK | NOT_END, 339 /* hg */ NOT_BEGIN | BREAK | NOT_END, 340 /* hh */ ILLEGAL_PAIR, 341 /* hi */ ANY_COMBINATION, 342 /* hj */ NOT_BEGIN | BREAK | NOT_END, 343 /* hk */ NOT_BEGIN | BREAK | NOT_END, 344 /* hl */ NOT_BEGIN | BREAK | NOT_END, 345 /* hm */ NOT_BEGIN | BREAK | NOT_END, 346 /* hn */ NOT_BEGIN | BREAK | NOT_END, 347 /* ho */ ANY_COMBINATION, 348 /* hp */ NOT_BEGIN | BREAK | NOT_END, 349 /* hr */ NOT_BEGIN | BREAK | NOT_END, 350 /* hs */ NOT_BEGIN | BREAK | NOT_END, 351 /* ht */ NOT_BEGIN | BREAK | NOT_END, 352 /* hu */ ANY_COMBINATION, 353 /* hv */ NOT_BEGIN | BREAK | NOT_END, 354 /* hw */ NOT_BEGIN | BREAK | NOT_END, 355 /* hx */ ILLEGAL_PAIR, 356 /* hy */ ANY_COMBINATION, 357 /* hz */ NOT_BEGIN | BREAK | NOT_END, 358 /* hch */ NOT_BEGIN | BREAK | NOT_END, 359 /* hgh */ NOT_BEGIN | BREAK | NOT_END, 360 /* hph */ NOT_BEGIN | BREAK | NOT_END, 361 /* hrh */ ILLEGAL_PAIR, 362 /* hsh */ NOT_BEGIN | BREAK | NOT_END, 363 /* hth */ NOT_BEGIN | BREAK | NOT_END, 364 /* hwh */ ILLEGAL_PAIR, 365 /* hqu */ NOT_BEGIN | BREAK | NOT_END, 366 /* hck */ ILLEGAL_PAIR }, 367 {/* ia */ ANY_COMBINATION, 368 /* ib */ ANY_COMBINATION, 369 /* ic */ ANY_COMBINATION, 370 /* id */ ANY_COMBINATION, 371 /* ie */ NOT_BEGIN, 372 /* if */ ANY_COMBINATION, 373 /* ig */ ANY_COMBINATION, 374 /* ih */ NOT_BEGIN | BREAK | NOT_END, 375 /* ii */ ILLEGAL_PAIR, 376 /* ij */ ANY_COMBINATION, 377 /* ik */ ANY_COMBINATION, 378 /* il */ ANY_COMBINATION, 379 /* im */ ANY_COMBINATION, 380 /* in */ ANY_COMBINATION, 381 /* io */ BREAK, 382 /* ip */ ANY_COMBINATION, 383 /* ir */ ANY_COMBINATION, 384 /* is */ ANY_COMBINATION, 385 /* it */ ANY_COMBINATION, 386 /* iu */ NOT_BEGIN | BREAK | NOT_END, 387 /* iv */ ANY_COMBINATION, 388 /* iw */ NOT_BEGIN | BREAK | NOT_END, 389 /* ix */ ANY_COMBINATION, 390 /* iy */ NOT_BEGIN | BREAK | NOT_END, 391 /* iz */ ANY_COMBINATION, 392 /* ich */ ANY_COMBINATION, 393 /* igh */ NOT_BEGIN, 394 /* iph */ ANY_COMBINATION, 395 /* irh */ ILLEGAL_PAIR, 396 /* ish */ ANY_COMBINATION, 397 /* ith */ ANY_COMBINATION, 398 /* iwh */ ILLEGAL_PAIR, 399 /* iqu */ BREAK | NOT_END, 400 /* ick */ ANY_COMBINATION }, 401 {/* ja */ ANY_COMBINATION, 402 /* jb */ NOT_BEGIN | BREAK | NOT_END, 403 /* jc */ NOT_BEGIN | BREAK | NOT_END, 404 /* jd */ NOT_BEGIN | BREAK | NOT_END, 405 /* je */ ANY_COMBINATION, 406 /* jf */ NOT_BEGIN | BREAK | NOT_END, 407 /* jg */ ILLEGAL_PAIR, 408 /* jh */ NOT_BEGIN | BREAK | NOT_END, 409 /* ji */ ANY_COMBINATION, 410 /* jj */ ILLEGAL_PAIR, 411 /* jk */ NOT_BEGIN | BREAK | NOT_END, 412 /* jl */ NOT_BEGIN | BREAK | NOT_END, 413 /* jm */ NOT_BEGIN | BREAK | NOT_END, 414 /* jn */ NOT_BEGIN | BREAK | NOT_END, 415 /* jo */ ANY_COMBINATION, 416 /* jp */ NOT_BEGIN | BREAK | NOT_END, 417 /* jr */ NOT_BEGIN | BREAK | NOT_END, 418 /* js */ NOT_BEGIN | BREAK | NOT_END, 419 /* jt */ NOT_BEGIN | BREAK | NOT_END, 420 /* ju */ ANY_COMBINATION, 421 /* jv */ NOT_BEGIN | BREAK | NOT_END, 422 /* jw */ NOT_BEGIN | BREAK | NOT_END, 423 /* jx */ ILLEGAL_PAIR, 424 /* jy */ NOT_BEGIN, 425 /* jz */ NOT_BEGIN | BREAK | NOT_END, 426 /* jch */ NOT_BEGIN | BREAK | NOT_END, 427 /* jgh */ NOT_BEGIN | BREAK | NOT_END, 428 /* jph */ NOT_BEGIN | BREAK | NOT_END, 429 /* jrh */ ILLEGAL_PAIR, 430 /* jsh */ NOT_BEGIN | BREAK | NOT_END, 431 /* jth */ NOT_BEGIN | BREAK | NOT_END, 432 /* jwh */ ILLEGAL_PAIR, 433 /* jqu */ NOT_BEGIN | BREAK | NOT_END, 434 /* jck */ ILLEGAL_PAIR }, 435 {/* ka */ ANY_COMBINATION, 436 /* kb */ NOT_BEGIN | BREAK | NOT_END, 437 /* kc */ NOT_BEGIN | BREAK | NOT_END, 438 /* kd */ NOT_BEGIN | BREAK | NOT_END, 439 /* ke */ ANY_COMBINATION, 440 /* kf */ NOT_BEGIN | BREAK | NOT_END, 441 /* kg */ NOT_BEGIN | BREAK | NOT_END, 442 /* kh */ NOT_BEGIN | BREAK | NOT_END, 443 /* ki */ ANY_COMBINATION, 444 /* kj */ NOT_BEGIN | BREAK | NOT_END, 445 /* kk */ NOT_BEGIN | BREAK | NOT_END, 446 /* kl */ SUFFIX | NOT_END, 447 /* km */ NOT_BEGIN | BREAK | NOT_END, 448 /* kn */ BEGIN | SUFFIX | NOT_END, 449 /* ko */ ANY_COMBINATION, 450 /* kp */ NOT_BEGIN | BREAK | NOT_END, 451 /* kr */ SUFFIX | NOT_END, 452 /* ks */ NOT_BEGIN | END, 453 /* kt */ NOT_BEGIN | BREAK | NOT_END, 454 /* ku */ ANY_COMBINATION, 455 /* kv */ NOT_BEGIN | BREAK | NOT_END, 456 /* kw */ NOT_BEGIN | BREAK | NOT_END, 457 /* kx */ ILLEGAL_PAIR, 458 /* ky */ NOT_BEGIN, 459 /* kz */ NOT_BEGIN | BREAK | NOT_END, 460 /* kch */ NOT_BEGIN | BREAK | NOT_END, 461 /* kgh */ NOT_BEGIN | BREAK | NOT_END, 462 /* kph */ NOT_BEGIN | PREFIX, 463 /* krh */ ILLEGAL_PAIR, 464 /* ksh */ NOT_BEGIN, 465 /* kth */ NOT_BEGIN | BREAK | NOT_END, 466 /* kwh */ ILLEGAL_PAIR, 467 /* kqu */ NOT_BEGIN | BREAK | NOT_END, 468 /* kck */ ILLEGAL_PAIR }, 469 {/* la */ ANY_COMBINATION, 470 /* lb */ NOT_BEGIN | PREFIX, 471 /* lc */ NOT_BEGIN | BREAK | NOT_END, 472 /* ld */ NOT_BEGIN | PREFIX, 473 /* le */ ANY_COMBINATION, 474 /* lf */ NOT_BEGIN | PREFIX, 475 /* lg */ NOT_BEGIN | PREFIX, 476 /* lh */ NOT_BEGIN | BREAK | NOT_END, 477 /* li */ ANY_COMBINATION, 478 /* lj */ NOT_BEGIN | PREFIX, 479 /* lk */ NOT_BEGIN | PREFIX, 480 /* ll */ NOT_BEGIN | PREFIX, 481 /* lm */ NOT_BEGIN | PREFIX, 482 /* ln */ NOT_BEGIN | BREAK | NOT_END, 483 /* lo */ ANY_COMBINATION, 484 /* lp */ NOT_BEGIN | PREFIX, 485 /* lr */ NOT_BEGIN | BREAK | NOT_END, 486 /* ls */ NOT_BEGIN, 487 /* lt */ NOT_BEGIN | PREFIX, 488 /* lu */ ANY_COMBINATION, 489 /* lv */ NOT_BEGIN | PREFIX, 490 /* lw */ NOT_BEGIN | BREAK | NOT_END, 491 /* lx */ ILLEGAL_PAIR, 492 /* ly */ ANY_COMBINATION, 493 /* lz */ NOT_BEGIN | BREAK | NOT_END, 494 /* lch */ NOT_BEGIN | PREFIX, 495 /* lgh */ NOT_BEGIN | BREAK | NOT_END, 496 /* lph */ NOT_BEGIN | PREFIX, 497 /* lrh */ ILLEGAL_PAIR, 498 /* lsh */ NOT_BEGIN | PREFIX, 499 /* lth */ NOT_BEGIN | PREFIX, 500 /* lwh */ ILLEGAL_PAIR, 501 /* lqu */ NOT_BEGIN | BREAK | NOT_END, 502 /* lck */ ILLEGAL_PAIR }, 503 {/* ma */ ANY_COMBINATION, 504 /* mb */ NOT_BEGIN | BREAK | NOT_END, 505 /* mc */ NOT_BEGIN | BREAK | NOT_END, 506 /* md */ NOT_BEGIN | BREAK | NOT_END, 507 /* me */ ANY_COMBINATION, 508 /* mf */ NOT_BEGIN | BREAK | NOT_END, 509 /* mg */ NOT_BEGIN | BREAK | NOT_END, 510 /* mh */ NOT_BEGIN | BREAK | NOT_END, 511 /* mi */ ANY_COMBINATION, 512 /* mj */ NOT_BEGIN | BREAK | NOT_END, 513 /* mk */ NOT_BEGIN | BREAK | NOT_END, 514 /* ml */ NOT_BEGIN | BREAK | NOT_END, 515 /* mm */ NOT_BEGIN, 516 /* mn */ NOT_BEGIN | BREAK | NOT_END, 517 /* mo */ ANY_COMBINATION, 518 /* mp */ NOT_BEGIN, 519 /* mr */ NOT_BEGIN | BREAK | NOT_END, 520 /* ms */ NOT_BEGIN, 521 /* mt */ NOT_BEGIN, 522 /* mu */ ANY_COMBINATION, 523 /* mv */ NOT_BEGIN | BREAK | NOT_END, 524 /* mw */ NOT_BEGIN | BREAK | NOT_END, 525 /* mx */ ILLEGAL_PAIR, 526 /* my */ ANY_COMBINATION, 527 /* mz */ NOT_BEGIN | BREAK | NOT_END, 528 /* mch */ NOT_BEGIN | PREFIX, 529 /* mgh */ NOT_BEGIN | BREAK | NOT_END, 530 /* mph */ NOT_BEGIN, 531 /* mrh */ ILLEGAL_PAIR, 532 /* msh */ NOT_BEGIN, 533 /* mth */ NOT_BEGIN, 534 /* mwh */ ILLEGAL_PAIR, 535 /* mqu */ NOT_BEGIN | BREAK | NOT_END, 536 /* mck */ ILLEGAL_PAIR }, 537 {/* na */ ANY_COMBINATION, 538 /* nb */ NOT_BEGIN | BREAK | NOT_END, 539 /* nc */ NOT_BEGIN | BREAK | NOT_END, 540 /* nd */ NOT_BEGIN, 541 /* ne */ ANY_COMBINATION, 542 /* nf */ NOT_BEGIN | BREAK | NOT_END, 543 /* ng */ NOT_BEGIN | PREFIX, 544 /* nh */ NOT_BEGIN | BREAK | NOT_END, 545 /* ni */ ANY_COMBINATION, 546 /* nj */ NOT_BEGIN | BREAK | NOT_END, 547 /* nk */ NOT_BEGIN | PREFIX, 548 /* nl */ NOT_BEGIN | BREAK | NOT_END, 549 /* nm */ NOT_BEGIN | BREAK | NOT_END, 550 /* nn */ NOT_BEGIN, 551 /* no */ ANY_COMBINATION, 552 /* np */ NOT_BEGIN | BREAK | NOT_END, 553 /* nr */ NOT_BEGIN | BREAK | NOT_END, 554 /* ns */ NOT_BEGIN, 555 /* nt */ NOT_BEGIN, 556 /* nu */ ANY_COMBINATION, 557 /* nv */ NOT_BEGIN | BREAK | NOT_END, 558 /* nw */ NOT_BEGIN | BREAK | NOT_END, 559 /* nx */ ILLEGAL_PAIR, 560 /* ny */ NOT_BEGIN, 561 /* nz */ NOT_BEGIN | BREAK | NOT_END, 562 /* nch */ NOT_BEGIN | PREFIX, 563 /* ngh */ NOT_BEGIN | BREAK | NOT_END, 564 /* nph */ NOT_BEGIN | PREFIX, 565 /* nrh */ ILLEGAL_PAIR, 566 /* nsh */ NOT_BEGIN, 567 /* nth */ NOT_BEGIN, 568 /* nwh */ ILLEGAL_PAIR, 569 /* nqu */ NOT_BEGIN | BREAK | NOT_END, 570 /* nck */ NOT_BEGIN | PREFIX }, 571 {/* oa */ ANY_COMBINATION, 572 /* ob */ ANY_COMBINATION, 573 /* oc */ ANY_COMBINATION, 574 /* od */ ANY_COMBINATION, 575 /* oe */ ILLEGAL_PAIR, 576 /* of */ ANY_COMBINATION, 577 /* og */ ANY_COMBINATION, 578 /* oh */ NOT_BEGIN | BREAK | NOT_END, 579 /* oi */ ANY_COMBINATION, 580 /* oj */ ANY_COMBINATION, 581 /* ok */ ANY_COMBINATION, 582 /* ol */ ANY_COMBINATION, 583 /* om */ ANY_COMBINATION, 584 /* on */ ANY_COMBINATION, 585 /* oo */ ANY_COMBINATION, 586 /* op */ ANY_COMBINATION, 587 /* or */ ANY_COMBINATION, 588 /* os */ ANY_COMBINATION, 589 /* ot */ ANY_COMBINATION, 590 /* ou */ ANY_COMBINATION, 591 /* ov */ ANY_COMBINATION, 592 /* ow */ ANY_COMBINATION, 593 /* ox */ ANY_COMBINATION, 594 /* oy */ ANY_COMBINATION, 595 /* oz */ ANY_COMBINATION, 596 /* och */ ANY_COMBINATION, 597 /* ogh */ NOT_BEGIN, 598 /* oph */ ANY_COMBINATION, 599 /* orh */ ILLEGAL_PAIR, 600 /* osh */ ANY_COMBINATION, 601 /* oth */ ANY_COMBINATION, 602 /* owh */ ILLEGAL_PAIR, 603 /* oqu */ BREAK | NOT_END, 604 /* ock */ ANY_COMBINATION }, 605 {/* pa */ ANY_COMBINATION, 606 /* pb */ NOT_BEGIN | BREAK | NOT_END, 607 /* pc */ NOT_BEGIN | BREAK | NOT_END, 608 /* pd */ NOT_BEGIN | BREAK | NOT_END, 609 /* pe */ ANY_COMBINATION, 610 /* pf */ NOT_BEGIN | BREAK | NOT_END, 611 /* pg */ NOT_BEGIN | BREAK | NOT_END, 612 /* ph */ NOT_BEGIN | BREAK | NOT_END, 613 /* pi */ ANY_COMBINATION, 614 /* pj */ NOT_BEGIN | BREAK | NOT_END, 615 /* pk */ NOT_BEGIN | BREAK | NOT_END, 616 /* pl */ SUFFIX | NOT_END, 617 /* pm */ NOT_BEGIN | BREAK | NOT_END, 618 /* pn */ NOT_BEGIN | BREAK | NOT_END, 619 /* po */ ANY_COMBINATION, 620 /* pp */ NOT_BEGIN | PREFIX, 621 /* pr */ NOT_END, 622 /* ps */ NOT_BEGIN | END, 623 /* pt */ NOT_BEGIN | END, 624 /* pu */ NOT_BEGIN | END, 625 /* pv */ NOT_BEGIN | BREAK | NOT_END, 626 /* pw */ NOT_BEGIN | BREAK | NOT_END, 627 /* px */ ILLEGAL_PAIR, 628 /* py */ ANY_COMBINATION, 629 /* pz */ NOT_BEGIN | BREAK | NOT_END, 630 /* pch */ NOT_BEGIN | BREAK | NOT_END, 631 /* pgh */ NOT_BEGIN | BREAK | NOT_END, 632 /* pph */ NOT_BEGIN | BREAK | NOT_END, 633 /* prh */ ILLEGAL_PAIR, 634 /* psh */ NOT_BEGIN | BREAK | NOT_END, 635 /* pth */ NOT_BEGIN | BREAK | NOT_END, 636 /* pwh */ ILLEGAL_PAIR, 637 /* pqu */ NOT_BEGIN | BREAK | NOT_END, 638 /* pck */ ILLEGAL_PAIR }, 639 {/* ra */ ANY_COMBINATION, 640 /* rb */ NOT_BEGIN | PREFIX, 641 /* rc */ NOT_BEGIN | PREFIX, 642 /* rd */ NOT_BEGIN | PREFIX, 643 /* re */ ANY_COMBINATION, 644 /* rf */ NOT_BEGIN | PREFIX, 645 /* rg */ NOT_BEGIN | PREFIX, 646 /* rh */ NOT_BEGIN | BREAK | NOT_END, 647 /* ri */ ANY_COMBINATION, 648 /* rj */ NOT_BEGIN | PREFIX, 649 /* rk */ NOT_BEGIN | PREFIX, 650 /* rl */ NOT_BEGIN | PREFIX, 651 /* rm */ NOT_BEGIN | PREFIX, 652 /* rn */ NOT_BEGIN | PREFIX, 653 /* ro */ ANY_COMBINATION, 654 /* rp */ NOT_BEGIN | PREFIX, 655 /* rr */ NOT_BEGIN | PREFIX, 656 /* rs */ NOT_BEGIN | PREFIX, 657 /* rt */ NOT_BEGIN | PREFIX, 658 /* ru */ ANY_COMBINATION, 659 /* rv */ NOT_BEGIN | PREFIX, 660 /* rw */ NOT_BEGIN | BREAK | NOT_END, 661 /* rx */ ILLEGAL_PAIR, 662 /* ry */ ANY_COMBINATION, 663 /* rz */ NOT_BEGIN | PREFIX, 664 /* rch */ NOT_BEGIN | PREFIX, 665 /* rgh */ NOT_BEGIN | BREAK | NOT_END, 666 /* rph */ NOT_BEGIN | PREFIX, 667 /* rrh */ ILLEGAL_PAIR, 668 /* rsh */ NOT_BEGIN | PREFIX, 669 /* rth */ NOT_BEGIN | PREFIX, 670 /* rwh */ ILLEGAL_PAIR, 671 /* rqu */ NOT_BEGIN | PREFIX | NOT_END, 672 /* rck */ NOT_BEGIN | PREFIX }, 673 {/* sa */ ANY_COMBINATION, 674 /* sb */ NOT_BEGIN | BREAK | NOT_END, 675 /* sc */ NOT_END, 676 /* sd */ NOT_BEGIN | BREAK | NOT_END, 677 /* se */ ANY_COMBINATION, 678 /* sf */ NOT_BEGIN | BREAK | NOT_END, 679 /* sg */ NOT_BEGIN | BREAK | NOT_END, 680 /* sh */ NOT_BEGIN | BREAK | NOT_END, 681 /* si */ ANY_COMBINATION, 682 /* sj */ NOT_BEGIN | BREAK | NOT_END, 683 /* sk */ ANY_COMBINATION, 684 /* sl */ BEGIN | SUFFIX | NOT_END, 685 /* sm */ SUFFIX | NOT_END, 686 /* sn */ PREFIX | SUFFIX | NOT_END, 687 /* so */ ANY_COMBINATION, 688 /* sp */ ANY_COMBINATION, 689 /* sr */ NOT_BEGIN | NOT_END, 690 /* ss */ NOT_BEGIN | PREFIX, 691 /* st */ ANY_COMBINATION, 692 /* su */ ANY_COMBINATION, 693 /* sv */ NOT_BEGIN | BREAK | NOT_END, 694 /* sw */ BEGIN | SUFFIX | NOT_END, 695 /* sx */ ILLEGAL_PAIR, 696 /* sy */ ANY_COMBINATION, 697 /* sz */ NOT_BEGIN | BREAK | NOT_END, 698 /* sch */ BEGIN | SUFFIX | NOT_END, 699 /* sgh */ NOT_BEGIN | BREAK | NOT_END, 700 /* sph */ NOT_BEGIN | BREAK | NOT_END, 701 /* srh */ ILLEGAL_PAIR, 702 /* ssh */ NOT_BEGIN | BREAK | NOT_END, 703 /* sth */ NOT_BEGIN | BREAK | NOT_END, 704 /* swh */ ILLEGAL_PAIR, 705 /* squ */ SUFFIX | NOT_END, 706 /* sck */ NOT_BEGIN }, 707 {/* ta */ ANY_COMBINATION, 708 /* tb */ NOT_BEGIN | BREAK | NOT_END, 709 /* tc */ NOT_BEGIN | BREAK | NOT_END, 710 /* td */ NOT_BEGIN | BREAK | NOT_END, 711 /* te */ ANY_COMBINATION, 712 /* tf */ NOT_BEGIN | BREAK | NOT_END, 713 /* tg */ NOT_BEGIN | BREAK | NOT_END, 714 /* th */ NOT_BEGIN | BREAK | NOT_END, 715 /* ti */ ANY_COMBINATION, 716 /* tj */ NOT_BEGIN | BREAK | NOT_END, 717 /* tk */ NOT_BEGIN | BREAK | NOT_END, 718 /* tl */ NOT_BEGIN | BREAK | NOT_END, 719 /* tm */ NOT_BEGIN | BREAK | NOT_END, 720 /* tn */ NOT_BEGIN | BREAK | NOT_END, 721 /* to */ ANY_COMBINATION, 722 /* tp */ NOT_BEGIN | BREAK | NOT_END, 723 /* tr */ NOT_END, 724 /* ts */ NOT_BEGIN | END, 725 /* tt */ NOT_BEGIN | PREFIX, 726 /* tu */ ANY_COMBINATION, 727 /* tv */ NOT_BEGIN | BREAK | NOT_END, 728 /* tw */ BEGIN | SUFFIX | NOT_END, 729 /* tx */ ILLEGAL_PAIR, 730 /* ty */ ANY_COMBINATION, 731 /* tz */ NOT_BEGIN | BREAK | NOT_END, 732 /* tch */ NOT_BEGIN, 733 /* tgh */ NOT_BEGIN | BREAK | NOT_END, 734 /* tph */ NOT_BEGIN | END, 735 /* trh */ ILLEGAL_PAIR, 736 /* tsh */ NOT_BEGIN | END, 737 /* tth */ NOT_BEGIN | BREAK | NOT_END, 738 /* twh */ ILLEGAL_PAIR, 739 /* tqu */ NOT_BEGIN | BREAK | NOT_END, 740 /* tck */ ILLEGAL_PAIR }, 741 {/* ua */ NOT_BEGIN | BREAK | NOT_END, 742 /* ub */ ANY_COMBINATION, 743 /* uc */ ANY_COMBINATION, 744 /* ud */ ANY_COMBINATION, 745 /* ue */ NOT_BEGIN, 746 /* uf */ ANY_COMBINATION, 747 /* ug */ ANY_COMBINATION, 748 /* uh */ NOT_BEGIN | BREAK | NOT_END, 749 /* ui */ NOT_BEGIN | BREAK | NOT_END, 750 /* uj */ ANY_COMBINATION, 751 /* uk */ ANY_COMBINATION, 752 /* ul */ ANY_COMBINATION, 753 /* um */ ANY_COMBINATION, 754 /* un */ ANY_COMBINATION, 755 /* uo */ NOT_BEGIN | BREAK, 756 /* up */ ANY_COMBINATION, 757 /* ur */ ANY_COMBINATION, 758 /* us */ ANY_COMBINATION, 759 /* ut */ ANY_COMBINATION, 760 /* uu */ ILLEGAL_PAIR, 761 /* uv */ ANY_COMBINATION, 762 /* uw */ NOT_BEGIN | BREAK | NOT_END, 763 /* ux */ ANY_COMBINATION, 764 /* uy */ NOT_BEGIN | BREAK | NOT_END, 765 /* uz */ ANY_COMBINATION, 766 /* uch */ ANY_COMBINATION, 767 /* ugh */ NOT_BEGIN | PREFIX, 768 /* uph */ ANY_COMBINATION, 769 /* urh */ ILLEGAL_PAIR, 770 /* ush */ ANY_COMBINATION, 771 /* uth */ ANY_COMBINATION, 772 /* uwh */ ILLEGAL_PAIR, 773 /* uqu */ BREAK | NOT_END, 774 /* uck */ ANY_COMBINATION }, 775 {/* va */ ANY_COMBINATION, 776 /* vb */ NOT_BEGIN | BREAK | NOT_END, 777 /* vc */ NOT_BEGIN | BREAK | NOT_END, 778 /* vd */ NOT_BEGIN | BREAK | NOT_END, 779 /* ve */ ANY_COMBINATION, 780 /* vf */ NOT_BEGIN | BREAK | NOT_END, 781 /* vg */ NOT_BEGIN | BREAK | NOT_END, 782 /* vh */ NOT_BEGIN | BREAK | NOT_END, 783 /* vi */ ANY_COMBINATION, 784 /* vj */ NOT_BEGIN | BREAK | NOT_END, 785 /* vk */ NOT_BEGIN | BREAK | NOT_END, 786 /* vl */ NOT_BEGIN | BREAK | NOT_END, 787 /* vm */ NOT_BEGIN | BREAK | NOT_END, 788 /* vn */ NOT_BEGIN | BREAK | NOT_END, 789 /* vo */ ANY_COMBINATION, 790 /* vp */ NOT_BEGIN | BREAK | NOT_END, 791 /* vr */ NOT_BEGIN | BREAK | NOT_END, 792 /* vs */ NOT_BEGIN | BREAK | NOT_END, 793 /* vt */ NOT_BEGIN | BREAK | NOT_END, 794 /* vu */ ANY_COMBINATION, 795 /* vv */ NOT_BEGIN | BREAK | NOT_END, 796 /* vw */ NOT_BEGIN | BREAK | NOT_END, 797 /* vx */ ILLEGAL_PAIR, 798 /* vy */ NOT_BEGIN, 799 /* vz */ NOT_BEGIN | BREAK | NOT_END, 800 /* vch */ NOT_BEGIN | BREAK | NOT_END, 801 /* vgh */ NOT_BEGIN | BREAK | NOT_END, 802 /* vph */ NOT_BEGIN | BREAK | NOT_END, 803 /* vrh */ ILLEGAL_PAIR, 804 /* vsh */ NOT_BEGIN | BREAK | NOT_END, 805 /* vth */ NOT_BEGIN | BREAK | NOT_END, 806 /* vwh */ ILLEGAL_PAIR, 807 /* vqu */ NOT_BEGIN | BREAK | NOT_END, 808 /* vck */ ILLEGAL_PAIR }, 809 {/* wa */ ANY_COMBINATION, 810 /* wb */ NOT_BEGIN | PREFIX, 811 /* wc */ NOT_BEGIN | BREAK | NOT_END, 812 /* wd */ NOT_BEGIN | PREFIX | END, 813 /* we */ ANY_COMBINATION, 814 /* wf */ NOT_BEGIN | PREFIX, 815 /* wg */ NOT_BEGIN | PREFIX | END, 816 /* wh */ NOT_BEGIN | BREAK | NOT_END, 817 /* wi */ ANY_COMBINATION, 818 /* wj */ NOT_BEGIN | BREAK | NOT_END, 819 /* wk */ NOT_BEGIN | PREFIX, 820 /* wl */ NOT_BEGIN | PREFIX | SUFFIX, 821 /* wm */ NOT_BEGIN | PREFIX, 822 /* wn */ NOT_BEGIN | PREFIX, 823 /* wo */ ANY_COMBINATION, 824 /* wp */ NOT_BEGIN | PREFIX, 825 /* wr */ BEGIN | SUFFIX | NOT_END, 826 /* ws */ NOT_BEGIN | PREFIX, 827 /* wt */ NOT_BEGIN | PREFIX, 828 /* wu */ ANY_COMBINATION, 829 /* wv */ NOT_BEGIN | PREFIX, 830 /* ww */ NOT_BEGIN | BREAK | NOT_END, 831 /* wx */ NOT_BEGIN | PREFIX, 832 /* wy */ ANY_COMBINATION, 833 /* wz */ NOT_BEGIN | PREFIX, 834 /* wch */ NOT_BEGIN, 835 /* wgh */ NOT_BEGIN | BREAK | NOT_END, 836 /* wph */ NOT_BEGIN, 837 /* wrh */ ILLEGAL_PAIR, 838 /* wsh */ NOT_BEGIN, 839 /* wth */ NOT_BEGIN, 840 /* wwh */ ILLEGAL_PAIR, 841 /* wqu */ NOT_BEGIN | BREAK | NOT_END, 842 /* wck */ NOT_BEGIN }, 843 {/* xa */ NOT_BEGIN, 844 /* xb */ NOT_BEGIN | BREAK | NOT_END, 845 /* xc */ NOT_BEGIN | BREAK | NOT_END, 846 /* xd */ NOT_BEGIN | BREAK | NOT_END, 847 /* xe */ NOT_BEGIN, 848 /* xf */ NOT_BEGIN | BREAK | NOT_END, 849 /* xg */ NOT_BEGIN | BREAK | NOT_END, 850 /* xh */ NOT_BEGIN | BREAK | NOT_END, 851 /* xi */ NOT_BEGIN, 852 /* xj */ NOT_BEGIN | BREAK | NOT_END, 853 /* xk */ NOT_BEGIN | BREAK | NOT_END, 854 /* xl */ NOT_BEGIN | BREAK | NOT_END, 855 /* xm */ NOT_BEGIN | BREAK | NOT_END, 856 /* xn */ NOT_BEGIN | BREAK | NOT_END, 857 /* xo */ NOT_BEGIN, 858 /* xp */ NOT_BEGIN | BREAK | NOT_END, 859 /* xr */ NOT_BEGIN | BREAK | NOT_END, 860 /* xs */ NOT_BEGIN | BREAK | NOT_END, 861 /* xt */ NOT_BEGIN | BREAK | NOT_END, 862 /* xu */ NOT_BEGIN, 863 /* xv */ NOT_BEGIN | BREAK | NOT_END, 864 /* xw */ NOT_BEGIN | BREAK | NOT_END, 865 /* xx */ ILLEGAL_PAIR, 866 /* xy */ NOT_BEGIN, 867 /* xz */ NOT_BEGIN | BREAK | NOT_END, 868 /* xch */ NOT_BEGIN | BREAK | NOT_END, 869 /* xgh */ NOT_BEGIN | BREAK | NOT_END, 870 /* xph */ NOT_BEGIN | BREAK | NOT_END, 871 /* xrh */ ILLEGAL_PAIR, 872 /* xsh */ NOT_BEGIN | BREAK | NOT_END, 873 /* xth */ NOT_BEGIN | BREAK | NOT_END, 874 /* xwh */ ILLEGAL_PAIR, 875 /* xqu */ NOT_BEGIN | BREAK | NOT_END, 876 /* xck */ ILLEGAL_PAIR }, 877 {/* ya */ ANY_COMBINATION, 878 /* yb */ NOT_BEGIN, 879 /* yc */ NOT_BEGIN | NOT_END, 880 /* yd */ NOT_BEGIN, 881 /* ye */ ANY_COMBINATION, 882 /* yf */ NOT_BEGIN | NOT_END, 883 /* yg */ NOT_BEGIN, 884 /* yh */ NOT_BEGIN | BREAK | NOT_END, 885 /* yi */ BEGIN | NOT_END, 886 /* yj */ NOT_BEGIN | NOT_END, 887 /* yk */ NOT_BEGIN, 888 /* yl */ NOT_BEGIN | NOT_END, 889 /* ym */ NOT_BEGIN, 890 /* yn */ NOT_BEGIN, 891 /* yo */ ANY_COMBINATION, 892 /* yp */ NOT_BEGIN, 893 /* yr */ NOT_BEGIN | BREAK | NOT_END, 894 /* ys */ NOT_BEGIN, 895 /* yt */ NOT_BEGIN, 896 /* yu */ ANY_COMBINATION, 897 /* yv */ NOT_BEGIN | NOT_END, 898 /* yw */ NOT_BEGIN | BREAK | NOT_END, 899 /* yx */ NOT_BEGIN, 900 /* yy */ ILLEGAL_PAIR, 901 /* yz */ NOT_BEGIN, 902 /* ych */ NOT_BEGIN | BREAK | NOT_END, 903 /* ygh */ NOT_BEGIN | BREAK | NOT_END, 904 /* yph */ NOT_BEGIN | BREAK | NOT_END, 905 /* yrh */ ILLEGAL_PAIR, 906 /* ysh */ NOT_BEGIN | BREAK | NOT_END, 907 /* yth */ NOT_BEGIN | BREAK | NOT_END, 908 /* ywh */ ILLEGAL_PAIR, 909 /* yqu */ NOT_BEGIN | BREAK | NOT_END, 910 /* yck */ ILLEGAL_PAIR }, 911 {/* za */ ANY_COMBINATION, 912 /* zb */ NOT_BEGIN | BREAK | NOT_END, 913 /* zc */ NOT_BEGIN | BREAK | NOT_END, 914 /* zd */ NOT_BEGIN | BREAK | NOT_END, 915 /* ze */ ANY_COMBINATION, 916 /* zf */ NOT_BEGIN | BREAK | NOT_END, 917 /* zg */ NOT_BEGIN | BREAK | NOT_END, 918 /* zh */ NOT_BEGIN | BREAK | NOT_END, 919 /* zi */ ANY_COMBINATION, 920 /* zj */ NOT_BEGIN | BREAK | NOT_END, 921 /* zk */ NOT_BEGIN | BREAK | NOT_END, 922 /* zl */ NOT_BEGIN | BREAK | NOT_END, 923 /* zm */ NOT_BEGIN | BREAK | NOT_END, 924 /* zn */ NOT_BEGIN | BREAK | NOT_END, 925 /* zo */ ANY_COMBINATION, 926 /* zp */ NOT_BEGIN | BREAK | NOT_END, 927 /* zr */ NOT_BEGIN | NOT_END, 928 /* zs */ NOT_BEGIN | BREAK | NOT_END, 929 /* zt */ NOT_BEGIN, 930 /* zu */ ANY_COMBINATION, 931 /* zv */ NOT_BEGIN | BREAK | NOT_END, 932 /* zw */ SUFFIX | NOT_END, 933 /* zx */ ILLEGAL_PAIR, 934 /* zy */ ANY_COMBINATION, 935 /* zz */ NOT_BEGIN, 936 /* zch */ NOT_BEGIN | BREAK | NOT_END, 937 /* zgh */ NOT_BEGIN | BREAK | NOT_END, 938 /* zph */ NOT_BEGIN | BREAK | NOT_END, 939 /* zrh */ ILLEGAL_PAIR, 940 /* zsh */ NOT_BEGIN | BREAK | NOT_END, 941 /* zth */ NOT_BEGIN | BREAK | NOT_END, 942 /* zwh */ ILLEGAL_PAIR, 943 /* zqu */ NOT_BEGIN | BREAK | NOT_END, 944 /* zck */ ILLEGAL_PAIR }, 945 {/* cha */ ANY_COMBINATION, 946 /* chb */ NOT_BEGIN | BREAK | NOT_END, 947 /* chc */ NOT_BEGIN | BREAK | NOT_END, 948 /* chd */ NOT_BEGIN | BREAK | NOT_END, 949 /* che */ ANY_COMBINATION, 950 /* chf */ NOT_BEGIN | BREAK | NOT_END, 951 /* chg */ NOT_BEGIN | BREAK | NOT_END, 952 /* chh */ NOT_BEGIN | BREAK | NOT_END, 953 /* chi */ ANY_COMBINATION, 954 /* chj */ NOT_BEGIN | BREAK | NOT_END, 955 /* chk */ NOT_BEGIN | BREAK | NOT_END, 956 /* chl */ NOT_BEGIN | BREAK | NOT_END, 957 /* chm */ NOT_BEGIN | BREAK | NOT_END, 958 /* chn */ NOT_BEGIN | BREAK | NOT_END, 959 /* cho */ ANY_COMBINATION, 960 /* chp */ NOT_BEGIN | BREAK | NOT_END, 961 /* chr */ NOT_END, 962 /* chs */ NOT_BEGIN | BREAK | NOT_END, 963 /* cht */ NOT_BEGIN | BREAK | NOT_END, 964 /* chu */ ANY_COMBINATION, 965 /* chv */ NOT_BEGIN | BREAK | NOT_END, 966 /* chw */ NOT_BEGIN | NOT_END, 967 /* chx */ ILLEGAL_PAIR, 968 /* chy */ ANY_COMBINATION, 969 /* chz */ NOT_BEGIN | BREAK | NOT_END, 970 /* chch */ ILLEGAL_PAIR, 971 /* chgh */ NOT_BEGIN | BREAK | NOT_END, 972 /* chph */ NOT_BEGIN | BREAK | NOT_END, 973 /* chrh */ ILLEGAL_PAIR, 974 /* chsh */ NOT_BEGIN | BREAK | NOT_END, 975 /* chth */ NOT_BEGIN | BREAK | NOT_END, 976 /* chwh */ ILLEGAL_PAIR, 977 /* chqu */ NOT_BEGIN | BREAK | NOT_END, 978 /* chck */ ILLEGAL_PAIR }, 979 {/* gha */ ANY_COMBINATION, 980 /* ghb */ NOT_BEGIN | BREAK | PREFIX | NOT_END, 981 /* ghc */ NOT_BEGIN | BREAK | PREFIX | NOT_END, 982 /* ghd */ NOT_BEGIN | BREAK | PREFIX | NOT_END, 983 /* ghe */ ANY_COMBINATION, 984 /* ghf */ NOT_BEGIN | BREAK | PREFIX | NOT_END, 985 /* ghg */ NOT_BEGIN | BREAK | PREFIX | NOT_END, 986 /* ghh */ NOT_BEGIN | BREAK | PREFIX | NOT_END, 987 /* ghi */ BEGIN | NOT_END, 988 /* ghj */ NOT_BEGIN | BREAK | PREFIX | NOT_END, 989 /* ghk */ NOT_BEGIN | BREAK | PREFIX | NOT_END, 990 /* ghl */ NOT_BEGIN | BREAK | PREFIX | NOT_END, 991 /* ghm */ NOT_BEGIN | BREAK | PREFIX | NOT_END, 992 /* ghn */ NOT_BEGIN | BREAK | PREFIX | NOT_END, 993 /* gho */ BEGIN | NOT_END, 994 /* ghp */ NOT_BEGIN | BREAK | NOT_END, 995 /* ghr */ NOT_BEGIN | BREAK | PREFIX | NOT_END, 996 /* ghs */ NOT_BEGIN | PREFIX, 997 /* ght */ NOT_BEGIN | PREFIX, 998 /* ghu */ NOT_BEGIN | BREAK | PREFIX | NOT_END, 999 /* ghv */ NOT_BEGIN | BREAK | PREFIX | NOT_END, 1000 /* ghw */ NOT_BEGIN | BREAK | PREFIX | NOT_END, 1001 /* ghx */ ILLEGAL_PAIR, 1002 /* ghy */ NOT_BEGIN | BREAK | PREFIX | NOT_END, 1003 /* ghz */ NOT_BEGIN | BREAK | PREFIX | NOT_END, 1004 /* ghch */ NOT_BEGIN | BREAK | PREFIX | NOT_END, 1005 /* ghgh */ ILLEGAL_PAIR, 1006 /* ghph */ NOT_BEGIN | BREAK | PREFIX | NOT_END, 1007 /* ghrh */ ILLEGAL_PAIR, 1008 /* ghsh */ NOT_BEGIN | BREAK | PREFIX | NOT_END, 1009 /* ghth */ NOT_BEGIN | BREAK | PREFIX | NOT_END, 1010 /* ghwh */ ILLEGAL_PAIR, 1011 /* ghqu */ NOT_BEGIN | BREAK | PREFIX | NOT_END, 1012 /* ghck */ ILLEGAL_PAIR }, 1013 {/* pha */ ANY_COMBINATION, 1014 /* phb */ NOT_BEGIN | BREAK | NOT_END, 1015 /* phc */ NOT_BEGIN | BREAK | NOT_END, 1016 /* phd */ NOT_BEGIN | BREAK | NOT_END, 1017 /* phe */ ANY_COMBINATION, 1018 /* phf */ NOT_BEGIN | BREAK | NOT_END, 1019 /* phg */ NOT_BEGIN | BREAK | NOT_END, 1020 /* phh */ NOT_BEGIN | BREAK | NOT_END, 1021 /* phi */ ANY_COMBINATION, 1022 /* phj */ NOT_BEGIN | BREAK | NOT_END, 1023 /* phk */ NOT_BEGIN | BREAK | NOT_END, 1024 /* phl */ BEGIN | SUFFIX | NOT_END, 1025 /* phm */ NOT_BEGIN | BREAK | NOT_END, 1026 /* phn */ NOT_BEGIN | BREAK | NOT_END, 1027 /* pho */ ANY_COMBINATION, 1028 /* php */ NOT_BEGIN | BREAK | NOT_END, 1029 /* phr */ NOT_END, 1030 /* phs */ NOT_BEGIN, 1031 /* pht */ NOT_BEGIN, 1032 /* phu */ ANY_COMBINATION, 1033 /* phv */ NOT_BEGIN | NOT_END, 1034 /* phw */ NOT_BEGIN | NOT_END, 1035 /* phx */ ILLEGAL_PAIR, 1036 /* phy */ NOT_BEGIN, 1037 /* phz */ NOT_BEGIN | BREAK | NOT_END, 1038 /* phch */ NOT_BEGIN | BREAK | NOT_END, 1039 /* phgh */ NOT_BEGIN | BREAK | NOT_END, 1040 /* phph */ ILLEGAL_PAIR, 1041 /* phrh */ ILLEGAL_PAIR, 1042 /* phsh */ NOT_BEGIN | BREAK | NOT_END, 1043 /* phth */ NOT_BEGIN | BREAK | NOT_END, 1044 /* phwh */ ILLEGAL_PAIR, 1045 /* phqu */ NOT_BEGIN | BREAK | NOT_END, 1046 /* phck */ ILLEGAL_PAIR }, 1047 {/* rha */ BEGIN | NOT_END, 1048 /* rhb */ ILLEGAL_PAIR, 1049 /* rhc */ ILLEGAL_PAIR, 1050 /* rhd */ ILLEGAL_PAIR, 1051 /* rhe */ BEGIN | NOT_END, 1052 /* rhf */ ILLEGAL_PAIR, 1053 /* rhg */ ILLEGAL_PAIR, 1054 /* rhh */ ILLEGAL_PAIR, 1055 /* rhi */ BEGIN | NOT_END, 1056 /* rhj */ ILLEGAL_PAIR, 1057 /* rhk */ ILLEGAL_PAIR, 1058 /* rhl */ ILLEGAL_PAIR, 1059 /* rhm */ ILLEGAL_PAIR, 1060 /* rhn */ ILLEGAL_PAIR, 1061 /* rho */ BEGIN | NOT_END, 1062 /* rhp */ ILLEGAL_PAIR, 1063 /* rhr */ ILLEGAL_PAIR, 1064 /* rhs */ ILLEGAL_PAIR, 1065 /* rht */ ILLEGAL_PAIR, 1066 /* rhu */ BEGIN | NOT_END, 1067 /* rhv */ ILLEGAL_PAIR, 1068 /* rhw */ ILLEGAL_PAIR, 1069 /* rhx */ ILLEGAL_PAIR, 1070 /* rhy */ BEGIN | NOT_END, 1071 /* rhz */ ILLEGAL_PAIR, 1072 /* rhch */ ILLEGAL_PAIR, 1073 /* rhgh */ ILLEGAL_PAIR, 1074 /* rhph */ ILLEGAL_PAIR, 1075 /* rhrh */ ILLEGAL_PAIR, 1076 /* rhsh */ ILLEGAL_PAIR, 1077 /* rhth */ ILLEGAL_PAIR, 1078 /* rhwh */ ILLEGAL_PAIR, 1079 /* rhqu */ ILLEGAL_PAIR, 1080 /* rhck */ ILLEGAL_PAIR }, 1081 {/* sha */ ANY_COMBINATION, 1082 /* shb */ NOT_BEGIN | BREAK | NOT_END, 1083 /* shc */ NOT_BEGIN | BREAK | NOT_END, 1084 /* shd */ NOT_BEGIN | BREAK | NOT_END, 1085 /* she */ ANY_COMBINATION, 1086 /* shf */ NOT_BEGIN | BREAK | NOT_END, 1087 /* shg */ NOT_BEGIN | BREAK | NOT_END, 1088 /* shh */ ILLEGAL_PAIR, 1089 /* shi */ ANY_COMBINATION, 1090 /* shj */ NOT_BEGIN | BREAK | NOT_END, 1091 /* shk */ NOT_BEGIN, 1092 /* shl */ BEGIN | SUFFIX | NOT_END, 1093 /* shm */ BEGIN | SUFFIX | NOT_END, 1094 /* shn */ BEGIN | SUFFIX | NOT_END, 1095 /* sho */ ANY_COMBINATION, 1096 /* shp */ NOT_BEGIN, 1097 /* shr */ BEGIN | SUFFIX | NOT_END, 1098 /* shs */ NOT_BEGIN | BREAK | NOT_END, 1099 /* sht */ SUFFIX, 1100 /* shu */ ANY_COMBINATION, 1101 /* shv */ NOT_BEGIN | BREAK | NOT_END, 1102 /* shw */ SUFFIX | NOT_END, 1103 /* shx */ ILLEGAL_PAIR, 1104 /* shy */ ANY_COMBINATION, 1105 /* shz */ NOT_BEGIN | BREAK | NOT_END, 1106 /* shch */ NOT_BEGIN | BREAK | NOT_END, 1107 /* shgh */ NOT_BEGIN | BREAK | NOT_END, 1108 /* shph */ NOT_BEGIN | BREAK | NOT_END, 1109 /* shrh */ ILLEGAL_PAIR, 1110 /* shsh */ ILLEGAL_PAIR, 1111 /* shth */ NOT_BEGIN | BREAK | NOT_END, 1112 /* shwh */ ILLEGAL_PAIR, 1113 /* shqu */ NOT_BEGIN | BREAK | NOT_END, 1114 /* shck */ ILLEGAL_PAIR }, 1115 {/* tha */ ANY_COMBINATION, 1116 /* thb */ NOT_BEGIN | BREAK | NOT_END, 1117 /* thc */ NOT_BEGIN | BREAK | NOT_END, 1118 /* thd */ NOT_BEGIN | BREAK | NOT_END, 1119 /* the */ ANY_COMBINATION, 1120 /* thf */ NOT_BEGIN | BREAK | NOT_END, 1121 /* thg */ NOT_BEGIN | BREAK | NOT_END, 1122 /* thh */ NOT_BEGIN | BREAK | NOT_END, 1123 /* thi */ ANY_COMBINATION, 1124 /* thj */ NOT_BEGIN | BREAK | NOT_END, 1125 /* thk */ NOT_BEGIN | BREAK | NOT_END, 1126 /* thl */ NOT_BEGIN | BREAK | NOT_END, 1127 /* thm */ NOT_BEGIN | BREAK | NOT_END, 1128 /* thn */ NOT_BEGIN | BREAK | NOT_END, 1129 /* tho */ ANY_COMBINATION, 1130 /* thp */ NOT_BEGIN | BREAK | NOT_END, 1131 /* thr */ NOT_END, 1132 /* ths */ NOT_BEGIN | END, 1133 /* tht */ NOT_BEGIN | BREAK | NOT_END, 1134 /* thu */ ANY_COMBINATION, 1135 /* thv */ NOT_BEGIN | BREAK | NOT_END, 1136 /* thw */ SUFFIX | NOT_END, 1137 /* thx */ ILLEGAL_PAIR, 1138 /* thy */ ANY_COMBINATION, 1139 /* thz */ NOT_BEGIN | BREAK | NOT_END, 1140 /* thch */ NOT_BEGIN | BREAK | NOT_END, 1141 /* thgh */ NOT_BEGIN | BREAK | NOT_END, 1142 /* thph */ NOT_BEGIN | BREAK | NOT_END, 1143 /* thrh */ ILLEGAL_PAIR, 1144 /* thsh */ NOT_BEGIN | BREAK | NOT_END, 1145 /* thth */ ILLEGAL_PAIR, 1146 /* thwh */ ILLEGAL_PAIR, 1147 /* thqu */ NOT_BEGIN | BREAK | NOT_END, 1148 /* thck */ ILLEGAL_PAIR }, 1149 {/* wha */ BEGIN | NOT_END, 1150 /* whb */ ILLEGAL_PAIR, 1151 /* whc */ ILLEGAL_PAIR, 1152 /* whd */ ILLEGAL_PAIR, 1153 /* whe */ BEGIN | NOT_END, 1154 /* whf */ ILLEGAL_PAIR, 1155 /* whg */ ILLEGAL_PAIR, 1156 /* whh */ ILLEGAL_PAIR, 1157 /* whi */ BEGIN | NOT_END, 1158 /* whj */ ILLEGAL_PAIR, 1159 /* whk */ ILLEGAL_PAIR, 1160 /* whl */ ILLEGAL_PAIR, 1161 /* whm */ ILLEGAL_PAIR, 1162 /* whn */ ILLEGAL_PAIR, 1163 /* who */ BEGIN | NOT_END, 1164 /* whp */ ILLEGAL_PAIR, 1165 /* whr */ ILLEGAL_PAIR, 1166 /* whs */ ILLEGAL_PAIR, 1167 /* wht */ ILLEGAL_PAIR, 1168 /* whu */ ILLEGAL_PAIR, 1169 /* whv */ ILLEGAL_PAIR, 1170 /* whw */ ILLEGAL_PAIR, 1171 /* whx */ ILLEGAL_PAIR, 1172 /* why */ BEGIN | NOT_END, 1173 /* whz */ ILLEGAL_PAIR, 1174 /* whch */ ILLEGAL_PAIR, 1175 /* whgh */ ILLEGAL_PAIR, 1176 /* whph */ ILLEGAL_PAIR, 1177 /* whrh */ ILLEGAL_PAIR, 1178 /* whsh */ ILLEGAL_PAIR, 1179 /* whth */ ILLEGAL_PAIR, 1180 /* whwh */ ILLEGAL_PAIR, 1181 /* whqu */ ILLEGAL_PAIR, 1182 /* whck */ ILLEGAL_PAIR }, 1183 {/* qua */ ANY_COMBINATION, 1184 /* qub */ ILLEGAL_PAIR, 1185 /* quc */ ILLEGAL_PAIR, 1186 /* qud */ ILLEGAL_PAIR, 1187 /* que */ ANY_COMBINATION, 1188 /* quf */ ILLEGAL_PAIR, 1189 /* qug */ ILLEGAL_PAIR, 1190 /* quh */ ILLEGAL_PAIR, 1191 /* qui */ ANY_COMBINATION, 1192 /* quj */ ILLEGAL_PAIR, 1193 /* quk */ ILLEGAL_PAIR, 1194 /* qul */ ILLEGAL_PAIR, 1195 /* qum */ ILLEGAL_PAIR, 1196 /* qun */ ILLEGAL_PAIR, 1197 /* quo */ ANY_COMBINATION, 1198 /* qup */ ILLEGAL_PAIR, 1199 /* qur */ ILLEGAL_PAIR, 1200 /* qus */ ILLEGAL_PAIR, 1201 /* qut */ ILLEGAL_PAIR, 1202 /* quu */ ILLEGAL_PAIR, 1203 /* quv */ ILLEGAL_PAIR, 1204 /* quw */ ILLEGAL_PAIR, 1205 /* qux */ ILLEGAL_PAIR, 1206 /* quy */ ILLEGAL_PAIR, 1207 /* quz */ ILLEGAL_PAIR, 1208 /* quch */ ILLEGAL_PAIR, 1209 /* qugh */ ILLEGAL_PAIR, 1210 /* quph */ ILLEGAL_PAIR, 1211 /* qurh */ ILLEGAL_PAIR, 1212 /* qush */ ILLEGAL_PAIR, 1213 /* quth */ ILLEGAL_PAIR, 1214 /* quwh */ ILLEGAL_PAIR, 1215 /* ququ */ ILLEGAL_PAIR, 1216 /* quck */ ILLEGAL_PAIR }, 1217 {/* cka */ NOT_BEGIN | BREAK | NOT_END, 1218 /* ckb */ NOT_BEGIN | BREAK | NOT_END, 1219 /* ckc */ NOT_BEGIN | BREAK | NOT_END, 1220 /* ckd */ NOT_BEGIN | BREAK | NOT_END, 1221 /* cke */ NOT_BEGIN | BREAK | NOT_END, 1222 /* ckf */ NOT_BEGIN | BREAK | NOT_END, 1223 /* ckg */ NOT_BEGIN | BREAK | NOT_END, 1224 /* ckh */ NOT_BEGIN | BREAK | NOT_END, 1225 /* cki */ NOT_BEGIN | BREAK | NOT_END, 1226 /* ckj */ NOT_BEGIN | BREAK | NOT_END, 1227 /* ckk */ NOT_BEGIN | BREAK | NOT_END, 1228 /* ckl */ NOT_BEGIN | BREAK | NOT_END, 1229 /* ckm */ NOT_BEGIN | BREAK | NOT_END, 1230 /* ckn */ NOT_BEGIN | BREAK | NOT_END, 1231 /* cko */ NOT_BEGIN | BREAK | NOT_END, 1232 /* ckp */ NOT_BEGIN | BREAK | NOT_END, 1233 /* ckr */ NOT_BEGIN | BREAK | NOT_END, 1234 /* cks */ NOT_BEGIN, 1235 /* ckt */ NOT_BEGIN | BREAK | NOT_END, 1236 /* cku */ NOT_BEGIN | BREAK | NOT_END, 1237 /* ckv */ NOT_BEGIN | BREAK | NOT_END, 1238 /* ckw */ NOT_BEGIN | BREAK | NOT_END, 1239 /* ckx */ ILLEGAL_PAIR, 1240 /* cky */ NOT_BEGIN, 1241 /* ckz */ NOT_BEGIN | BREAK | NOT_END, 1242 /* ckch */ NOT_BEGIN | BREAK | NOT_END, 1243 /* ckgh */ NOT_BEGIN | BREAK | NOT_END, 1244 /* ckph */ NOT_BEGIN | BREAK | NOT_END, 1245 /* ckrh */ ILLEGAL_PAIR, 1246 /* cksh */ NOT_BEGIN | BREAK | NOT_END, 1247 /* ckth */ NOT_BEGIN | BREAK | NOT_END, 1248 /* ckwh */ ILLEGAL_PAIR, 1249 /* ckqu */ NOT_BEGIN | BREAK | NOT_END, 1250 /* ckck */ ILLEGAL_PAIR} 1251 }; 1252 1253 /* 1254 ** gen_pron_pass will generate a Random word and place it in the 1255 ** buffer word. Also, the hyphenated word will be placed into 1256 ** the buffer hyphenated_word. Both word and hyphenated_word must 1257 ** be pre-allocated. The words generated will have sizes between 1258 ** minlen and maxlen. If restrict is TRUE, words will not be generated that 1259 ** appear as login names or as entries in the on-line dictionary. 1260 ** This algorithm was initially worded out by Morrie Gasser in 1975. 1261 ** Any changes here are minimal so that as many word combinations 1262 ** can be produced as possible (and thus keep the words Random). 1263 ** The seed is used on first use of the routine. 1264 ** The length of the unhyphenated word is returned, or -1 if there 1265 ** were an error (length settings are wrong or dictionary checking 1266 ** could not be done. 1267 */ 1268 int 1269 gen_pron_pass (char *word, char *hyphenated_word, USHORT minlen, 1270 USHORT maxlen, unsigned int pass_mode) 1271 { 1272 1273 int pwlen; 1274 1275 /* 1276 * Check for minlen>maxlen. This is an error. 1277 * and a length of 0. 1278 */ 1279 if (minlen > maxlen || minlen > APG_MAX_PASSWORD_LENGTH || 1280 maxlen > APG_MAX_PASSWORD_LENGTH) 1281 return (-1); 1282 /* 1283 * Check for zero length words. This is technically not an error, 1284 * so we take the short cut and return a null word and a length of 0. 1285 */ 1286 if (maxlen == 0) 1287 { 1288 word[0] = '\0'; 1289 hyphenated_word[0] = '\0'; 1290 return (0); 1291 } 1292 1293 /* 1294 * Find password. 1295 */ 1296 pwlen = gen_word (word, hyphenated_word, base::RandInt(minlen, maxlen), 1297 pass_mode); 1298 return (pwlen); 1299 } 1300 1301 1302 /* 1303 * This is the routine that returns a Random word -- as 1304 * yet unchecked against the passwd file or the dictionary. 1305 * It collects Random syllables until a predetermined 1306 * word length is found. If a retry threshold is reached, 1307 * another word is tried. Given that the Random number 1308 * generator is uniformly distributed, eventually a word 1309 * will be found if the retry limit is adequately large enough. 1310 */ 1311 int 1312 gen_word (char *word, char *hyphenated_word, USHORT pwlen, unsigned int pass_mode) 1313 { 1314 USHORT word_length; 1315 USHORT syllable_length; 1316 char *new_syllable; 1317 char *syllable_for_hyph; 1318 USHORT *syllable_units; 1319 USHORT word_size; 1320 USHORT word_place; 1321 USHORT *word_units; 1322 USHORT syllable_size; 1323 UINT tries; 1324 int ch_flag = FALSE; 1325 int dsd = 0; 1326 1327 /* 1328 * Keep count of retries. 1329 */ 1330 tries = 0; 1331 1332 /* 1333 * The length of the word in characters. 1334 */ 1335 word_length = 0; 1336 1337 /* 1338 * The length of the word in character units (each of which is one or 1339 * two characters long. 1340 */ 1341 word_size = 0; 1342 1343 /* 1344 * Initialize the array storing the word units. Since we know the 1345 * length of the word, we only need one of that length. This method is 1346 * preferable to a static array, since it allows us flexibility in 1347 * choosing arbitrarily long word lengths. Since a word can contain one 1348 * syllable, we should make syllable_units, the array holding the 1349 * analogous units for an individual syllable, the same length. No 1350 * explicit rule limits the length of syllables, but digram rules and 1351 * heuristics do so indirectly. 1352 */ 1353 if ( (word_units = (USHORT *) calloc (sizeof (USHORT), pwlen+1))==NULL || 1354 (syllable_units = (USHORT *) calloc (sizeof (USHORT), pwlen+1))==NULL || 1355 (new_syllable = (char *) calloc (sizeof (USHORT), pwlen+1)) ==NULL || 1356 (syllable_for_hyph = (char *) calloc (sizeof(char), 20))==NULL) 1357 return(-1); 1358 1359 /* 1360 * Find syllables until the entire word is constructed. 1361 */ 1362 while (word_length < pwlen) 1363 { 1364 /* 1365 * Get the syllable and find its length. 1366 */ 1367 (void) gen_syllable (new_syllable, pwlen - word_length, syllable_units, &syllable_size); 1368 syllable_length = (USHORT) strlen (new_syllable); 1369 1370 /* 1371 * Append the syllable units to the word units. 1372 */ 1373 for (word_place = 0; word_place <= syllable_size; word_place++) 1374 word_units[word_size + word_place] = syllable_units[word_place]; 1375 word_size += syllable_size + 1; 1376 1377 /* 1378 * If the word has been improperly formed, throw out 1379 * the syllable. The checks performed here are those 1380 * that must be formed on a word basis. The other 1381 * tests are performed entirely within the syllable. 1382 * Otherwise, append the syllable to the word and 1383 * append the syllable to the hyphenated version of 1384 * the word. 1385 */ 1386 if (improper_word (word_units, word_size) || 1387 ((word_length == 0) && have_initial_y (syllable_units, syllable_size)) || 1388 ((word_length + syllable_length == pwlen) && have_final_split (syllable_units, syllable_size))) 1389 word_size -= syllable_size + 1; 1390 else 1391 { 1392 if (word_length == 0) 1393 { 1394 /* 1395 ** Modify syllable for numeric or capital symbols required 1396 ** Should be done after word quality check. 1397 */ 1398 dsd = base::RandInt(0, 1); 1399 if ( ((pass_mode & S_NB) > 0) && (syllable_length == 1) && dsd == 0) 1400 { 1401 numerize(new_syllable); 1402 ch_flag = TRUE; 1403 } 1404 if ( ((pass_mode & S_SS) > 0) && (syllable_length == 1) && (dsd == 1)) 1405 { 1406 specialize(new_syllable); 1407 ch_flag = TRUE; 1408 } 1409 if ( ( (pass_mode & S_CL) > 0) && (ch_flag != TRUE)) 1410 capitalize(new_syllable); 1411 ch_flag = FALSE; 1412 /**/ 1413 (void) strcpy (word, new_syllable); 1414 if (syllable_length == 1) 1415 { 1416 symb2name(new_syllable, syllable_for_hyph); 1417 (void) strcpy (hyphenated_word, syllable_for_hyph); 1418 } 1419 else 1420 { 1421 (void) strcpy (hyphenated_word, new_syllable); 1422 } 1423 (void)memset ( (void *)new_syllable, 0, (size_t)(pwlen * sizeof(USHORT)+1)); 1424 (void)memset ( (void *)syllable_for_hyph, 0, 20); 1425 } 1426 else 1427 { 1428 /* 1429 ** Modify syllable for numeric or capital symbols required 1430 ** Should be done after word quality check. 1431 */ 1432 dsd = base::RandInt(0, 1); 1433 if ( ((pass_mode & S_NB) > 0) && (syllable_length == 1) && (dsd == 0)) 1434 { 1435 numerize(new_syllable); 1436 ch_flag = TRUE; 1437 } 1438 if ( ( (pass_mode & S_SS) > 0) && (syllable_length == 1) && (dsd == 1)) 1439 { 1440 specialize(new_syllable); 1441 ch_flag = TRUE; 1442 } 1443 if ( ( (pass_mode & S_CL) > 0) && (ch_flag != TRUE)) 1444 capitalize(new_syllable); 1445 ch_flag = FALSE; 1446 /**/ 1447 (void) strcat (word, new_syllable); 1448 (void) strcat (hyphenated_word, "-"); 1449 if (syllable_length == 1) 1450 { 1451 symb2name(new_syllable, syllable_for_hyph); 1452 (void) strcat (hyphenated_word, syllable_for_hyph); 1453 } 1454 else 1455 { 1456 (void) strcat (hyphenated_word, new_syllable); 1457 } 1458 (void)memset ( (void *)new_syllable, 0, (size_t)(pwlen * sizeof(USHORT)+1)); 1459 (void)memset ( (void *)syllable_for_hyph, 0, 20); 1460 } 1461 word_length += syllable_length; 1462 } 1463 1464 /* 1465 * Keep track of the times we have tried to get 1466 * syllables. If we have exceeded the threshold, 1467 * reinitialize the pwlen and word_size variables, clear 1468 * out the word arrays, and start from scratch. 1469 */ 1470 tries++; 1471 if (tries > MAX_RETRIES) 1472 { 1473 word_length = 0; 1474 word_size = 0; 1475 tries = 0; 1476 (void) strcpy (word, ""); 1477 (void) strcpy (hyphenated_word, ""); 1478 } 1479 } 1480 1481 /* 1482 * The units arrays and syllable storage are internal to this 1483 * routine. Since the caller has no need for them, we 1484 * release the space. 1485 */ 1486 free ((char *) new_syllable); 1487 free ((char *) syllable_units); 1488 free ((char *) word_units); 1489 free ((char *) syllable_for_hyph); 1490 1491 return ((int) word_length); 1492 } 1493 1494 1495 1496 /* 1497 * Check that the word does not contain illegal combinations 1498 * that may span syllables. Specifically, these are: 1499 * 1. An illegal pair of units between syllables. 1500 * 2. Three consecutive vowel units. 1501 * 3. Three consecutive consonant units. 1502 * The checks are made against units (1 or 2 letters), not against 1503 * the individual letters, so three consecutive units can have 1504 * the length of 6 at most. 1505 */ 1506 boolean 1507 improper_word (USHORT *units, USHORT word_size) 1508 { 1509 USHORT unit_count; 1510 boolean failure; 1511 1512 failure = FALSE; 1513 1514 for (unit_count = 0; !failure && (unit_count < word_size); 1515 unit_count++) 1516 { 1517 /* 1518 * Check for ILLEGAL_PAIR. This should have been caught 1519 * for units within a syllable, but in some cases it 1520 * would have gone unnoticed for units between syllables 1521 * (e.g., when saved_unit's in gen_syllable() were not 1522 * used). 1523 */ 1524 if ((unit_count != 0) && 1525 (digram[units[unit_count - 1]][units[unit_count]] & 1526 ILLEGAL_PAIR)) 1527 failure = TRUE; 1528 1529 /* 1530 * Check for consecutive vowels or consonants. Because 1531 * the initial y of a syllable is treated as a consonant 1532 * rather than as a vowel, we exclude y from the first 1533 * vowel in the vowel test. The only problem comes when 1534 * y ends a syllable and two other vowels start the next, 1535 * like fly-oint. Since such words are still 1536 * pronounceable, we accept this. 1537 */ 1538 if (!failure && (unit_count >= 2)) 1539 { 1540 /* 1541 * Vowel check. 1542 */ 1543 if ((((rules[units[unit_count - 2]].flags & VOWEL) && 1544 !(rules[units[unit_count - 2]].flags & 1545 ALTERNATE_VOWEL)) && 1546 (rules[units[unit_count - 1]].flags & VOWEL) && 1547 (rules[units[unit_count]].flags & VOWEL)) || 1548 /* 1549 * Consonant check. 1550 */ 1551 (!(rules[units[unit_count - 2]].flags & VOWEL) && 1552 !(rules[units[unit_count - 1]].flags & VOWEL) && 1553 !(rules[units[unit_count]].flags & VOWEL))) 1554 failure = TRUE; 1555 } 1556 } 1557 1558 return (failure); 1559 } 1560 1561 1562 /* 1563 * Treating y as a vowel is sometimes a problem. Some words 1564 * get formed that look irregular. One special group is when 1565 * y starts a word and is the only vowel in the first syllable. 1566 * The word ycl is one example. We discard words like these. 1567 */ 1568 boolean 1569 have_initial_y (USHORT *units, USHORT unit_size) 1570 { 1571 USHORT unit_count; 1572 USHORT vowel_count; 1573 USHORT normal_vowel_count; 1574 1575 vowel_count = 0; 1576 normal_vowel_count = 0; 1577 1578 for (unit_count = 0; unit_count <= unit_size; unit_count++) 1579 /* 1580 * Count vowels. 1581 */ 1582 if (rules[units[unit_count]].flags & VOWEL) 1583 { 1584 vowel_count++; 1585 1586 /* 1587 * Count the vowels that are not: 1. y, 2. at the start of 1588 * the word. 1589 */ 1590 if (!(rules[units[unit_count]].flags & ALTERNATE_VOWEL) || 1591 (unit_count != 0)) 1592 normal_vowel_count++; 1593 } 1594 1595 return ((vowel_count <= 1) && (normal_vowel_count == 0)); 1596 } 1597 1598 1599 /* 1600 * Besides the problem with the letter y, there is one with 1601 * a silent e at the end of words, like face or nice. We 1602 * allow this silent e, but we do not allow it as the only 1603 * vowel at the end of the word or syllables like ble will 1604 * be generated. 1605 */ 1606 boolean 1607 have_final_split (USHORT *units, USHORT unit_size) 1608 { 1609 USHORT unit_count; 1610 USHORT vowel_count; 1611 1612 vowel_count = 0; 1613 1614 /* 1615 * Count all the vowels in the word. 1616 */ 1617 for (unit_count = 0; unit_count <= unit_size; unit_count++) 1618 if (rules[units[unit_count]].flags & VOWEL) 1619 vowel_count++; 1620 1621 /* 1622 * Return TRUE iff the only vowel was e, found at the end if the 1623 * word. 1624 */ 1625 return ((vowel_count == 1) && 1626 (rules[units[unit_size]].flags & NO_FINAL_SPLIT)); 1627 } 1628 1629 1630 /* 1631 * Generate next unit to password, making sure that it follows 1632 * these rules: 1633 * 1. Each syllable must contain exactly 1 or 2 consecutive 1634 * vowels, where y is considered a vowel. 1635 * 2. Syllable end is determined as follows: 1636 * a. Vowel is generated and previous unit is a 1637 * consonant and syllable already has a vowel. In 1638 * this case, new syllable is started and already 1639 * contains a vowel. 1640 * b. A pair determined to be a "break" pair is encountered. 1641 * In this case new syllable is started with second unit 1642 * of this pair. 1643 * c. End of password is encountered. 1644 * d. "begin" pair is encountered legally. New syllable is 1645 * started with this pair. 1646 * e. "end" pair is legally encountered. New syllable has 1647 * nothing yet. 1648 * 3. Try generating another unit if: 1649 * a. third consecutive vowel and not y. 1650 * b. "break" pair generated but no vowel yet in current 1651 * or previous 2 units are "not_end". 1652 * c. "begin" pair generated but no vowel in syllable 1653 * preceding begin pair, or both previous 2 pairs are 1654 * designated "not_end". 1655 * d. "end" pair generated but no vowel in current syllable 1656 * or in "end" pair. 1657 * e. "not_begin" pair generated but new syllable must 1658 * begin (because previous syllable ended as defined in 1659 * 2 above). 1660 * f. vowel is generated and 2a is satisfied, but no syllable 1661 * break is possible in previous 3 pairs. 1662 * g. Second and third units of syllable must begin, and 1663 * first unit is "alternate_vowel". 1664 */ 1665 char * 1666 gen_syllable (char *syllable, USHORT pwlen, USHORT *units_in_syllable, 1667 USHORT *syllable_length) 1668 { 1669 USHORT unit = 0; 1670 SHORT current_unit = 0; 1671 USHORT vowel_count = 0; 1672 boolean rule_broken; 1673 boolean want_vowel; 1674 boolean want_another_unit; 1675 UINT tries = 0; 1676 USHORT last_unit = 0; 1677 SHORT length_left = 0; 1678 USHORT hold_saved_unit = 0; 1679 static USHORT saved_unit; 1680 static USHORT saved_pair[2]; 1681 1682 /* 1683 * This is needed if the saved_unit is tries and the syllable then 1684 * discarded because of the retry limit. Since the saved_unit is OK and 1685 * fits in nicely with the preceding syllable, we will always use it. 1686 */ 1687 hold_saved_unit = saved_unit; 1688 1689 /* 1690 * Loop until valid syllable is found. 1691 */ 1692 do 1693 { 1694 /* 1695 * Try for a new syllable. Initialize all pertinent 1696 * syllable variables. 1697 */ 1698 tries = 0; 1699 saved_unit = hold_saved_unit; 1700 (void) strcpy (syllable, ""); 1701 vowel_count = 0; 1702 current_unit = 0; 1703 length_left = (short int) pwlen; 1704 want_another_unit = TRUE; 1705 1706 /* 1707 * This loop finds all the units for the syllable. 1708 */ 1709 do 1710 { 1711 want_vowel = FALSE; 1712 1713 /* 1714 * This loop continues until a valid unit is found for the 1715 * current position within the syllable. 1716 */ 1717 do 1718 { 1719 /* 1720 * If there are saved_unit's from the previous 1721 * syllable, use them up first. 1722 */ 1723 if (saved_unit != 0) 1724 { 1725 /* 1726 * If there were two saved units, the first is 1727 * guaranteed (by checks performed in the previous 1728 * syllable) to be valid. We ignore the checks 1729 * and place it in this syllable manually. 1730 */ 1731 if (saved_unit == 2) 1732 { 1733 units_in_syllable[0] = saved_pair[1]; 1734 if (rules[saved_pair[1]].flags & VOWEL) 1735 vowel_count++; 1736 current_unit++; 1737 (void) strcpy (syllable, rules[saved_pair[1]].unit_code); 1738 length_left -= (short) strlen (syllable); 1739 } 1740 1741 /* 1742 * The unit becomes the last unit checked in the 1743 * previous syllable. 1744 */ 1745 unit = saved_pair[0]; 1746 1747 /* 1748 * The saved units have been used. Do not try to 1749 * reuse them in this syllable (unless this particular 1750 * syllable is rejected at which point we start to rebuild 1751 * it with these same saved units. 1752 */ 1753 saved_unit = 0; 1754 } 1755 else 1756 /* 1757 * If we don't have to scoff the saved units, 1758 * we generate a Random one. If we know it has 1759 * to be a vowel, we get one rather than looping 1760 * through until one shows up. 1761 */ 1762 if (want_vowel) 1763 unit = random_unit (VOWEL); 1764 else 1765 unit = random_unit (NO_SPECIAL_RULE); 1766 length_left -= (short int) strlen (rules[unit].unit_code); 1767 1768 /* 1769 * Prevent having a word longer than expected. 1770 */ 1771 if (length_left < 0) 1772 rule_broken = TRUE; 1773 else 1774 rule_broken = FALSE; 1775 1776 /* 1777 * First unit of syllable. This is special because the 1778 * digram tests require 2 units and we don't have that yet. 1779 * Nevertheless, we can perform some checks. 1780 */ 1781 if (current_unit == 0) 1782 { 1783 /* 1784 * If the shouldn't begin a syllable, don't 1785 * use it. 1786 */ 1787 if (rules[unit].flags & NOT_BEGIN_SYLLABLE) 1788 rule_broken = TRUE; 1789 else 1790 /* 1791 * If this is the last unit of a word, 1792 * we have a one unit syllable. Since each 1793 * syllable must have a vowel, we make sure 1794 * the unit is a vowel. Otherwise, we 1795 * discard it. 1796 */ 1797 if (length_left == 0) 1798 { 1799 if (rules[unit].flags & VOWEL) 1800 want_another_unit = FALSE; 1801 else 1802 rule_broken = TRUE; 1803 } 1804 } 1805 else 1806 { 1807 /* 1808 * There are some digram tests that are 1809 * universally true. We test them out. 1810 */ 1811 1812 /* 1813 * Reject ILLEGAL_PAIRS of units. 1814 */ 1815 if ((ALLOWED (ILLEGAL_PAIR)) || 1816 1817 /* 1818 * Reject units that will be split between syllables 1819 * when the syllable has no vowels in it. 1820 */ 1821 (ALLOWED (BREAK) && (vowel_count == 0)) || 1822 1823 /* 1824 * Reject a unit that will end a syllable when no 1825 * previous unit was a vowel and neither is this one. 1826 */ 1827 (ALLOWED (END) && (vowel_count == 0) && 1828 !(rules[unit].flags & VOWEL))) 1829 rule_broken = TRUE; 1830 1831 if (current_unit == 1) 1832 { 1833 /* 1834 * Reject the unit if we are at te starting digram of 1835 * a syllable and it does not fit. 1836 */ 1837 if (ALLOWED (NOT_BEGIN)) 1838 rule_broken = TRUE; 1839 } 1840 else 1841 { 1842 /* 1843 * We are not at the start of a syllable. 1844 * Save the previous unit for later tests. 1845 */ 1846 last_unit = units_in_syllable[current_unit - 1]; 1847 1848 /* 1849 * Do not allow syllables where the first letter is y 1850 * and the next pair can begin a syllable. This may 1851 * lead to splits where y is left alone in a syllable. 1852 * Also, the combination does not sound to good even 1853 * if not split. 1854 */ 1855 if (((current_unit == 2) && 1856 (ALLOWED (BEGIN)) && 1857 (rules[units_in_syllable[0]].flags & 1858 ALTERNATE_VOWEL)) || 1859 1860 /* 1861 * If this is the last unit of a word, we should 1862 * reject any digram that cannot end a syllable. 1863 */ 1864 (ALLOWED (NOT_END) && 1865 (length_left == 0)) || 1866 1867 /* 1868 * Reject the unit if the digram it forms wants 1869 * to break the syllable, but the resulting 1870 * digram that would end the syllable is not 1871 * allowed to end a syllable. 1872 */ 1873 (ALLOWED (BREAK) && 1874 (digram[units_in_syllable 1875 [current_unit - 2]] 1876 [last_unit] & 1877 NOT_END)) || 1878 1879 /* 1880 * Reject the unit if the digram it forms 1881 * expects a vowel preceding it and there is 1882 * none. 1883 */ 1884 (ALLOWED (PREFIX) && 1885 !(rules[units_in_syllable 1886 [current_unit - 2]].flags & 1887 VOWEL))) 1888 rule_broken = TRUE; 1889 1890 /* 1891 * The following checks occur when the current unit 1892 * is a vowel and we are not looking at a word ending 1893 * with an e. 1894 */ 1895 if (!rule_broken && 1896 (rules[unit].flags & VOWEL) && 1897 ((length_left > 0) || 1898 !(rules[last_unit].flags & 1899 NO_FINAL_SPLIT))) 1900 { 1901 /* 1902 * Don't allow 3 consecutive vowels in a 1903 * syllable. Although some words formed like this 1904 * are OK, like beau, most are not. 1905 */ 1906 if ((vowel_count > 1) && 1907 (rules[last_unit].flags & VOWEL)) 1908 rule_broken = TRUE; 1909 else 1910 /* 1911 * Check for the case of 1912 * vowels-consonants-vowel, which is only 1913 * legal if the last vowel is an e and we are 1914 * the end of the word (wich is not 1915 * happening here due to a previous check. 1916 */ 1917 if ((vowel_count != 0) && 1918 !(rules[last_unit].flags & VOWEL)) 1919 { 1920 /* 1921 * Try to save the vowel for the next 1922 * syllable, but if the syllable left here 1923 * is not proper (i.e., the resulting last 1924 * digram cannot legally end it), just 1925 * discard it and try for another. 1926 */ 1927 if (digram[units_in_syllable 1928 [current_unit - 2]] 1929 [last_unit] & 1930 NOT_END) 1931 rule_broken = TRUE; 1932 else 1933 { 1934 saved_unit = 1; 1935 saved_pair[0] = unit; 1936 want_another_unit = FALSE; 1937 } 1938 } 1939 } 1940 } 1941 1942 /* 1943 * The unit picked and the digram formed are legal. 1944 * We now determine if we can end the syllable. It may, 1945 * in some cases, mean the last unit(s) may be deferred to 1946 * the next syllable. We also check here to see if the 1947 * digram formed expects a vowel to follow. 1948 */ 1949 if (!rule_broken && want_another_unit) 1950 { 1951 /* 1952 * This word ends in a silent e. 1953 */ 1954 /******/ if (((vowel_count != 0) && 1955 (rules[unit].flags & NO_FINAL_SPLIT) && 1956 (length_left == 0) && 1957 !(rules[last_unit].flags & VOWEL)) || 1958 1959 /* 1960 * This syllable ends either because the digram 1961 * is an END pair or we would otherwise exceed 1962 * the length of the word. 1963 */ 1964 (ALLOWED (END) || (length_left == 0))) 1965 { 1966 want_another_unit = FALSE; 1967 } 1968 else 1969 /* 1970 * Since we have a vowel in the syllable 1971 * already, if the digram calls for the end of the 1972 * syllable, we can legally split it off. We also 1973 * make sure that we are not at the end of the 1974 * dangerous because that syllable may not have 1975 * vowels, or it may not be a legal syllable end, 1976 * and the retrying mechanism will loop infinitely 1977 * with the same digram. 1978 */ 1979 if ((vowel_count != 0) && (length_left > 0)) 1980 { 1981 /* 1982 * If we must begin a syllable, we do so if 1983 * the only vowel in THIS syllable is not part 1984 * of the digram we are pushing to the next 1985 * syllable. 1986 */ 1987 if (ALLOWED (BEGIN) && 1988 (current_unit > 1) && 1989 !((vowel_count == 1) && 1990 (rules[last_unit].flags & VOWEL))) 1991 { 1992 saved_unit = 2; 1993 saved_pair[0] = unit; 1994 saved_pair[1] = last_unit; 1995 want_another_unit = FALSE; 1996 } 1997 else 1998 if (ALLOWED (BREAK)) 1999 { 2000 saved_unit = 1; 2001 saved_pair[0] = unit; 2002 want_another_unit = FALSE; 2003 } 2004 } 2005 else 2006 if (ALLOWED (SUFFIX)) 2007 { 2008 want_vowel = TRUE; 2009 } 2010 } 2011 } 2012 /********/ 2013 tries++; 2014 2015 /* 2016 * If this unit was illegal, redetermine the amount of 2017 * letters left to go in the word. 2018 */ 2019 if (rule_broken) 2020 length_left += (short int) strlen (rules[unit].unit_code); 2021 } 2022 while (rule_broken && (tries <= MAX_RETRIES)); 2023 2024 /* 2025 * The unit fit OK. 2026 */ 2027 if (tries <= MAX_RETRIES) 2028 { 2029 /* 2030 * If the unit were a vowel, count it in. 2031 * However, if the unit were a y and appear 2032 * at the start of the syllable, treat it 2033 * like a constant (so that words like year can 2034 * appear and not conflict with the 3 consecutive 2035 * vowel rule. 2036 */ 2037 if ((rules[unit].flags & VOWEL) && 2038 ((current_unit > 0) || 2039 !(rules[unit].flags & ALTERNATE_VOWEL))) 2040 vowel_count++; 2041 2042 /* 2043 * If a unit or units were to be saved, we must 2044 * adjust the syllable formed. Otherwise, we 2045 * append the current unit to the syllable. 2046 */ 2047 switch (saved_unit) 2048 { 2049 case 0: 2050 units_in_syllable[current_unit] = unit; 2051 (void) strcat (syllable, rules[unit].unit_code); 2052 break; 2053 case 1: 2054 current_unit--; 2055 break; 2056 case 2: 2057 (void) strcpy (&syllable[strlen (syllable) - 2058 strlen (rules[last_unit].unit_code)],""); 2059 length_left += (short int) strlen (rules[last_unit].unit_code); 2060 current_unit -= 2; 2061 break; 2062 } 2063 } 2064 else 2065 /* 2066 * Whoops! Too many tries. We set rule_broken so we can 2067 * loop in the outer loop and try another syllable. 2068 */ 2069 rule_broken = TRUE; 2070 2071 /* 2072 * ...and the syllable length grows. 2073 */ 2074 *syllable_length = current_unit; 2075 2076 current_unit++; 2077 } 2078 while ((tries <= MAX_RETRIES) && want_another_unit); 2079 } 2080 while (rule_broken || 2081 illegal_placement (units_in_syllable, *syllable_length)); 2082 2083 return (syllable); 2084 } 2085 2086 2087 /* 2088 * This routine goes through an individual syllable and checks 2089 * for illegal combinations of letters that go beyond looking 2090 * at digrams. We look at things like 3 consecutive vowels or 2091 * consonants, or syllables with consonants between vowels (unless 2092 * one of them is the final silent e). 2093 */ 2094 boolean 2095 illegal_placement (USHORT *units, USHORT pwlen) 2096 { 2097 USHORT vowel_count; 2098 USHORT unit_count; 2099 boolean failure; 2100 2101 vowel_count = 0; 2102 failure = FALSE; 2103 2104 for (unit_count = 0; !failure && (unit_count <= pwlen); 2105 unit_count++) 2106 { 2107 if (unit_count >= 1) 2108 { 2109 /* 2110 * Don't allow vowels to be split with consonants in 2111 * a single syllable. If we find such a combination 2112 * (except for the silent e) we have to discard the 2113 * syllable). 2114 */ 2115 if ((!(rules[units[unit_count - 1]].flags & VOWEL) && 2116 (rules[units[unit_count]].flags & VOWEL) && 2117 !((rules[units[unit_count]].flags & NO_FINAL_SPLIT) && 2118 (unit_count == pwlen)) && (vowel_count != 0)) || 2119 /* 2120 * Perform these checks when we have at least 3 units. 2121 */ 2122 ((unit_count >= 2) && 2123 2124 /* 2125 * Disallow 3 consecutive consonants. 2126 */ 2127 ((!(rules[units[unit_count - 2]].flags & VOWEL) && 2128 !(rules[units[unit_count - 1]].flags & 2129 VOWEL) && 2130 !(rules[units[unit_count]].flags & 2131 VOWEL)) || 2132 2133 /* 2134 * Disallow 3 consecutive vowels, where the first is 2135 * not a y. 2136 */ 2137 (((rules[units[unit_count - 2]].flags & 2138 VOWEL) && 2139 !((rules[units[0]].flags & 2140 ALTERNATE_VOWEL) && 2141 (unit_count == 2))) && 2142 (rules[units[unit_count - 1]].flags & 2143 VOWEL) && 2144 (rules[units[unit_count]].flags & 2145 VOWEL))))) 2146 failure = TRUE; 2147 } 2148 2149 /* 2150 * Count the vowels in the syllable. As mentioned somewhere 2151 * above, exclude the initial y of a syllable. Instead, 2152 * treat it as a consonant. 2153 */ 2154 if ((rules[units[unit_count]].flags & VOWEL) && 2155 !((rules[units[0]].flags & ALTERNATE_VOWEL) && 2156 (unit_count == 0) && (pwlen != 0))) 2157 vowel_count++; 2158 } 2159 2160 return (failure); 2161 } 2162 2163 2164 2165 /* 2166 * This is the standard Random unit generating routine for 2167 * gen_syllable(). It does not reference the digrams, but 2168 * assumes that it contains 34 units in a particular order. 2169 * This routine attempts to return unit indexes with a distribution 2170 * approaching that of the distribution of the 34 units in 2171 * English. In order to do this, a Random number (supposedly 2172 * uniformly distributed) is used to do a table lookup into an 2173 * array containing unit indices. There are 211 entries in 2174 * the array for the random_unit entry point. The probability 2175 * of a particular unit being generated is equal to the 2176 * fraction of those 211 entries that contain that unit index. 2177 * For example, the letter `a' is unit number 1. Since unit 2178 * index 1 appears 10 times in the array, the probability of 2179 * selecting an `a' is 10/211. 2180 * 2181 * Changes may be made to the digram table without affect to this 2182 * procedure providing the letter-to-number correspondence of 2183 * the units does not change. Likewise, the distribution of the 2184 * 34 units may be altered (and the array size may be changed) 2185 * in this procedure without affecting the digram table or any other 2186 * programs using the Random_word subroutine. 2187 */ 2188 static USHORT numbers[] = 2189 { 2190 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2191 1, 1, 1, 1, 1, 1, 1, 1, 2192 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2193 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2194 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2195 5, 5, 5, 5, 5, 5, 5, 5, 2196 6, 6, 6, 6, 6, 6, 6, 6, 2197 7, 7, 7, 7, 7, 7, 2198 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2199 9, 9, 9, 9, 9, 9, 9, 9, 2200 10, 10, 10, 10, 10, 10, 10, 10, 2201 11, 11, 11, 11, 11, 11, 2202 12, 12, 12, 12, 12, 12, 2203 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2204 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 2205 15, 15, 15, 15, 15, 15, 2206 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2207 17, 17, 17, 17, 17, 17, 17, 17, 2208 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 2209 19, 19, 19, 19, 19, 19, 2210 20, 20, 20, 20, 20, 20, 20, 20, 2211 21, 21, 21, 21, 21, 21, 21, 21, 2212 22, 2213 23, 23, 23, 23, 23, 23, 23, 23, 2214 24, 2215 25, 2216 26, 2217 27, 2218 28, 2219 29, 29, 2220 30, 2221 31, 2222 32, 2223 33 2224 }; 2225 2226 2227 /* 2228 * This structure has a typical English frequency of vowels. 2229 * The value of an entry is the vowel position (a=0, e=4, i=8, 2230 * o=14, u=19, y=23) in the rules array. The number of times 2231 * the value appears is the frequency. Thus, the letter "a" 2232 * is assumed to appear 2/12 = 1/6 of the time. This array 2233 * may be altered if better data is obtained. The routines that 2234 * use vowel_numbers will adjust to the size difference 2235 automatically. 2236 */ 2237 static USHORT vowel_numbers[] = 2238 { 2239 0, 0, 4, 4, 4, 8, 8, 14, 14, 19, 19, 23 2240 }; 2241 2242 2243 /* 2244 * Select a unit (a letter or a consonant group). If a vowel is 2245 * expected, use the vowel_numbers array rather than looping through 2246 * the numbers array until a vowel is found. 2247 */ 2248 USHORT 2249 random_unit (USHORT type) 2250 { 2251 USHORT number; 2252 2253 /* 2254 * Sometimes, we are asked to explicitly get a vowel (i.e., if 2255 * a digram pair expects one following it). This is a shortcut 2256 * to do that and avoid looping with rejected consonants. 2257 */ 2258 if (type & VOWEL) 2259 number = vowel_numbers[ 2260 base::RandInt(0, (sizeof (vowel_numbers) / sizeof (USHORT))-1)]; 2261 else 2262 /* 2263 * Get any letter according to the English distribution. 2264 */ 2265 number = numbers[ 2266 base::RandInt(0, (sizeof (numbers) / sizeof (USHORT))-1)]; 2267 return (number); 2268 } 2269