"Fossies" - the Fresh Open Source Software Archive 
Member "apg-2.2.3/pronpass.c" (7 Aug 2003, 79621 Bytes) of package /linux/privat/old/apg-2.2.3.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
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 "pronpass.h"
46 #include "randpass.h"
47 #include "convert.h"
48 #include "errs.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, get_random (minlen, maxlen), pass_mode);
1297 return (pwlen);
1298 }
1299
1300
1301 /*
1302 * This is the routine that returns a Random word -- as
1303 * yet unchecked against the passwd file or the dictionary.
1304 * It collects Random syllables until a predetermined
1305 * word length is found. If a retry threshold is reached,
1306 * another word is tried. Given that the Random number
1307 * generator is uniformly distributed, eventually a word
1308 * will be found if the retry limit is adequately large enough.
1309 */
1310 int
1311 gen_word (char *word, char *hyphenated_word, USHORT pwlen, unsigned int pass_mode)
1312 {
1313 USHORT word_length;
1314 USHORT syllable_length;
1315 char *new_syllable;
1316 char *syllable_for_hyph;
1317 USHORT *syllable_units;
1318 USHORT word_size;
1319 USHORT word_place;
1320 USHORT *word_units;
1321 USHORT syllable_size;
1322 UINT tries;
1323 int ch_flag = FALSE;
1324 int dsd = 0;
1325
1326 /*
1327 * Keep count of retries.
1328 */
1329 tries = 0;
1330
1331 /*
1332 * The length of the word in characters.
1333 */
1334 word_length = 0;
1335
1336 /*
1337 * The length of the word in character units (each of which is one or
1338 * two characters long.
1339 */
1340 word_size = 0;
1341
1342 /*
1343 * Initialize the array storing the word units. Since we know the
1344 * length of the word, we only need one of that length. This method is
1345 * preferable to a static array, since it allows us flexibility in
1346 * choosing arbitrarily long word lengths. Since a word can contain one
1347 * syllable, we should make syllable_units, the array holding the
1348 * analogous units for an individual syllable, the same length. No
1349 * explicit rule limits the length of syllables, but digram rules and
1350 * heuristics do so indirectly.
1351 */
1352 if ( (word_units = (USHORT *) calloc (sizeof (USHORT), pwlen+1))==NULL ||
1353 (syllable_units = (USHORT *) calloc (sizeof (USHORT), pwlen+1))==NULL ||
1354 (new_syllable = (char *) calloc (sizeof (USHORT), pwlen+1)) ==NULL ||
1355 (syllable_for_hyph = (char *) calloc (sizeof(char), 20))==NULL)
1356 return(-1);
1357
1358 /*
1359 * Find syllables until the entire word is constructed.
1360 */
1361 while (word_length < pwlen)
1362 {
1363 /*
1364 * Get the syllable and find its length.
1365 */
1366 (void) gen_syllable (new_syllable, pwlen - word_length, syllable_units, &syllable_size);
1367 syllable_length = strlen (new_syllable);
1368
1369 /*
1370 * Append the syllable units to the word units.
1371 */
1372 for (word_place = 0; word_place <= syllable_size; word_place++)
1373 word_units[word_size + word_place] = syllable_units[word_place];
1374 word_size += syllable_size + 1;
1375
1376 /*
1377 * If the word has been improperly formed, throw out
1378 * the syllable. The checks performed here are those
1379 * that must be formed on a word basis. The other
1380 * tests are performed entirely within the syllable.
1381 * Otherwise, append the syllable to the word and
1382 * append the syllable to the hyphenated version of
1383 * the word.
1384 */
1385 if (improper_word (word_units, word_size) ||
1386 ((word_length == 0) && have_initial_y (syllable_units, syllable_size)) ||
1387 ((word_length + syllable_length == pwlen) && have_final_split (syllable_units, syllable_size)))
1388 word_size -= syllable_size + 1;
1389 else
1390 {
1391 if (word_length == 0)
1392 {
1393 /*
1394 ** Modify syllable for numeric or capital symbols required
1395 ** Should be done after word quality check.
1396 */
1397 dsd = randint(2);
1398 if ( ((pass_mode & S_NB) > 0) && (syllable_length == 1) && dsd == 0)
1399 {
1400 numerize(new_syllable);
1401 ch_flag = TRUE;
1402 }
1403 if ( ((pass_mode & S_SS) > 0) && (syllable_length == 1) && (dsd == 1))
1404 {
1405 specialize(new_syllable);
1406 ch_flag = TRUE;
1407 }
1408 if ( ( (pass_mode & S_CL) > 0) && (ch_flag != TRUE))
1409 capitalize(new_syllable);
1410 ch_flag = FALSE;
1411 /**/
1412 (void) strcpy (word, new_syllable);
1413 if (syllable_length == 1)
1414 {
1415 symb2name(new_syllable, syllable_for_hyph);
1416 (void) strcpy (hyphenated_word, syllable_for_hyph);
1417 }
1418 else
1419 {
1420 (void) strcpy (hyphenated_word, new_syllable);
1421 }
1422 (void)memset ( (void *)new_syllable, 0, (size_t)(pwlen * sizeof(USHORT)+1));
1423 (void)memset ( (void *)syllable_for_hyph, 0, 20);
1424 }
1425 else
1426 {
1427 /*
1428 ** Modify syllable for numeric or capital symbols required
1429 ** Should be done after word quality check.
1430 */
1431 dsd = randint(2);
1432 if ( ((pass_mode & S_NB) > 0) && (syllable_length == 1) && (dsd == 0))
1433 {
1434 numerize(new_syllable);
1435 ch_flag = TRUE;
1436 }
1437 if ( ( (pass_mode & S_SS) > 0) && (syllable_length == 1) && (dsd == 1))
1438 {
1439 specialize(new_syllable);
1440 ch_flag = TRUE;
1441 }
1442 if ( ( (pass_mode & S_CL) > 0) && (ch_flag != TRUE))
1443 capitalize(new_syllable);
1444 ch_flag = FALSE;
1445 /**/
1446 (void) strcat (word, new_syllable);
1447 (void) strcat (hyphenated_word, "-");
1448 if (syllable_length == 1)
1449 {
1450 symb2name(new_syllable, syllable_for_hyph);
1451 (void) strcat (hyphenated_word, syllable_for_hyph);
1452 }
1453 else
1454 {
1455 (void) strcat (hyphenated_word, new_syllable);
1456 }
1457 (void)memset ( (void *)new_syllable, 0, (size_t)(pwlen * sizeof(USHORT)+1));
1458 (void)memset ( (void *)syllable_for_hyph, 0, 20);
1459 }
1460 word_length += syllable_length;
1461 }
1462
1463 /*
1464 * Keep track of the times we have tried to get
1465 * syllables. If we have exceeded the threshold,
1466 * reinitialize the pwlen and word_size variables, clear
1467 * out the word arrays, and start from scratch.
1468 */
1469 tries++;
1470 if (tries > MAX_RETRIES)
1471 {
1472 word_length = 0;
1473 word_size = 0;
1474 tries = 0;
1475 (void) strcpy (word, "");
1476 (void) strcpy (hyphenated_word, "");
1477 }
1478 }
1479
1480 /*
1481 * The units arrays and syllable storage are internal to this
1482 * routine. Since the caller has no need for them, we
1483 * release the space.
1484 */
1485 free ((char *) new_syllable);
1486 free ((char *) syllable_units);
1487 free ((char *) word_units);
1488 free ((char *) syllable_for_hyph);
1489
1490 return ((int) word_length);
1491 }
1492
1493
1494
1495 /*
1496 * Check that the word does not contain illegal combinations
1497 * that may span syllables. Specifically, these are:
1498 * 1. An illegal pair of units between syllables.
1499 * 2. Three consecutive vowel units.
1500 * 3. Three consecutive consonant units.
1501 * The checks are made against units (1 or 2 letters), not against
1502 * the individual letters, so three consecutive units can have
1503 * the length of 6 at most.
1504 */
1505 boolean
1506 improper_word (USHORT *units, USHORT word_size)
1507 {
1508 USHORT unit_count;
1509 boolean failure;
1510
1511 failure = FALSE;
1512
1513 for (unit_count = 0; !failure && (unit_count < word_size);
1514 unit_count++)
1515 {
1516 /*
1517 * Check for ILLEGAL_PAIR. This should have been caught
1518 * for units within a syllable, but in some cases it
1519 * would have gone unnoticed for units between syllables
1520 * (e.g., when saved_unit's in gen_syllable() were not
1521 * used).
1522 */
1523 if ((unit_count != 0) &&
1524 (digram[units[unit_count - 1]][units[unit_count]] &
1525 ILLEGAL_PAIR))
1526 failure = TRUE;
1527
1528 /*
1529 * Check for consecutive vowels or consonants. Because
1530 * the initial y of a syllable is treated as a consonant
1531 * rather than as a vowel, we exclude y from the first
1532 * vowel in the vowel test. The only problem comes when
1533 * y ends a syllable and two other vowels start the next,
1534 * like fly-oint. Since such words are still
1535 * pronounceable, we accept this.
1536 */
1537 if (!failure && (unit_count >= 2))
1538 {
1539 /*
1540 * Vowel check.
1541 */
1542 if ((((rules[units[unit_count - 2]].flags & VOWEL) &&
1543 !(rules[units[unit_count - 2]].flags &
1544 ALTERNATE_VOWEL)) &&
1545 (rules[units[unit_count - 1]].flags & VOWEL) &&
1546 (rules[units[unit_count]].flags & VOWEL)) ||
1547 /*
1548 * Consonant check.
1549 */
1550 (!(rules[units[unit_count - 2]].flags & VOWEL) &&
1551 !(rules[units[unit_count - 1]].flags & VOWEL) &&
1552 !(rules[units[unit_count]].flags & VOWEL)))
1553 failure = TRUE;
1554 }
1555 }
1556
1557 return (failure);
1558 }
1559
1560
1561 /*
1562 * Treating y as a vowel is sometimes a problem. Some words
1563 * get formed that look irregular. One special group is when
1564 * y starts a word and is the only vowel in the first syllable.
1565 * The word ycl is one example. We discard words like these.
1566 */
1567 boolean
1568 have_initial_y (USHORT *units, USHORT unit_size)
1569 {
1570 USHORT unit_count;
1571 USHORT vowel_count;
1572 USHORT normal_vowel_count;
1573
1574 vowel_count = 0;
1575 normal_vowel_count = 0;
1576
1577 for (unit_count = 0; unit_count <= unit_size; unit_count++)
1578 /*
1579 * Count vowels.
1580 */
1581 if (rules[units[unit_count]].flags & VOWEL)
1582 {
1583 vowel_count++;
1584
1585 /*
1586 * Count the vowels that are not: 1. y, 2. at the start of
1587 * the word.
1588 */
1589 if (!(rules[units[unit_count]].flags & ALTERNATE_VOWEL) ||
1590 (unit_count != 0))
1591 normal_vowel_count++;
1592 }
1593
1594 return ((vowel_count <= 1) && (normal_vowel_count == 0));
1595 }
1596
1597
1598 /*
1599 * Besides the problem with the letter y, there is one with
1600 * a silent e at the end of words, like face or nice. We
1601 * allow this silent e, but we do not allow it as the only
1602 * vowel at the end of the word or syllables like ble will
1603 * be generated.
1604 */
1605 boolean
1606 have_final_split (USHORT *units, USHORT unit_size)
1607 {
1608 USHORT unit_count;
1609 USHORT vowel_count;
1610
1611 vowel_count = 0;
1612
1613 /*
1614 * Count all the vowels in the word.
1615 */
1616 for (unit_count = 0; unit_count <= unit_size; unit_count++)
1617 if (rules[units[unit_count]].flags & VOWEL)
1618 vowel_count++;
1619
1620 /*
1621 * Return TRUE iff the only vowel was e, found at the end if the
1622 * word.
1623 */
1624 return ((vowel_count == 1) &&
1625 (rules[units[unit_size]].flags & NO_FINAL_SPLIT));
1626 }
1627
1628
1629 /*
1630 * Generate next unit to password, making sure that it follows
1631 * these rules:
1632 * 1. Each syllable must contain exactly 1 or 2 consecutive
1633 * vowels, where y is considered a vowel.
1634 * 2. Syllable end is determined as follows:
1635 * a. Vowel is generated and previous unit is a
1636 * consonant and syllable already has a vowel. In
1637 * this case, new syllable is started and already
1638 * contains a vowel.
1639 * b. A pair determined to be a "break" pair is encountered.
1640 * In this case new syllable is started with second unit
1641 * of this pair.
1642 * c. End of password is encountered.
1643 * d. "begin" pair is encountered legally. New syllable is
1644 * started with this pair.
1645 * e. "end" pair is legally encountered. New syllable has
1646 * nothing yet.
1647 * 3. Try generating another unit if:
1648 * a. third consecutive vowel and not y.
1649 * b. "break" pair generated but no vowel yet in current
1650 * or previous 2 units are "not_end".
1651 * c. "begin" pair generated but no vowel in syllable
1652 * preceding begin pair, or both previous 2 pairs are
1653 * designated "not_end".
1654 * d. "end" pair generated but no vowel in current syllable
1655 * or in "end" pair.
1656 * e. "not_begin" pair generated but new syllable must
1657 * begin (because previous syllable ended as defined in
1658 * 2 above).
1659 * f. vowel is generated and 2a is satisfied, but no syllable
1660 * break is possible in previous 3 pairs.
1661 * g. Second and third units of syllable must begin, and
1662 * first unit is "alternate_vowel".
1663 */
1664 char *
1665 gen_syllable (char *syllable, USHORT pwlen, USHORT *units_in_syllable,
1666 USHORT *syllable_length)
1667 {
1668 USHORT unit = 0;
1669 SHORT current_unit = 0;
1670 USHORT vowel_count = 0;
1671 boolean rule_broken;
1672 boolean want_vowel;
1673 boolean want_another_unit;
1674 UINT tries = 0;
1675 USHORT last_unit = 0;
1676 SHORT length_left = 0;
1677 USHORT hold_saved_unit = 0;
1678 static USHORT saved_unit;
1679 static USHORT saved_pair[2];
1680
1681 /*
1682 * This is needed if the saved_unit is tries and the syllable then
1683 * discarded because of the retry limit. Since the saved_unit is OK and
1684 * fits in nicely with the preceding syllable, we will always use it.
1685 */
1686 hold_saved_unit = saved_unit;
1687
1688 /*
1689 * Loop until valid syllable is found.
1690 */
1691 do
1692 {
1693 /*
1694 * Try for a new syllable. Initialize all pertinent
1695 * syllable variables.
1696 */
1697 tries = 0;
1698 saved_unit = hold_saved_unit;
1699 (void) strcpy (syllable, "");
1700 vowel_count = 0;
1701 current_unit = 0;
1702 length_left = (short int) pwlen;
1703 want_another_unit = TRUE;
1704
1705 /*
1706 * This loop finds all the units for the syllable.
1707 */
1708 do
1709 {
1710 want_vowel = FALSE;
1711
1712 /*
1713 * This loop continues until a valid unit is found for the
1714 * current position within the syllable.
1715 */
1716 do
1717 {
1718 /*
1719 * If there are saved_unit's from the previous
1720 * syllable, use them up first.
1721 */
1722 if (saved_unit != 0)
1723 {
1724 /*
1725 * If there were two saved units, the first is
1726 * guaranteed (by checks performed in the previous
1727 * syllable) to be valid. We ignore the checks
1728 * and place it in this syllable manually.
1729 */
1730 if (saved_unit == 2)
1731 {
1732 units_in_syllable[0] = saved_pair[1];
1733 if (rules[saved_pair[1]].flags & VOWEL)
1734 vowel_count++;
1735 current_unit++;
1736 (void) strcpy (syllable, rules[saved_pair[1]].unit_code);
1737 length_left -= strlen (syllable);
1738 }
1739
1740 /*
1741 * The unit becomes the last unit checked in the
1742 * previous syllable.
1743 */
1744 unit = saved_pair[0];
1745
1746 /*
1747 * The saved units have been used. Do not try to
1748 * reuse them in this syllable (unless this particular
1749 * syllable is rejected at which point we start to rebuild
1750 * it with these same saved units.
1751 */
1752 saved_unit = 0;
1753 }
1754 else
1755 /*
1756 * If we don't have to scoff the saved units,
1757 * we generate a Random one. If we know it has
1758 * to be a vowel, we get one rather than looping
1759 * through until one shows up.
1760 */
1761 if (want_vowel)
1762 unit = random_unit (VOWEL);
1763 else
1764 unit = random_unit (NO_SPECIAL_RULE);
1765 length_left -= (short int) strlen (rules[unit].unit_code);
1766
1767 /*
1768 * Prevent having a word longer than expected.
1769 */
1770 if (length_left < 0)
1771 rule_broken = TRUE;
1772 else
1773 rule_broken = FALSE;
1774
1775 /*
1776 * First unit of syllable. This is special because the
1777 * digram tests require 2 units and we don't have that yet.
1778 * Nevertheless, we can perform some checks.
1779 */
1780 if (current_unit == 0)
1781 {
1782 /*
1783 * If the shouldn't begin a syllable, don't
1784 * use it.
1785 */
1786 if (rules[unit].flags & NOT_BEGIN_SYLLABLE)
1787 rule_broken = TRUE;
1788 else
1789 /*
1790 * If this is the last unit of a word,
1791 * we have a one unit syllable. Since each
1792 * syllable must have a vowel, we make sure
1793 * the unit is a vowel. Otherwise, we
1794 * discard it.
1795 */
1796 if (length_left == 0)
1797 {
1798 if (rules[unit].flags & VOWEL)
1799 want_another_unit = FALSE;
1800 else
1801 rule_broken = TRUE;
1802 }
1803 }
1804 else
1805 {
1806 /*
1807 * There are some digram tests that are
1808 * universally true. We test them out.
1809 */
1810
1811 /*
1812 * Reject ILLEGAL_PAIRS of units.
1813 */
1814 if ((ALLOWED (ILLEGAL_PAIR)) ||
1815
1816 /*
1817 * Reject units that will be split between syllables
1818 * when the syllable has no vowels in it.
1819 */
1820 (ALLOWED (BREAK) && (vowel_count == 0)) ||
1821
1822 /*
1823 * Reject a unit that will end a syllable when no
1824 * previous unit was a vowel and neither is this one.
1825 */
1826 (ALLOWED (END) && (vowel_count == 0) &&
1827 !(rules[unit].flags & VOWEL)))
1828 rule_broken = TRUE;
1829
1830 if (current_unit == 1)
1831 {
1832 /*
1833 * Reject the unit if we are at te starting digram of
1834 * a syllable and it does not fit.
1835 */
1836 if (ALLOWED (NOT_BEGIN))
1837 rule_broken = TRUE;
1838 }
1839 else
1840 {
1841 /*
1842 * We are not at the start of a syllable.
1843 * Save the previous unit for later tests.
1844 */
1845 last_unit = units_in_syllable[current_unit - 1];
1846
1847 /*
1848 * Do not allow syllables where the first letter is y
1849 * and the next pair can begin a syllable. This may
1850 * lead to splits where y is left alone in a syllable.
1851 * Also, the combination does not sound to good even
1852 * if not split.
1853 */
1854 if (((current_unit == 2) &&
1855 (ALLOWED (BEGIN)) &&
1856 (rules[units_in_syllable[0]].flags &
1857 ALTERNATE_VOWEL)) ||
1858
1859 /*
1860 * If this is the last unit of a word, we should
1861 * reject any digram that cannot end a syllable.
1862 */
1863 (ALLOWED (NOT_END) &&
1864 (length_left == 0)) ||
1865
1866 /*
1867 * Reject the unit if the digram it forms wants
1868 * to break the syllable, but the resulting
1869 * digram that would end the syllable is not
1870 * allowed to end a syllable.
1871 */
1872 (ALLOWED (BREAK) &&
1873 (digram[units_in_syllable
1874 [current_unit - 2]]
1875 [last_unit] &
1876 NOT_END)) ||
1877
1878 /*
1879 * Reject the unit if the digram it forms
1880 * expects a vowel preceding it and there is
1881 * none.
1882 */
1883 (ALLOWED (PREFIX) &&
1884 !(rules[units_in_syllable
1885 [current_unit - 2]].flags &
1886 VOWEL)))
1887 rule_broken = TRUE;
1888
1889 /*
1890 * The following checks occur when the current unit
1891 * is a vowel and we are not looking at a word ending
1892 * with an e.
1893 */
1894 if (!rule_broken &&
1895 (rules[unit].flags & VOWEL) &&
1896 ((length_left > 0) ||
1897 !(rules[last_unit].flags &
1898 NO_FINAL_SPLIT)))
1899 {
1900 /*
1901 * Don't allow 3 consecutive vowels in a
1902 * syllable. Although some words formed like this
1903 * are OK, like beau, most are not.
1904 */
1905 if ((vowel_count > 1) &&
1906 (rules[last_unit].flags & VOWEL))
1907 rule_broken = TRUE;
1908 else
1909 /*
1910 * Check for the case of
1911 * vowels-consonants-vowel, which is only
1912 * legal if the last vowel is an e and we are
1913 * the end of the word (wich is not
1914 * happening here due to a previous check.
1915 */
1916 if ((vowel_count != 0) &&
1917 !(rules[last_unit].flags & VOWEL))
1918 {
1919 /*
1920 * Try to save the vowel for the next
1921 * syllable, but if the syllable left here
1922 * is not proper (i.e., the resulting last
1923 * digram cannot legally end it), just
1924 * discard it and try for another.
1925 */
1926 if (digram[units_in_syllable
1927 [current_unit - 2]]
1928 [last_unit] &
1929 NOT_END)
1930 rule_broken = TRUE;
1931 else
1932 {
1933 saved_unit = 1;
1934 saved_pair[0] = unit;
1935 want_another_unit = FALSE;
1936 }
1937 }
1938 }
1939 }
1940
1941 /*
1942 * The unit picked and the digram formed are legal.
1943 * We now determine if we can end the syllable. It may,
1944 * in some cases, mean the last unit(s) may be deferred to
1945 * the next syllable. We also check here to see if the
1946 * digram formed expects a vowel to follow.
1947 */
1948 if (!rule_broken && want_another_unit)
1949 {
1950 /*
1951 * This word ends in a silent e.
1952 */
1953 /******/ if (((vowel_count != 0) &&
1954 (rules[unit].flags & NO_FINAL_SPLIT) &&
1955 (length_left == 0) &&
1956 !(rules[last_unit].flags & VOWEL)) ||
1957
1958 /*
1959 * This syllable ends either because the digram
1960 * is an END pair or we would otherwise exceed
1961 * the length of the word.
1962 */
1963 (ALLOWED (END) || (length_left == 0)))
1964 {
1965 want_another_unit = FALSE;
1966 }
1967 else
1968 /*
1969 * Since we have a vowel in the syllable
1970 * already, if the digram calls for the end of the
1971 * syllable, we can legally split it off. We also
1972 * make sure that we are not at the end of the
1973 * dangerous because that syllable may not have
1974 * vowels, or it may not be a legal syllable end,
1975 * and the retrying mechanism will loop infinitely
1976 * with the same digram.
1977 */
1978 if ((vowel_count != 0) && (length_left > 0))
1979 {
1980 /*
1981 * If we must begin a syllable, we do so if
1982 * the only vowel in THIS syllable is not part
1983 * of the digram we are pushing to the next
1984 * syllable.
1985 */
1986 if (ALLOWED (BEGIN) &&
1987 (current_unit > 1) &&
1988 !((vowel_count == 1) &&
1989 (rules[last_unit].flags & VOWEL)))
1990 {
1991 saved_unit = 2;
1992 saved_pair[0] = unit;
1993 saved_pair[1] = last_unit;
1994 want_another_unit = FALSE;
1995 }
1996 else
1997 if (ALLOWED (BREAK))
1998 {
1999 saved_unit = 1;
2000 saved_pair[0] = unit;
2001 want_another_unit = FALSE;
2002 }
2003 }
2004 else
2005 if (ALLOWED (SUFFIX))
2006 {
2007 want_vowel = TRUE;
2008 }
2009 }
2010 }
2011 /********/
2012 tries++;
2013
2014 /*
2015 * If this unit was illegal, redetermine the amount of
2016 * letters left to go in the word.
2017 */
2018 if (rule_broken)
2019 length_left += (short int) strlen (rules[unit].unit_code);
2020 }
2021 while (rule_broken && (tries <= MAX_RETRIES));
2022
2023 /*
2024 * The unit fit OK.
2025 */
2026 if (tries <= MAX_RETRIES)
2027 {
2028 /*
2029 * If the unit were a vowel, count it in.
2030 * However, if the unit were a y and appear
2031 * at the start of the syllable, treat it
2032 * like a constant (so that words like year can
2033 * appear and not conflict with the 3 consecutive
2034 * vowel rule.
2035 */
2036 if ((rules[unit].flags & VOWEL) &&
2037 ((current_unit > 0) ||
2038 !(rules[unit].flags & ALTERNATE_VOWEL)))
2039 vowel_count++;
2040
2041 /*
2042 * If a unit or units were to be saved, we must
2043 * adjust the syllable formed. Otherwise, we
2044 * append the current unit to the syllable.
2045 */
2046 switch (saved_unit)
2047 {
2048 case 0:
2049 units_in_syllable[current_unit] = unit;
2050 (void) strcat (syllable, rules[unit].unit_code);
2051 break;
2052 case 1:
2053 current_unit--;
2054 break;
2055 case 2:
2056 (void) strcpy (&syllable[strlen (syllable) -
2057 strlen (rules[last_unit].unit_code)],"");
2058 length_left += (short int) strlen (rules[last_unit].unit_code);
2059 current_unit -= 2;
2060 break;
2061 }
2062 }
2063 else
2064 /*
2065 * Whoops! Too many tries. We set rule_broken so we can
2066 * loop in the outer loop and try another syllable.
2067 */
2068 rule_broken = TRUE;
2069
2070 /*
2071 * ...and the syllable length grows.
2072 */
2073 *syllable_length = current_unit;
2074
2075 current_unit++;
2076 }
2077 while ((tries <= MAX_RETRIES) && want_another_unit);
2078 }
2079 while (rule_broken ||
2080 illegal_placement (units_in_syllable, *syllable_length));
2081
2082 return (syllable);
2083 }
2084
2085
2086 /*
2087 * This routine goes through an individual syllable and checks
2088 * for illegal combinations of letters that go beyond looking
2089 * at digrams. We look at things like 3 consecutive vowels or
2090 * consonants, or syllables with consonants between vowels (unless
2091 * one of them is the final silent e).
2092 */
2093 boolean
2094 illegal_placement (USHORT *units, USHORT pwlen)
2095 {
2096 USHORT vowel_count;
2097 USHORT unit_count;
2098 boolean failure;
2099
2100 vowel_count = 0;
2101 failure = FALSE;
2102
2103 for (unit_count = 0; !failure && (unit_count <= pwlen);
2104 unit_count++)
2105 {
2106 if (unit_count >= 1)
2107 {
2108 /*
2109 * Don't allow vowels to be split with consonants in
2110 * a single syllable. If we find such a combination
2111 * (except for the silent e) we have to discard the
2112 * syllable).
2113 */
2114 if ((!(rules[units[unit_count - 1]].flags & VOWEL) &&
2115 (rules[units[unit_count]].flags & VOWEL) &&
2116 !((rules[units[unit_count]].flags & NO_FINAL_SPLIT) &&
2117 (unit_count == pwlen)) && (vowel_count != 0)) ||
2118 /*
2119 * Perform these checks when we have at least 3 units.
2120 */
2121 ((unit_count >= 2) &&
2122
2123 /*
2124 * Disallow 3 consecutive consonants.
2125 */
2126 ((!(rules[units[unit_count - 2]].flags & VOWEL) &&
2127 !(rules[units[unit_count - 1]].flags &
2128 VOWEL) &&
2129 !(rules[units[unit_count]].flags &
2130 VOWEL)) ||
2131
2132 /*
2133 * Disallow 3 consecutive vowels, where the first is
2134 * not a y.
2135 */
2136 (((rules[units[unit_count - 2]].flags &
2137 VOWEL) &&
2138 !((rules[units[0]].flags &
2139 ALTERNATE_VOWEL) &&
2140 (unit_count == 2))) &&
2141 (rules[units[unit_count - 1]].flags &
2142 VOWEL) &&
2143 (rules[units[unit_count]].flags &
2144 VOWEL)))))
2145 failure = TRUE;
2146 }
2147
2148 /*
2149 * Count the vowels in the syllable. As mentioned somewhere
2150 * above, exclude the initial y of a syllable. Instead,
2151 * treat it as a consonant.
2152 */
2153 if ((rules[units[unit_count]].flags & VOWEL) &&
2154 !((rules[units[0]].flags & ALTERNATE_VOWEL) &&
2155 (unit_count == 0) && (pwlen != 0)))
2156 vowel_count++;
2157 }
2158
2159 return (failure);
2160 }
2161
2162
2163
2164 /*
2165 * This is the standard Random unit generating routine for
2166 * gen_syllable(). It does not reference the digrams, but
2167 * assumes that it contains 34 units in a particular order.
2168 * This routine attempts to return unit indexes with a distribution
2169 * approaching that of the distribution of the 34 units in
2170 * English. In order to do this, a Random number (supposedly
2171 * uniformly distributed) is used to do a table lookup into an
2172 * array containing unit indices. There are 211 entries in
2173 * the array for the random_unit entry point. The probability
2174 * of a particular unit being generated is equal to the
2175 * fraction of those 211 entries that contain that unit index.
2176 * For example, the letter `a' is unit number 1. Since unit
2177 * index 1 appears 10 times in the array, the probability of
2178 * selecting an `a' is 10/211.
2179 *
2180 * Changes may be made to the digram table without affect to this
2181 * procedure providing the letter-to-number correspondence of
2182 * the units does not change. Likewise, the distribution of the
2183 * 34 units may be altered (and the array size may be changed)
2184 * in this procedure without affecting the digram table or any other
2185 * programs using the Random_word subroutine.
2186 */
2187 static USHORT numbers[] =
2188 {
2189 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2190 1, 1, 1, 1, 1, 1, 1, 1,
2191 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2192 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2193 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
2194 5, 5, 5, 5, 5, 5, 5, 5,
2195 6, 6, 6, 6, 6, 6, 6, 6,
2196 7, 7, 7, 7, 7, 7,
2197 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
2198 9, 9, 9, 9, 9, 9, 9, 9,
2199 10, 10, 10, 10, 10, 10, 10, 10,
2200 11, 11, 11, 11, 11, 11,
2201 12, 12, 12, 12, 12, 12,
2202 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
2203 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
2204 15, 15, 15, 15, 15, 15,
2205 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
2206 17, 17, 17, 17, 17, 17, 17, 17,
2207 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
2208 19, 19, 19, 19, 19, 19,
2209 20, 20, 20, 20, 20, 20, 20, 20,
2210 21, 21, 21, 21, 21, 21, 21, 21,
2211 22,
2212 23, 23, 23, 23, 23, 23, 23, 23,
2213 24,
2214 25,
2215 26,
2216 27,
2217 28,
2218 29, 29,
2219 30,
2220 31,
2221 32,
2222 33
2223 };
2224
2225
2226 /*
2227 * This structure has a typical English frequency of vowels.
2228 * The value of an entry is the vowel position (a=0, e=4, i=8,
2229 * o=14, u=19, y=23) in the rules array. The number of times
2230 * the value appears is the frequency. Thus, the letter "a"
2231 * is assumed to appear 2/12 = 1/6 of the time. This array
2232 * may be altered if better data is obtained. The routines that
2233 * use vowel_numbers will adjust to the size difference
2234 automatically.
2235 */
2236 static USHORT vowel_numbers[] =
2237 {
2238 0, 0, 4, 4, 4, 8, 8, 14, 14, 19, 19, 23
2239 };
2240
2241
2242 /*
2243 * Select a unit (a letter or a consonant group). If a vowel is
2244 * expected, use the vowel_numbers array rather than looping through
2245 * the numbers array until a vowel is found.
2246 */
2247 USHORT
2248 random_unit (USHORT type)
2249 {
2250 USHORT number;
2251
2252 /*
2253 * Sometimes, we are asked to explicitly get a vowel (i.e., if
2254 * a digram pair expects one following it). This is a shortcut
2255 * to do that and avoid looping with rejected consonants.
2256 */
2257 if (type & VOWEL)
2258 number = vowel_numbers[get_random (0, (sizeof (vowel_numbers) / sizeof (USHORT))-1)];
2259 else
2260 /*
2261 * Get any letter according to the English distribution.
2262 */
2263 number = numbers[get_random (0, (sizeof (numbers) / sizeof (USHORT))-1)];
2264 return (number);
2265 }
2266
2267
2268 /*
2269 ** get_random() -
2270 ** This routine should return a uniformly distributed Random number between
2271 ** minlen and maxlen inclusive. The Electronic Code Book form of CAST is
2272 ** used to produce the Random number. The inputs to CAST are the old pass-
2273 ** word and a pseudoRandom key generated according to the procedure out-
2274 ** lined in Appendix C of ANSI X9.17.
2275 ** INPUT:
2276 ** USHORT - minimum
2277 ** USHORT - maximum
2278 ** OUTPUT:
2279 ** USHORT - random number
2280 ** NOTES:
2281 ** none.
2282 */
2283
2284 USHORT
2285 get_random (USHORT minlen, USHORT maxlen)
2286 {
2287 USHORT ret = 0;
2288 ret = minlen + (USHORT) randint ((int) (maxlen - minlen + 1));
2289 return (ret);
2290 }