1/*
2 * otpcode.c --
3 *
4 *      Implements and registers conversion from and to OTP's english words.
5 *
6 *
7 * Copyright (c) 1999 Marshall Rose (mrose@dbc.mtview.ca.us)
8 * All rights reserved.
9 *
10 * Permission is hereby granted, without written agreement and without
11 * license or royalty fees, to use, copy, modify, and distribute this
12 * software and its documentation for any purpose, provided that the
13 * above copyright notice and the following two paragraphs appear in
14 * all copies of this software.
15 *
16 * IN NO EVENT SHALL I LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
17 * INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
18 * SOFTWARE AND ITS DOCUMENTATION, EVEN IF I HAVE BEEN ADVISED OF THE
19 * POSSIBILITY OF SUCH DAMAGE.
20 *
21 * I SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND
24 * I HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
25 * ENHANCEMENTS, OR MODIFICATIONS.
26 *
27 * CVS: $Id: otpcode.c,v 1.7 2009/05/07 04:57:27 andreas_kupries Exp $
28 */
29
30#include <ctype.h>
31#include "transformInt.h"
32
33/*
34 * Converter description
35 * ---------------------
36 *
37 * Reference:
38 *      RFC 2289
39 *
40 * Encoding:
41 *      Each sequence of 64-bits is converted to OTP's 6 english words.
42 *      For ease of readability, a newline is written after each 6 words.
43 *
44 * Decoding:
45 *      Each 6 word sequence is converted to 64-bits.
46 */
47
48
49/*
50 * Declarations of internal procedures.
51 */
52
53static Trf_ControlBlock CreateEncoder  _ANSI_ARGS_ ((ClientData writeClientData,
54                                                     Trf_WriteProc *fun,
55                                                     Trf_Options optInfo,
56                                                     Tcl_Interp*   interp,
57                                                     ClientData clientData));
58static void             DeleteEncoder  _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock,
59                                                     ClientData clientData));
60static int              Encode         _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock,
61                                                     unsigned int character,
62                                                     Tcl_Interp* interp,
63                                                     ClientData clientData));
64static int              EncodeBuffer   _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock,
65                                                     unsigned char* buffer, int bufLen,
66                                                     Tcl_Interp* interp,
67                                                     ClientData clientData));
68static int              FlushEncoder   _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock,
69                                                     Tcl_Interp* interp,
70                                                     ClientData clientData));
71static void             ClearEncoder   _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock,
72                                                     ClientData clientData));
73
74static Trf_ControlBlock CreateDecoder  _ANSI_ARGS_ ((ClientData writeClientData,
75                                                     Trf_WriteProc *fun,
76                                                     Trf_Options optInfo,
77                                                     Tcl_Interp*   interp,
78                                                     ClientData clientData));
79static void             DeleteDecoder  _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock,
80                                                     ClientData clientData));
81static int              Decode         _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock,
82                                                     unsigned int character,
83                                                     Tcl_Interp* interp,
84                                                     ClientData clientData));
85static int              DecodeBuffer   _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock,
86                                                     unsigned char* buffer, int bufLen,
87                                                     Tcl_Interp* interp,
88                                                     ClientData clientData));
89static int              FlushDecoder   _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock,
90                                                     Tcl_Interp* interp,
91                                                     ClientData clientData));
92static void             ClearDecoder   _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock,
93                                                     ClientData clientData));
94
95
96/*
97 * Converter definition.
98 */
99
100static Trf_TypeDefinition convDefinition =
101{
102  "otp_words",
103  NULL, /* clientData not used by conversions. */
104  NULL, /* set later by TrfInit_OTP_WORDS, THREAD: serialize initialization */
105  {
106    CreateEncoder,
107    DeleteEncoder,
108    Encode,
109    EncodeBuffer,
110    FlushEncoder,
111    ClearEncoder,
112    NULL /* no MaxRead */
113  }, {
114    CreateDecoder,
115    DeleteDecoder,
116    Decode,
117    DecodeBuffer,
118    FlushDecoder,
119    ClearDecoder,
120    NULL /* no MaxRead */
121  },
122  TRF_UNSEEKABLE
123};
124
125/*
126 * Definition of the control blocks for en- and decoder.
127 */
128
129typedef struct _EncoderControl_ {
130    Trf_WriteProc* write;
131    ClientData     writeClientData;
132
133    /* add conversion specific items here (otp_words encode) */
134
135    int    charCount;
136    unsigned char buf[8];
137
138} EncoderControl;
139
140
141typedef struct _DecoderControl_ {
142    Trf_WriteProc* write;
143    ClientData     writeClientData;
144
145    /* add conversion specific items here (otp_words decode) */
146
147    int    charCount;
148    int    wordCount;
149    char   words[6][5];
150
151} DecoderControl;
152
153
154/* taken from RFC 2289... */
155
156static unsigned long    extract         _ANSI_ARGS_ ((char *s,
157                                                      int start,
158                                                      int length));
159static void             insert          _ANSI_ARGS_ ((char *s,
160                                                      int x,
161                                                      int start,
162                                                      int length));
163static int              wsrch           _ANSI_ARGS_ ((char *w,
164                                                      int low,
165                                                      int high));
166
167/* Dictionary for integer-word translations */
168static char Wp[2048][4] = { /* THREADING: constant, read-only => safe */
169"A",
170"ABE",
171"ACE",
172"ACT",
173"AD",
174"ADA",
175"ADD",
176"AGO",
177"AID",
178"AIM",
179"AIR",
180"ALL",
181"ALP",
182"AM",
183"AMY",
184"AN",
185"ANA",
186"AND",
187"ANN",
188"ANT",
189"ANY",
190"APE",
191"APS",
192"APT",
193"ARC",
194"ARE",
195"ARK",
196"ARM",
197"ART",
198"AS",
199"ASH",
200"ASK",
201"AT",
202"ATE",
203"AUG",
204"AUK",
205"AVE",
206"AWE",
207"AWK",
208"AWL",
209"AWN",
210"AX",
211"AYE",
212"BAD",
213"BAG",
214"BAH",
215"BAM",
216"BAN",
217"BAR",
218"BAT",
219"BAY",
220"BE",
221"BED",
222"BEE",
223"BEG",
224"BEN",
225"BET",
226"BEY",
227"BIB",
228"BID",
229"BIG",
230"BIN",
231"BIT",
232"BOB",
233"BOG",
234"BON",
235"BOO",
236"BOP",
237"BOW",
238"BOY",
239"BUB",
240"BUD",
241"BUG",
242"BUM",
243"BUN",
244"BUS",
245"BUT",
246"BUY",
247"BY",
248"BYE",
249"CAB",
250"CAL",
251"CAM",
252"CAN",
253"CAP",
254"CAR",
255"CAT",
256"CAW",
257"COD",
258"COG",
259"COL",
260"CON",
261"COO",
262"COP",
263"COT",
264"COW",
265"COY",
266"CRY",
267"CUB",
268"CUE",
269"CUP",
270"CUR",
271"CUT",
272"DAB",
273"DAD",
274"DAM",
275"DAN",
276"DAR",
277"DAY",
278"DEE",
279"DEL",
280"DEN",
281"DES",
282"DEW",
283"DID",
284"DIE",
285"DIG",
286"DIN",
287"DIP",
288"DO",
289"DOE",
290"DOG",
291"DON",
292"DOT",
293"DOW",
294"DRY",
295"DUB",
296"DUD",
297"DUE",
298"DUG",
299"DUN",
300"EAR",
301"EAT",
302"ED",
303"EEL",
304"EGG",
305"EGO",
306"ELI",
307"ELK",
308"ELM",
309"ELY",
310"EM",
311"END",
312"EST",
313"ETC",
314"EVA",
315"EVE",
316"EWE",
317"EYE",
318"FAD",
319"FAN",
320"FAR",
321"FAT",
322"FAY",
323"FED",
324"FEE",
325"FEW",
326"FIB",
327"FIG",
328"FIN",
329"FIR",
330"FIT",
331"FLO",
332"FLY",
333"FOE",
334"FOG",
335"FOR",
336"FRY",
337"FUM",
338"FUN",
339"FUR",
340"GAB",
341"GAD",
342"GAG",
343"GAL",
344"GAM",
345"GAP",
346"GAS",
347"GAY",
348"GEE",
349"GEL",
350"GEM",
351"GET",
352"GIG",
353"GIL",
354"GIN",
355"GO",
356"GOT",
357"GUM",
358"GUN",
359"GUS",
360"GUT",
361"GUY",
362"GYM",
363"GYP",
364"HA",
365"HAD",
366"HAL",
367"HAM",
368"HAN",
369"HAP",
370"HAS",
371"HAT",
372"HAW",
373"HAY",
374"HE",
375"HEM",
376"HEN",
377"HER",
378"HEW",
379"HEY",
380"HI",
381"HID",
382"HIM",
383"HIP",
384"HIS",
385"HIT",
386"HO",
387"HOB",
388"HOC",
389"HOE",
390"HOG",
391"HOP",
392"HOT",
393"HOW",
394"HUB",
395"HUE",
396"HUG",
397"HUH",
398"HUM",
399"HUT",
400"I",
401"ICY",
402"IDA",
403"IF",
404"IKE",
405"ILL",
406"INK",
407"INN",
408"IO",
409"ION",
410"IQ",
411"IRA",
412"IRE",
413"IRK",
414"IS",
415"IT",
416"ITS",
417"IVY",
418"JAB",
419"JAG",
420"JAM",
421"JAN",
422"JAR",
423"JAW",
424"JAY",
425"JET",
426"JIG",
427"JIM",
428"JO",
429"JOB",
430"JOE",
431"JOG",
432"JOT",
433"JOY",
434"JUG",
435"JUT",
436"KAY",
437"KEG",
438"KEN",
439"KEY",
440"KID",
441"KIM",
442"KIN",
443"KIT",
444"LA",
445"LAB",
446"LAC",
447"LAD",
448"LAG",
449"LAM",
450"LAP",
451"LAW",
452"LAY",
453"LEA",
454"LED",
455"LEE",
456"LEG",
457"LEN",
458"LEO",
459"LET",
460"LEW",
461"LID",
462"LIE",
463"LIN",
464"LIP",
465"LIT",
466"LO",
467"LOB",
468"LOG",
469"LOP",
470"LOS",
471"LOT",
472"LOU",
473"LOW",
474"LOY",
475"LUG",
476"LYE",
477"MA",
478"MAC",
479"MAD",
480"MAE",
481"MAN",
482"MAO",
483"MAP",
484"MAT",
485"MAW",
486"MAY",
487"ME",
488"MEG",
489"MEL",
490"MEN",
491"MET",
492"MEW",
493"MID",
494"MIN",
495"MIT",
496"MOB",
497"MOD",
498"MOE",
499"MOO",
500"MOP",
501"MOS",
502"MOT",
503"MOW",
504"MUD",
505"MUG",
506"MUM",
507"MY",
508"NAB",
509"NAG",
510"NAN",
511"NAP",
512"NAT",
513"NAY",
514"NE",
515"NED",
516"NEE",
517"NET",
518"NEW",
519"NIB",
520"NIL",
521"NIP",
522"NIT",
523"NO",
524"NOB",
525"NOD",
526"NON",
527"NOR",
528"NOT",
529"NOV",
530"NOW",
531"NU",
532"NUN",
533"NUT",
534"O",
535"OAF",
536"OAK",
537"OAR",
538"OAT",
539"ODD",
540"ODE",
541"OF",
542"OFF",
543"OFT",
544"OH",
545"OIL",
546"OK",
547"OLD",
548"ON",
549"ONE",
550"OR",
551"ORB",
552"ORE",
553"ORR",
554"OS",
555"OTT",
556"OUR",
557"OUT",
558"OVA",
559"OW",
560"OWE",
561"OWL",
562"OWN",
563"OX",
564"PA",
565"PAD",
566"PAL",
567"PAM",
568"PAN",
569"PAP",
570"PAR",
571"PAT",
572"PAW",
573"PAY",
574"PEA",
575"PEG",
576"PEN",
577"PEP",
578"PER",
579"PET",
580"PEW",
581"PHI",
582"PI",
583"PIE",
584"PIN",
585"PIT",
586"PLY",
587"PO",
588"POD",
589"POE",
590"POP",
591"POT",
592"POW",
593"PRO",
594"PRY",
595"PUB",
596"PUG",
597"PUN",
598"PUP",
599"PUT",
600"QUO",
601"RAG",
602"RAM",
603"RAN",
604"RAP",
605"RAT",
606"RAW",
607"RAY",
608"REB",
609"RED",
610"REP",
611"RET",
612"RIB",
613"RID",
614"RIG",
615"RIM",
616"RIO",
617"RIP",
618"ROB",
619"ROD",
620"ROE",
621"RON",
622"ROT",
623"ROW",
624"ROY",
625"RUB",
626"RUE",
627"RUG",
628"RUM",
629"RUN",
630"RYE",
631"SAC",
632"SAD",
633"SAG",
634"SAL",
635"SAM",
636"SAN",
637"SAP",
638"SAT",
639"SAW",
640"SAY",
641"SEA",
642"SEC",
643"SEE",
644"SEN",
645"SET",
646"SEW",
647"SHE",
648"SHY",
649"SIN",
650"SIP",
651"SIR",
652"SIS",
653"SIT",
654"SKI",
655"SKY",
656"SLY",
657"SO",
658"SOB",
659"SOD",
660"SON",
661"SOP",
662"SOW",
663"SOY",
664"SPA",
665"SPY",
666"SUB",
667"SUD",
668"SUE",
669"SUM",
670"SUN",
671"SUP",
672"TAB",
673"TAD",
674"TAG",
675"TAN",
676"TAP",
677"TAR",
678"TEA",
679"TED",
680"TEE",
681"TEN",
682"THE",
683"THY",
684"TIC",
685"TIE",
686"TIM",
687"TIN",
688"TIP",
689"TO",
690"TOE",
691"TOG",
692"TOM",
693"TON",
694"TOO",
695"TOP",
696"TOW",
697"TOY",
698"TRY",
699"TUB",
700"TUG",
701"TUM",
702"TUN",
703"TWO",
704"UN",
705"UP",
706"US",
707"USE",
708"VAN",
709"VAT",
710"VET",
711"VIE",
712"WAD",
713"WAG",
714"WAR",
715"WAS",
716"WAY",
717"WE",
718"WEB",
719"WED",
720"WEE",
721"WET",
722"WHO",
723"WHY",
724"WIN",
725"WIT",
726"WOK",
727"WON",
728"WOO",
729"WOW",
730"WRY",
731"WU",
732"YAM",
733"YAP",
734"YAW",
735"YE",
736"YEA",
737"YES",
738"YET",
739"YOU",
740"ABED",
741"ABEL",
742"ABET",
743"ABLE",
744"ABUT",
745"ACHE",
746"ACID",
747"ACME",
748"ACRE",
749"ACTA",
750"ACTS",
751"ADAM",
752"ADDS",
753"ADEN",
754"AFAR",
755"AFRO",
756"AGEE",
757"AHEM",
758"AHOY",
759"AIDA",
760"AIDE",
761"AIDS",
762"AIRY",
763"AJAR",
764"AKIN",
765"ALAN",
766"ALEC",
767"ALGA",
768"ALIA",
769"ALLY",
770"ALMA",
771"ALOE",
772"ALSO",
773"ALTO",
774"ALUM",
775"ALVA",
776"AMEN",
777"AMES",
778"AMID",
779"AMMO",
780"AMOK",
781"AMOS",
782"AMRA",
783"ANDY",
784"ANEW",
785"ANNA",
786"ANNE",
787"ANTE",
788"ANTI",
789"AQUA",
790"ARAB",
791"ARCH",
792"AREA",
793"ARGO",
794"ARID",
795"ARMY",
796"ARTS",
797"ARTY",
798"ASIA",
799"ASKS",
800"ATOM",
801"AUNT",
802"AURA",
803"AUTO",
804"AVER",
805"AVID",
806"AVIS",
807"AVON",
808"AVOW",
809"AWAY",
810"AWRY",
811"BABE",
812"BABY",
813"BACH",
814"BACK",
815"BADE",
816"BAIL",
817"BAIT",
818"BAKE",
819"BALD",
820"BALE",
821"BALI",
822"BALK",
823"BALL",
824"BALM",
825"BAND",
826"BANE",
827"BANG",
828"BANK",
829"BARB",
830"BARD",
831"BARE",
832"BARK",
833"BARN",
834"BARR",
835"BASE",
836"BASH",
837"BASK",
838"BASS",
839"BATE",
840"BATH",
841"BAWD",
842"BAWL",
843"BEAD",
844"BEAK",
845"BEAM",
846"BEAN",
847"BEAR",
848"BEAT",
849"BEAU",
850"BECK",
851"BEEF",
852"BEEN",
853"BEER",
854"BEET",
855"BELA",
856"BELL",
857"BELT",
858"BEND",
859"BENT",
860"BERG",
861"BERN",
862"BERT",
863"BESS",
864"BEST",
865"BETA",
866"BETH",
867"BHOY",
868"BIAS",
869"BIDE",
870"BIEN",
871"BILE",
872"BILK",
873"BILL",
874"BIND",
875"BING",
876"BIRD",
877"BITE",
878"BITS",
879"BLAB",
880"BLAT",
881"BLED",
882"BLEW",
883"BLOB",
884"BLOC",
885"BLOT",
886"BLOW",
887"BLUE",
888"BLUM",
889"BLUR",
890"BOAR",
891"BOAT",
892"BOCA",
893"BOCK",
894"BODE",
895"BODY",
896"BOGY",
897"BOHR",
898"BOIL",
899"BOLD",
900"BOLO",
901"BOLT",
902"BOMB",
903"BONA",
904"BOND",
905"BONE",
906"BONG",
907"BONN",
908"BONY",
909"BOOK",
910"BOOM",
911"BOON",
912"BOOT",
913"BORE",
914"BORG",
915"BORN",
916"BOSE",
917"BOSS",
918"BOTH",
919"BOUT",
920"BOWL",
921"BOYD",
922"BRAD",
923"BRAE",
924"BRAG",
925"BRAN",
926"BRAY",
927"BRED",
928"BREW",
929"BRIG",
930"BRIM",
931"BROW",
932"BUCK",
933"BUDD",
934"BUFF",
935"BULB",
936"BULK",
937"BULL",
938"BUNK",
939"BUNT",
940"BUOY",
941"BURG",
942"BURL",
943"BURN",
944"BURR",
945"BURT",
946"BURY",
947"BUSH",
948"BUSS",
949"BUST",
950"BUSY",
951"BYTE",
952"CADY",
953"CAFE",
954"CAGE",
955"CAIN",
956"CAKE",
957"CALF",
958"CALL",
959"CALM",
960"CAME",
961"CANE",
962"CANT",
963"CARD",
964"CARE",
965"CARL",
966"CARR",
967"CART",
968"CASE",
969"CASH",
970"CASK",
971"CAST",
972"CAVE",
973"CEIL",
974"CELL",
975"CENT",
976"CERN",
977"CHAD",
978"CHAR",
979"CHAT",
980"CHAW",
981"CHEF",
982"CHEN",
983"CHEW",
984"CHIC",
985"CHIN",
986"CHOU",
987"CHOW",
988"CHUB",
989"CHUG",
990"CHUM",
991"CITE",
992"CITY",
993"CLAD",
994"CLAM",
995"CLAN",
996"CLAW",
997"CLAY",
998"CLOD",
999"CLOG",
1000"CLOT",
1001"CLUB",
1002"CLUE",
1003"COAL",
1004"COAT",
1005"COCA",
1006"COCK",
1007"COCO",
1008"CODA",
1009"CODE",
1010"CODY",
1011"COED",
1012"COIL",
1013"COIN",
1014"COKE",
1015"COLA",
1016"COLD",
1017"COLT",
1018"COMA",
1019"COMB",
1020"COME",
1021"COOK",
1022"COOL",
1023"COON",
1024"COOT",
1025"CORD",
1026"CORE",
1027"CORK",
1028"CORN",
1029"COST",
1030"COVE",
1031"COWL",
1032"CRAB",
1033"CRAG",
1034"CRAM",
1035"CRAY",
1036"CREW",
1037"CRIB",
1038"CROW",
1039"CRUD",
1040"CUBA",
1041"CUBE",
1042"CUFF",
1043"CULL",
1044"CULT",
1045"CUNY",
1046"CURB",
1047"CURD",
1048"CURE",
1049"CURL",
1050"CURT",
1051"CUTS",
1052"DADE",
1053"DALE",
1054"DAME",
1055"DANA",
1056"DANE",
1057"DANG",
1058"DANK",
1059"DARE",
1060"DARK",
1061"DARN",
1062"DART",
1063"DASH",
1064"DATA",
1065"DATE",
1066"DAVE",
1067"DAVY",
1068"DAWN",
1069"DAYS",
1070"DEAD",
1071"DEAF",
1072"DEAL",
1073"DEAN",
1074"DEAR",
1075"DEBT",
1076"DECK",
1077"DEED",
1078"DEEM",
1079"DEER",
1080"DEFT",
1081"DEFY",
1082"DELL",
1083"DENT",
1084"DENY",
1085"DESK",
1086"DIAL",
1087"DICE",
1088"DIED",
1089"DIET",
1090"DIME",
1091"DINE",
1092"DING",
1093"DINT",
1094"DIRE",
1095"DIRT",
1096"DISC",
1097"DISH",
1098"DISK",
1099"DIVE",
1100"DOCK",
1101"DOES",
1102"DOLE",
1103"DOLL",
1104"DOLT",
1105"DOME",
1106"DONE",
1107"DOOM",
1108"DOOR",
1109"DORA",
1110"DOSE",
1111"DOTE",
1112"DOUG",
1113"DOUR",
1114"DOVE",
1115"DOWN",
1116"DRAB",
1117"DRAG",
1118"DRAM",
1119"DRAW",
1120"DREW",
1121"DRUB",
1122"DRUG",
1123"DRUM",
1124"DUAL",
1125"DUCK",
1126"DUCT",
1127"DUEL",
1128"DUET",
1129"DUKE",
1130"DULL",
1131"DUMB",
1132"DUNE",
1133"DUNK",
1134"DUSK",
1135"DUST",
1136"DUTY",
1137"EACH",
1138"EARL",
1139"EARN",
1140"EASE",
1141"EAST",
1142"EASY",
1143"EBEN",
1144"ECHO",
1145"EDDY",
1146"EDEN",
1147"EDGE",
1148"EDGY",
1149"EDIT",
1150"EDNA",
1151"EGAN",
1152"ELAN",
1153"ELBA",
1154"ELLA",
1155"ELSE",
1156"EMIL",
1157"EMIT",
1158"EMMA",
1159"ENDS",
1160"ERIC",
1161"EROS",
1162"EVEN",
1163"EVER",
1164"EVIL",
1165"EYED",
1166"FACE",
1167"FACT",
1168"FADE",
1169"FAIL",
1170"FAIN",
1171"FAIR",
1172"FAKE",
1173"FALL",
1174"FAME",
1175"FANG",
1176"FARM",
1177"FAST",
1178"FATE",
1179"FAWN",
1180"FEAR",
1181"FEAT",
1182"FEED",
1183"FEEL",
1184"FEET",
1185"FELL",
1186"FELT",
1187"FEND",
1188"FERN",
1189"FEST",
1190"FEUD",
1191"FIEF",
1192"FIGS",
1193"FILE",
1194"FILL",
1195"FILM",
1196"FIND",
1197"FINE",
1198"FINK",
1199"FIRE",
1200"FIRM",
1201"FISH",
1202"FISK",
1203"FIST",
1204"FITS",
1205"FIVE",
1206"FLAG",
1207"FLAK",
1208"FLAM",
1209"FLAT",
1210"FLAW",
1211"FLEA",
1212"FLED",
1213"FLEW",
1214"FLIT",
1215"FLOC",
1216"FLOG",
1217"FLOW",
1218"FLUB",
1219"FLUE",
1220"FOAL",
1221"FOAM",
1222"FOGY",
1223"FOIL",
1224"FOLD",
1225"FOLK",
1226"FOND",
1227"FONT",
1228"FOOD",
1229"FOOL",
1230"FOOT",
1231"FORD",
1232"FORE",
1233"FORK",
1234"FORM",
1235"FORT",
1236"FOSS",
1237"FOUL",
1238"FOUR",
1239"FOWL",
1240"FRAU",
1241"FRAY",
1242"FRED",
1243"FREE",
1244"FRET",
1245"FREY",
1246"FROG",
1247"FROM",
1248"FUEL",
1249"FULL",
1250"FUME",
1251"FUND",
1252"FUNK",
1253"FURY",
1254"FUSE",
1255"FUSS",
1256"GAFF",
1257"GAGE",
1258"GAIL",
1259"GAIN",
1260"GAIT",
1261"GALA",
1262"GALE",
1263"GALL",
1264"GALT",
1265"GAME",
1266"GANG",
1267"GARB",
1268"GARY",
1269"GASH",
1270"GATE",
1271"GAUL",
1272"GAUR",
1273"GAVE",
1274"GAWK",
1275"GEAR",
1276"GELD",
1277"GENE",
1278"GENT",
1279"GERM",
1280"GETS",
1281"GIBE",
1282"GIFT",
1283"GILD",
1284"GILL",
1285"GILT",
1286"GINA",
1287"GIRD",
1288"GIRL",
1289"GIST",
1290"GIVE",
1291"GLAD",
1292"GLEE",
1293"GLEN",
1294"GLIB",
1295"GLOB",
1296"GLOM",
1297"GLOW",
1298"GLUE",
1299"GLUM",
1300"GLUT",
1301"GOAD",
1302"GOAL",
1303"GOAT",
1304"GOER",
1305"GOES",
1306"GOLD",
1307"GOLF",
1308"GONE",
1309"GONG",
1310"GOOD",
1311"GOOF",
1312"GORE",
1313"GORY",
1314"GOSH",
1315"GOUT",
1316"GOWN",
1317"GRAB",
1318"GRAD",
1319"GRAY",
1320"GREG",
1321"GREW",
1322"GREY",
1323"GRID",
1324"GRIM",
1325"GRIN",
1326"GRIT",
1327"GROW",
1328"GRUB",
1329"GULF",
1330"GULL",
1331"GUNK",
1332"GURU",
1333"GUSH",
1334"GUST",
1335"GWEN",
1336"GWYN",
1337"HAAG",
1338"HAAS",
1339"HACK",
1340"HAIL",
1341"HAIR",
1342"HALE",
1343"HALF",
1344"HALL",
1345"HALO",
1346"HALT",
1347"HAND",
1348"HANG",
1349"HANK",
1350"HANS",
1351"HARD",
1352"HARK",
1353"HARM",
1354"HART",
1355"HASH",
1356"HAST",
1357"HATE",
1358"HATH",
1359"HAUL",
1360"HAVE",
1361"HAWK",
1362"HAYS",
1363"HEAD",
1364"HEAL",
1365"HEAR",
1366"HEAT",
1367"HEBE",
1368"HECK",
1369"HEED",
1370"HEEL",
1371"HEFT",
1372"HELD",
1373"HELL",
1374"HELM",
1375"HERB",
1376"HERD",
1377"HERE",
1378"HERO",
1379"HERS",
1380"HESS",
1381"HEWN",
1382"HICK",
1383"HIDE",
1384"HIGH",
1385"HIKE",
1386"HILL",
1387"HILT",
1388"HIND",
1389"HINT",
1390"HIRE",
1391"HISS",
1392"HIVE",
1393"HOBO",
1394"HOCK",
1395"HOFF",
1396"HOLD",
1397"HOLE",
1398"HOLM",
1399"HOLT",
1400"HOME",
1401"HONE",
1402"HONK",
1403"HOOD",
1404"HOOF",
1405"HOOK",
1406"HOOT",
1407"HORN",
1408"HOSE",
1409"HOST",
1410"HOUR",
1411"HOVE",
1412"HOWE",
1413"HOWL",
1414"HOYT",
1415"HUCK",
1416"HUED",
1417"HUFF",
1418"HUGE",
1419"HUGH",
1420"HUGO",
1421"HULK",
1422"HULL",
1423"HUNK",
1424"HUNT",
1425"HURD",
1426"HURL",
1427"HURT",
1428"HUSH",
1429"HYDE",
1430"HYMN",
1431"IBIS",
1432"ICON",
1433"IDEA",
1434"IDLE",
1435"IFFY",
1436"INCA",
1437"INCH",
1438"INTO",
1439"IONS",
1440"IOTA",
1441"IOWA",
1442"IRIS",
1443"IRMA",
1444"IRON",
1445"ISLE",
1446"ITCH",
1447"ITEM",
1448"IVAN",
1449"JACK",
1450"JADE",
1451"JAIL",
1452"JAKE",
1453"JANE",
1454"JAVA",
1455"JEAN",
1456"JEFF",
1457"JERK",
1458"JESS",
1459"JEST",
1460"JIBE",
1461"JILL",
1462"JILT",
1463"JIVE",
1464"JOAN",
1465"JOBS",
1466"JOCK",
1467"JOEL",
1468"JOEY",
1469"JOHN",
1470"JOIN",
1471"JOKE",
1472"JOLT",
1473"JOVE",
1474"JUDD",
1475"JUDE",
1476"JUDO",
1477"JUDY",
1478"JUJU",
1479"JUKE",
1480"JULY",
1481"JUNE",
1482"JUNK",
1483"JUNO",
1484"JURY",
1485"JUST",
1486"JUTE",
1487"KAHN",
1488"KALE",
1489"KANE",
1490"KANT",
1491"KARL",
1492"KATE",
1493"KEEL",
1494"KEEN",
1495"KENO",
1496"KENT",
1497"KERN",
1498"KERR",
1499"KEYS",
1500"KICK",
1501"KILL",
1502"KIND",
1503"KING",
1504"KIRK",
1505"KISS",
1506"KITE",
1507"KLAN",
1508"KNEE",
1509"KNEW",
1510"KNIT",
1511"KNOB",
1512"KNOT",
1513"KNOW",
1514"KOCH",
1515"KONG",
1516"KUDO",
1517"KURD",
1518"KURT",
1519"KYLE",
1520"LACE",
1521"LACK",
1522"LACY",
1523"LADY",
1524"LAID",
1525"LAIN",
1526"LAIR",
1527"LAKE",
1528"LAMB",
1529"LAME",
1530"LAND",
1531"LANE",
1532"LANG",
1533"LARD",
1534"LARK",
1535"LASS",
1536"LAST",
1537"LATE",
1538"LAUD",
1539"LAVA",
1540"LAWN",
1541"LAWS",
1542"LAYS",
1543"LEAD",
1544"LEAF",
1545"LEAK",
1546"LEAN",
1547"LEAR",
1548"LEEK",
1549"LEER",
1550"LEFT",
1551"LEND",
1552"LENS",
1553"LENT",
1554"LEON",
1555"LESK",
1556"LESS",
1557"LEST",
1558"LETS",
1559"LIAR",
1560"LICE",
1561"LICK",
1562"LIED",
1563"LIEN",
1564"LIES",
1565"LIEU",
1566"LIFE",
1567"LIFT",
1568"LIKE",
1569"LILA",
1570"LILT",
1571"LILY",
1572"LIMA",
1573"LIMB",
1574"LIME",
1575"LIND",
1576"LINE",
1577"LINK",
1578"LINT",
1579"LION",
1580"LISA",
1581"LIST",
1582"LIVE",
1583"LOAD",
1584"LOAF",
1585"LOAM",
1586"LOAN",
1587"LOCK",
1588"LOFT",
1589"LOGE",
1590"LOIS",
1591"LOLA",
1592"LONE",
1593"LONG",
1594"LOOK",
1595"LOON",
1596"LOOT",
1597"LORD",
1598"LORE",
1599"LOSE",
1600"LOSS",
1601"LOST",
1602"LOUD",
1603"LOVE",
1604"LOWE",
1605"LUCK",
1606"LUCY",
1607"LUGE",
1608"LUKE",
1609"LULU",
1610"LUND",
1611"LUNG",
1612"LURA",
1613"LURE",
1614"LURK",
1615"LUSH",
1616"LUST",
1617"LYLE",
1618"LYNN",
1619"LYON",
1620"LYRA",
1621"MACE",
1622"MADE",
1623"MAGI",
1624"MAID",
1625"MAIL",
1626"MAIN",
1627"MAKE",
1628"MALE",
1629"MALI",
1630"MALL",
1631"MALT",
1632"MANA",
1633"MANN",
1634"MANY",
1635"MARC",
1636"MARE",
1637"MARK",
1638"MARS",
1639"MART",
1640"MARY",
1641"MASH",
1642"MASK",
1643"MASS",
1644"MAST",
1645"MATE",
1646"MATH",
1647"MAUL",
1648"MAYO",
1649"MEAD",
1650"MEAL",
1651"MEAN",
1652"MEAT",
1653"MEEK",
1654"MEET",
1655"MELD",
1656"MELT",
1657"MEMO",
1658"MEND",
1659"MENU",
1660"MERT",
1661"MESH",
1662"MESS",
1663"MICE",
1664"MIKE",
1665"MILD",
1666"MILE",
1667"MILK",
1668"MILL",
1669"MILT",
1670"MIMI",
1671"MIND",
1672"MINE",
1673"MINI",
1674"MINK",
1675"MINT",
1676"MIRE",
1677"MISS",
1678"MIST",
1679"MITE",
1680"MITT",
1681"MOAN",
1682"MOAT",
1683"MOCK",
1684"MODE",
1685"MOLD",
1686"MOLE",
1687"MOLL",
1688"MOLT",
1689"MONA",
1690"MONK",
1691"MONT",
1692"MOOD",
1693"MOON",
1694"MOOR",
1695"MOOT",
1696"MORE",
1697"MORN",
1698"MORT",
1699"MOSS",
1700"MOST",
1701"MOTH",
1702"MOVE",
1703"MUCH",
1704"MUCK",
1705"MUDD",
1706"MUFF",
1707"MULE",
1708"MULL",
1709"MURK",
1710"MUSH",
1711"MUST",
1712"MUTE",
1713"MUTT",
1714"MYRA",
1715"MYTH",
1716"NAGY",
1717"NAIL",
1718"NAIR",
1719"NAME",
1720"NARY",
1721"NASH",
1722"NAVE",
1723"NAVY",
1724"NEAL",
1725"NEAR",
1726"NEAT",
1727"NECK",
1728"NEED",
1729"NEIL",
1730"NELL",
1731"NEON",
1732"NERO",
1733"NESS",
1734"NEST",
1735"NEWS",
1736"NEWT",
1737"NIBS",
1738"NICE",
1739"NICK",
1740"NILE",
1741"NINA",
1742"NINE",
1743"NOAH",
1744"NODE",
1745"NOEL",
1746"NOLL",
1747"NONE",
1748"NOOK",
1749"NOON",
1750"NORM",
1751"NOSE",
1752"NOTE",
1753"NOUN",
1754"NOVA",
1755"NUDE",
1756"NULL",
1757"NUMB",
1758"OATH",
1759"OBEY",
1760"OBOE",
1761"ODIN",
1762"OHIO",
1763"OILY",
1764"OINT",
1765"OKAY",
1766"OLAF",
1767"OLDY",
1768"OLGA",
1769"OLIN",
1770"OMAN",
1771"OMEN",
1772"OMIT",
1773"ONCE",
1774"ONES",
1775"ONLY",
1776"ONTO",
1777"ONUS",
1778"ORAL",
1779"ORGY",
1780"OSLO",
1781"OTIS",
1782"OTTO",
1783"OUCH",
1784"OUST",
1785"OUTS",
1786"OVAL",
1787"OVEN",
1788"OVER",
1789"OWLY",
1790"OWNS",
1791"QUAD",
1792"QUIT",
1793"QUOD",
1794"RACE",
1795"RACK",
1796"RACY",
1797"RAFT",
1798"RAGE",
1799"RAID",
1800"RAIL",
1801"RAIN",
1802"RAKE",
1803"RANK",
1804"RANT",
1805"RARE",
1806"RASH",
1807"RATE",
1808"RAVE",
1809"RAYS",
1810"READ",
1811"REAL",
1812"REAM",
1813"REAR",
1814"RECK",
1815"REED",
1816"REEF",
1817"REEK",
1818"REEL",
1819"REID",
1820"REIN",
1821"RENA",
1822"REND",
1823"RENT",
1824"REST",
1825"RICE",
1826"RICH",
1827"RICK",
1828"RIDE",
1829"RIFT",
1830"RILL",
1831"RIME",
1832"RING",
1833"RINK",
1834"RISE",
1835"RISK",
1836"RITE",
1837"ROAD",
1838"ROAM",
1839"ROAR",
1840"ROBE",
1841"ROCK",
1842"RODE",
1843"ROIL",
1844"ROLL",
1845"ROME",
1846"ROOD",
1847"ROOF",
1848"ROOK",
1849"ROOM",
1850"ROOT",
1851"ROSA",
1852"ROSE",
1853"ROSS",
1854"ROSY",
1855"ROTH",
1856"ROUT",
1857"ROVE",
1858"ROWE",
1859"ROWS",
1860"RUBE",
1861"RUBY",
1862"RUDE",
1863"RUDY",
1864"RUIN",
1865"RULE",
1866"RUNG",
1867"RUNS",
1868"RUNT",
1869"RUSE",
1870"RUSH",
1871"RUSK",
1872"RUSS",
1873"RUST",
1874"RUTH",
1875"SACK",
1876"SAFE",
1877"SAGE",
1878"SAID",
1879"SAIL",
1880"SALE",
1881"SALK",
1882"SALT",
1883"SAME",
1884"SAND",
1885"SANE",
1886"SANG",
1887"SANK",
1888"SARA",
1889"SAUL",
1890"SAVE",
1891"SAYS",
1892"SCAN",
1893"SCAR",
1894"SCAT",
1895"SCOT",
1896"SEAL",
1897"SEAM",
1898"SEAR",
1899"SEAT",
1900"SEED",
1901"SEEK",
1902"SEEM",
1903"SEEN",
1904"SEES",
1905"SELF",
1906"SELL",
1907"SEND",
1908"SENT",
1909"SETS",
1910"SEWN",
1911"SHAG",
1912"SHAM",
1913"SHAW",
1914"SHAY",
1915"SHED",
1916"SHIM",
1917"SHIN",
1918"SHOD",
1919"SHOE",
1920"SHOT",
1921"SHOW",
1922"SHUN",
1923"SHUT",
1924"SICK",
1925"SIDE",
1926"SIFT",
1927"SIGH",
1928"SIGN",
1929"SILK",
1930"SILL",
1931"SILO",
1932"SILT",
1933"SINE",
1934"SING",
1935"SINK",
1936"SIRE",
1937"SITE",
1938"SITS",
1939"SITU",
1940"SKAT",
1941"SKEW",
1942"SKID",
1943"SKIM",
1944"SKIN",
1945"SKIT",
1946"SLAB",
1947"SLAM",
1948"SLAT",
1949"SLAY",
1950"SLED",
1951"SLEW",
1952"SLID",
1953"SLIM",
1954"SLIT",
1955"SLOB",
1956"SLOG",
1957"SLOT",
1958"SLOW",
1959"SLUG",
1960"SLUM",
1961"SLUR",
1962"SMOG",
1963"SMUG",
1964"SNAG",
1965"SNOB",
1966"SNOW",
1967"SNUB",
1968"SNUG",
1969"SOAK",
1970"SOAR",
1971"SOCK",
1972"SODA",
1973"SOFA",
1974"SOFT",
1975"SOIL",
1976"SOLD",
1977"SOME",
1978"SONG",
1979"SOON",
1980"SOOT",
1981"SORE",
1982"SORT",
1983"SOUL",
1984"SOUR",
1985"SOWN",
1986"STAB",
1987"STAG",
1988"STAN",
1989"STAR",
1990"STAY",
1991"STEM",
1992"STEW",
1993"STIR",
1994"STOW",
1995"STUB",
1996"STUN",
1997"SUCH",
1998"SUDS",
1999"SUIT",
2000"SULK",
2001"SUMS",
2002"SUNG",
2003"SUNK",
2004"SURE",
2005"SURF",
2006"SWAB",
2007"SWAG",
2008"SWAM",
2009"SWAN",
2010"SWAT",
2011"SWAY",
2012"SWIM",
2013"SWUM",
2014"TACK",
2015"TACT",
2016"TAIL",
2017"TAKE",
2018"TALE",
2019"TALK",
2020"TALL",
2021"TANK",
2022"TASK",
2023"TATE",
2024"TAUT",
2025"TEAL",
2026"TEAM",
2027"TEAR",
2028"TECH",
2029"TEEM",
2030"TEEN",
2031"TEET",
2032"TELL",
2033"TEND",
2034"TENT",
2035"TERM",
2036"TERN",
2037"TESS",
2038"TEST",
2039"THAN",
2040"THAT",
2041"THEE",
2042"THEM",
2043"THEN",
2044"THEY",
2045"THIN",
2046"THIS",
2047"THUD",
2048"THUG",
2049"TICK",
2050"TIDE",
2051"TIDY",
2052"TIED",
2053"TIER",
2054"TILE",
2055"TILL",
2056"TILT",
2057"TIME",
2058"TINA",
2059"TINE",
2060"TINT",
2061"TINY",
2062"TIRE",
2063"TOAD",
2064"TOGO",
2065"TOIL",
2066"TOLD",
2067"TOLL",
2068"TONE",
2069"TONG",
2070"TONY",
2071"TOOK",
2072"TOOL",
2073"TOOT",
2074"TORE",
2075"TORN",
2076"TOTE",
2077"TOUR",
2078"TOUT",
2079"TOWN",
2080"TRAG",
2081"TRAM",
2082"TRAY",
2083"TREE",
2084"TREK",
2085"TRIG",
2086"TRIM",
2087"TRIO",
2088"TROD",
2089"TROT",
2090"TROY",
2091"TRUE",
2092"TUBA",
2093"TUBE",
2094"TUCK",
2095"TUFT",
2096"TUNA",
2097"TUNE",
2098"TUNG",
2099"TURF",
2100"TURN",
2101"TUSK",
2102"TWIG",
2103"TWIN",
2104"TWIT",
2105"ULAN",
2106"UNIT",
2107"URGE",
2108"USED",
2109"USER",
2110"USES",
2111"UTAH",
2112"VAIL",
2113"VAIN",
2114"VALE",
2115"VARY",
2116"VASE",
2117"VAST",
2118"VEAL",
2119"VEDA",
2120"VEIL",
2121"VEIN",
2122"VEND",
2123"VENT",
2124"VERB",
2125"VERY",
2126"VETO",
2127"VICE",
2128"VIEW",
2129"VINE",
2130"VISE",
2131"VOID",
2132"VOLT",
2133"VOTE",
2134"WACK",
2135"WADE",
2136"WAGE",
2137"WAIL",
2138"WAIT",
2139"WAKE",
2140"WALE",
2141"WALK",
2142"WALL",
2143"WALT",
2144"WAND",
2145"WANE",
2146"WANG",
2147"WANT",
2148"WARD",
2149"WARM",
2150"WARN",
2151"WART",
2152"WASH",
2153"WAST",
2154"WATS",
2155"WATT",
2156"WAVE",
2157"WAVY",
2158"WAYS",
2159"WEAK",
2160"WEAL",
2161"WEAN",
2162"WEAR",
2163"WEED",
2164"WEEK",
2165"WEIR",
2166"WELD",
2167"WELL",
2168"WELT",
2169"WENT",
2170"WERE",
2171"WERT",
2172"WEST",
2173"WHAM",
2174"WHAT",
2175"WHEE",
2176"WHEN",
2177"WHET",
2178"WHOA",
2179"WHOM",
2180"WICK",
2181"WIFE",
2182"WILD",
2183"WILL",
2184"WIND",
2185"WINE",
2186"WING",
2187"WINK",
2188"WINO",
2189"WIRE",
2190"WISE",
2191"WISH",
2192"WITH",
2193"WOLF",
2194"WONT",
2195"WOOD",
2196"WOOL",
2197"WORD",
2198"WORE",
2199"WORK",
2200"WORM",
2201"WORN",
2202"WOVE",
2203"WRIT",
2204"WYNN",
2205"YALE",
2206"YANG",
2207"YANK",
2208"YARD",
2209"YARN",
2210"YAWL",
2211"YAWN",
2212"YEAH",
2213"YEAR",
2214"YELL",
2215"YOGA",
2216"YOKE"
2217};
2218
2219
2220
2221
2222/*
2223 *------------------------------------------------------*
2224 *
2225 *      TrfInit_OTP_WORDS --
2226 *
2227 *      ------------------------------------------------*
2228 *      Register the conversion implemented in this file.
2229 *      ------------------------------------------------*
2230 *
2231 *      Sideeffects:
2232 *              As of 'Trf_Register'.
2233 *
2234 *      Result:
2235 *              A standard Tcl error code.
2236 *
2237 *------------------------------------------------------*
2238 */
2239
2240int
2241TrfInit_OTP_WORDS (interp)
2242Tcl_Interp* interp;
2243{
2244  TrfLock; /* THREADING: serialize initialization */
2245  convDefinition.options = Trf_ConverterOptions ();
2246  TrfUnlock;
2247
2248  return Trf_Register (interp, &convDefinition);
2249}
2250
2251/*
2252 *------------------------------------------------------*
2253 *
2254 *      CreateEncoder --
2255 *
2256 *      ------------------------------------------------*
2257 *      Allocate and initialize the control block of a
2258 *      data encoder.
2259 *      ------------------------------------------------*
2260 *
2261 *      Sideeffects:
2262 *              Allocates memory.
2263 *
2264 *      Result:
2265 *              An opaque reference to the control block.
2266 *
2267 *------------------------------------------------------*
2268 */
2269
2270static Trf_ControlBlock
2271CreateEncoder (writeClientData, fun, optInfo, interp, clientData)
2272ClientData    writeClientData;
2273Trf_WriteProc *fun;
2274Trf_Options   optInfo;
2275Tcl_Interp*   interp;
2276ClientData clientData;
2277{
2278  EncoderControl* c;
2279
2280  c = (EncoderControl*) ckalloc (sizeof (EncoderControl));
2281  c->write           = fun;
2282  c->writeClientData = writeClientData;
2283
2284  /* initialize conversion specific items here (otp_words encode) */
2285
2286  ClearEncoder ((Trf_ControlBlock) c, clientData);
2287
2288  return ((ClientData) c);
2289}
2290
2291/*
2292 *------------------------------------------------------*
2293 *
2294 *      DeleteEncoder --
2295 *
2296 *      ------------------------------------------------*
2297 *      Destroy the control block of an encoder.
2298 *      ------------------------------------------------*
2299 *
2300 *      Sideeffects:
2301 *              Releases the memory allocated by 'CreateEncoder'
2302 *
2303 *      Result:
2304 *              None.
2305 *
2306 *------------------------------------------------------*
2307 */
2308
2309static void
2310DeleteEncoder (ctrlBlock, clientData)
2311Trf_ControlBlock ctrlBlock;
2312ClientData clientData;
2313{
2314  EncoderControl* c = (EncoderControl*) ctrlBlock;
2315
2316  /* release conversion specific items here (otp_words encode) */
2317
2318  ckfree ((char*) c);
2319}
2320
2321/*
2322 *------------------------------------------------------*
2323 *
2324 *      Encode --
2325 *
2326 *      ------------------------------------------------*
2327 *      Encode the given character and write the result.
2328 *      ------------------------------------------------*
2329 *
2330 *      Sideeffects:
2331 *              As of the called WriteFun.
2332 *
2333 *      Result:
2334 *              Generated bytes implicitly via WriteFun.
2335 *              A standard Tcl error code.
2336 *
2337 *------------------------------------------------------*
2338 */
2339
2340static int
2341Encode (ctrlBlock, character, interp, clientData)
2342Trf_ControlBlock ctrlBlock;
2343unsigned int character;
2344Tcl_Interp* interp;
2345ClientData clientData;
2346{
2347  EncoderControl* c = (EncoderControl*) ctrlBlock;
2348
2349  /* execute conversion specific code here (otp_words encode) */
2350
2351  if (c -> charCount == 8) {
2352    int    i = FlushEncoder (ctrlBlock, interp, clientData);
2353
2354    if (i == TCL_OK)
2355      i = c -> write (c -> writeClientData, (unsigned char*) "\n", 1, interp);
2356
2357    if (i != TCL_OK)
2358      return i;
2359  }
2360
2361  c -> buf[c -> charCount++] = character;
2362
2363  return TCL_OK;
2364}
2365
2366/*
2367 *------------------------------------------------------*
2368 *
2369 *      EncodeBuffer --
2370 *
2371 *      ------------------------------------------------*
2372 *      Encode the given buffer and write the result.
2373 *      ------------------------------------------------*
2374 *
2375 *      Sideeffects:
2376 *              As of the called WriteFun.
2377 *
2378 *      Result:
2379 *              Generated bytes implicitly via WriteFun.
2380 *              A standard Tcl error code.
2381 *
2382 *------------------------------------------------------*
2383 */
2384
2385static int
2386EncodeBuffer (ctrlBlock, buffer, bufLen, interp, clientData)
2387Trf_ControlBlock ctrlBlock;
2388unsigned char* buffer;
2389int bufLen;
2390Tcl_Interp* interp;
2391ClientData clientData;
2392{
2393  /* EncoderControl* c = (EncoderControl*) ctrlBlock; unused */
2394  /* execute conversion specific code here (otp_words encode) */
2395
2396  int    i = TCL_OK;
2397
2398  while (bufLen-- > 0) {
2399    if ((i = Encode (ctrlBlock, *buffer++ & 0xff, interp, clientData))
2400	!= TCL_OK)
2401      break;
2402  }
2403
2404  return i;
2405}
2406
2407/*
2408 *------------------------------------------------------*
2409 *
2410 *      FlushEncoder --
2411 *
2412 *      ------------------------------------------------*
2413 *      Encode an incomplete character sequence (if possible).
2414 *      ------------------------------------------------*
2415 *
2416 *      Sideeffects:
2417 *              As of the called WriteFun.
2418 *
2419 *      Result:
2420 *              Generated bytes implicitly via WriteFun.
2421 *              A standard Tcl error code.
2422 *
2423 *------------------------------------------------------*
2424 */
2425
2426static int
2427FlushEncoder (ctrlBlock, interp, clientData)
2428Trf_ControlBlock ctrlBlock;
2429Tcl_Interp* interp;
2430ClientData clientData;
2431{
2432  EncoderControl* c = (EncoderControl*) ctrlBlock;
2433
2434  /* execute conversion specific code here (otp_words encode) */
2435
2436  int    i, p;
2437  char   cp[10];
2438
2439  switch (c -> charCount) {
2440  case 8:
2441    break;
2442
2443  case 0:
2444    return TCL_OK;
2445
2446  default:
2447    if (interp) {
2448      Tcl_ResetResult (interp);
2449      Tcl_AppendResult (interp,
2450			"input string must be a multiple of 64-bits",
2451			(char *) NULL);
2452    }
2453    return TCL_ERROR;
2454  }
2455
2456  memset (cp, '\0', sizeof cp);
2457  memcpy (cp, c -> buf, sizeof c -> buf);
2458
2459  for (p = 0, i = 0; i < 64; i += 2)
2460    p += extract (cp, i, 2);
2461
2462  cp[sizeof c -> buf] = (char) (p << 6);
2463
2464  for (p = 0; p <= 55; p += 11) {
2465    char    *w = &Wp[extract (cp, p, 11)][0];
2466    char     buf[5];
2467
2468    memset (buf, '\0', sizeof buf);
2469
2470    for (i = 0; i < 4; i++) {
2471      buf[i] = *w++;
2472    }
2473
2474    i = c -> write (c -> writeClientData, (unsigned char*) buf, strlen (buf),
2475		    interp);
2476    if ((i == TCL_OK) && (p != 55))
2477      i = c -> write (c -> writeClientData, (unsigned char*) " ", 1, interp);
2478    if (i != TCL_OK)
2479      return i;
2480  }
2481
2482  ClearEncoder (ctrlBlock, clientData);
2483
2484  return TCL_OK;
2485}
2486
2487/*
2488 *------------------------------------------------------*
2489 *
2490 *      ClearEncoder --
2491 *
2492 *      ------------------------------------------------*
2493 *      Discard an incomplete character sequence.
2494 *      ------------------------------------------------*
2495 *
2496 *      Sideeffects:
2497 *              See above.
2498 *
2499 *      Result:
2500 *              None.
2501 *
2502 *------------------------------------------------------*
2503 */
2504
2505static void
2506ClearEncoder (ctrlBlock, clientData)
2507Trf_ControlBlock ctrlBlock;
2508ClientData clientData;
2509{
2510  EncoderControl* c = (EncoderControl*) ctrlBlock;
2511
2512  /* execute conversion specific code here (otp_words encode) */
2513
2514  c -> charCount = 0;
2515  memset (c -> buf, '\0', sizeof c -> buf);
2516}
2517
2518/*
2519 *------------------------------------------------------*
2520 *
2521 *      CreateDecoder --
2522 *
2523 *      ------------------------------------------------*
2524 *      Allocate and initialize the control block of a
2525 *      data decoder.
2526 *      ------------------------------------------------*
2527 *
2528 *      Sideeffects:
2529 *              Allocates memory.
2530 *
2531 *      Result:
2532 *              An opaque reference to the control block.
2533 *
2534 *------------------------------------------------------*
2535 */
2536
2537static Trf_ControlBlock
2538CreateDecoder (writeClientData, fun, optInfo, interp, clientData)
2539ClientData    writeClientData;
2540Trf_WriteProc *fun;
2541Trf_Options   optInfo;
2542Tcl_Interp*   interp;
2543ClientData clientData;
2544{
2545  DecoderControl* c;
2546
2547  c = (DecoderControl*) ckalloc (sizeof (DecoderControl));
2548  c->write           = fun;
2549  c->writeClientData = writeClientData;
2550
2551  /* initialize conversion specific items here (otp_words decode) */
2552
2553  ClearDecoder ((Trf_ControlBlock) c, clientData);
2554
2555  return ((ClientData) c);
2556}
2557
2558/*
2559 *------------------------------------------------------*
2560 *
2561 *      DeleteDecoder --
2562 *
2563 *      ------------------------------------------------*
2564 *      Destroy the control block of an decoder.
2565 *      ------------------------------------------------*
2566 *
2567 *      Sideeffects:
2568 *              Releases the memory allocated by 'CreateDecoder'
2569 *
2570 *      Result:
2571 *              None.
2572 *
2573 *------------------------------------------------------*
2574 */
2575
2576static void
2577DeleteDecoder (ctrlBlock, clientData)
2578Trf_ControlBlock ctrlBlock;
2579ClientData clientData;
2580{
2581  DecoderControl* c = (DecoderControl*) ctrlBlock;
2582
2583  /* release conversion specific items here (otp_words decode) */
2584
2585  ckfree ((char*) c);
2586}
2587
2588/*
2589 *------------------------------------------------------*
2590 *
2591 *      Decode --
2592 *
2593 *      ------------------------------------------------*
2594 *      Decode the given character and write the result.
2595 *      ------------------------------------------------*
2596 *
2597 *      Sideeffects:
2598 *              As of the called WriteFun.
2599 *
2600 *      Result:
2601 *              Generated bytes implicitly via WriteFun.
2602 *              A standard Tcl error code.
2603 *
2604 *------------------------------------------------------*
2605 */
2606
2607static int
2608Decode (ctrlBlock, character, interp, clientData)
2609Trf_ControlBlock ctrlBlock;
2610unsigned int character;
2611Tcl_Interp* interp;
2612ClientData clientData;
2613{
2614  DecoderControl* c = (DecoderControl*) ctrlBlock;
2615
2616  /* execute conversion specific code here (otp_words decode) */
2617
2618  char x = character & 0xff;
2619  char *cp;
2620
2621  if (c -> wordCount == 6) {
2622    int    i = FlushDecoder (ctrlBlock, interp, clientData);
2623
2624    if (i != TCL_OK)
2625      return i;
2626  }
2627
2628  if (!isascii (x)) {
2629    if (interp) {
2630      Tcl_ResetResult (interp);
2631      Tcl_AppendResult (interp, "invalid character", (char *) NULL);
2632    }
2633    return TCL_ERROR;
2634  }
2635
2636  switch (x) {
2637  case ' ':  /* fall through */
2638  case '\t': /* fall through */
2639  case '\n': /* fall through */
2640  case ',':
2641    if (c -> charCount == 0) {
2642      if (interp) {
2643	Tcl_ResetResult (interp);
2644	Tcl_AppendResult (interp, "empty word", (char *) NULL);
2645      }
2646      return TCL_ERROR;
2647    }
2648    c -> charCount = 0;
2649    c -> wordCount++;
2650    return TCL_OK;
2651
2652  default:
2653    if (c -> charCount == 4) {
2654      if (interp) {
2655	Tcl_ResetResult (interp);
2656	Tcl_AppendResult (interp, "word too long", (char *) NULL);
2657      }
2658      return TCL_ERROR;
2659    }
2660    if (islower (x)) {
2661      x = toupper (x);
2662    }
2663    break;
2664  }
2665
2666  switch (x) {
2667  case '5':
2668    x = 'S';
2669    break;
2670
2671  case '1':
2672    x = 'L';
2673    break;
2674
2675  case '0':
2676    x = 'O';
2677    break;
2678  }
2679
2680  cp = &(c -> words[c -> wordCount][0]);
2681  cp[c -> charCount++] = x;
2682  cp[c -> charCount] = '\0';
2683
2684  return TCL_OK;
2685}
2686
2687/*
2688 *------------------------------------------------------*
2689 *
2690 *      DecodeBuffer --
2691 *
2692 *      ------------------------------------------------*
2693 *      Decode the given buffer and write the result.
2694 *      ------------------------------------------------*
2695 *
2696 *      Sideeffects:
2697 *              As of the called WriteFun.
2698 *
2699 *      Result:
2700 *              Generated bytes implicitly via WriteFun.
2701 *              A standard Tcl error code.
2702 *
2703 *------------------------------------------------------*
2704 */
2705
2706static int
2707DecodeBuffer (ctrlBlock, buffer, bufLen, interp, clientData)
2708Trf_ControlBlock ctrlBlock;
2709unsigned char* buffer;
2710int bufLen;
2711Tcl_Interp* interp;
2712ClientData clientData;
2713{
2714  /* DecoderControl* c = (DecoderControl*) ctrlBlock; unused */
2715  /* execute conversion specific code here (otp_words decode) */
2716
2717  int    i = TCL_OK;
2718
2719  while (bufLen-- > 0) {
2720    if ((i = Decode (ctrlBlock, *buffer++ & 0xff, interp, clientData))
2721	!= TCL_OK)
2722      break;
2723  }
2724
2725  return i;
2726}
2727
2728/*
2729 *------------------------------------------------------*
2730 *
2731 *      FlushDecoder --
2732 *
2733 *      ------------------------------------------------*
2734 *      Decode an incomplete character sequence (if possible).
2735 *      ------------------------------------------------*
2736 *
2737 *      Sideeffects:
2738 *              As of the called WriteFun.
2739 *
2740 *      Result:
2741 *              Generated bytes implicitly via WriteFun.
2742 *              A standard Tcl error code.
2743 *
2744 *------------------------------------------------------*
2745 */
2746
2747static int
2748FlushDecoder (ctrlBlock, interp, clientData)
2749Trf_ControlBlock ctrlBlock;
2750Tcl_Interp* interp;
2751ClientData clientData;
2752{
2753  DecoderControl* c = (DecoderControl*) ctrlBlock;
2754
2755  /* execute conversion specific code here (otp_words decode) */
2756
2757  int    i;
2758  unsigned long p;
2759  char   b[9];
2760
2761  if ((c -> wordCount == 5) && (c -> charCount > 0))
2762    c -> wordCount = 6;
2763
2764  switch (c -> wordCount) {
2765  case 6:
2766    break;
2767
2768  case 0:
2769    if (c -> charCount == 0)
2770      return TCL_OK;
2771    /* else fall through... */
2772  default:
2773    if (interp) {
2774      Tcl_ResetResult (interp);
2775      Tcl_AppendResult (interp, "too few words", (char *) NULL);
2776    }
2777    return TCL_ERROR;
2778  }
2779
2780  memset (b, '\0', sizeof b);
2781  for (c -> wordCount = 0, p = 0;
2782       c -> wordCount < 6;
2783       c -> wordCount++, p += 11) {
2784    int    lo, hi;
2785    int    v;
2786    char  *w = &c -> words[c -> wordCount][0];
2787
2788    if (strlen (w) < 4)
2789      lo = 0, hi = 570;
2790    else
2791      lo = 571, hi = 2047;
2792    if ((v = wsrch (w, lo, hi)) < 0) {
2793      if (interp) {
2794	Tcl_ResetResult (interp);
2795	Tcl_AppendResult (interp, "unknown word \"", w, "\"",
2796			  (char *) NULL);
2797      }
2798      return TCL_ERROR;
2799    }
2800    insert (b, v, p, 11);
2801  }
2802
2803  for (p = 0, i = 0; i < 64; i += 2)
2804    p += extract (b, i, 2);
2805
2806  if ((p & 0x03) != extract (b, 64, 2)) {
2807    if (interp) {
2808      Tcl_ResetResult (interp);
2809      Tcl_AppendResult (interp, "parity error", (char *) NULL);
2810    }
2811    return TCL_ERROR;
2812  }
2813
2814  i = c -> write (c -> writeClientData, (unsigned char*) b, 8, interp);
2815  if (i != TCL_OK)
2816    return i;
2817
2818  ClearDecoder (ctrlBlock, clientData);
2819
2820  return TCL_OK;
2821}
2822
2823/*
2824 *------------------------------------------------------*
2825 *
2826 *      ClearDecoder --
2827 *
2828 *      ------------------------------------------------*
2829 *      Discard an incomplete character sequence.
2830 *      ------------------------------------------------*
2831 *
2832 *      Sideeffects:
2833 *              See above.
2834 *
2835 *      Result:
2836 *              None.
2837 *
2838 *------------------------------------------------------*
2839 */
2840
2841static void
2842ClearDecoder (ctrlBlock, clientData)
2843Trf_ControlBlock ctrlBlock;
2844ClientData clientData;
2845{
2846  DecoderControl* c = (DecoderControl*) ctrlBlock;
2847
2848  /* execute conversion specific code here (otp_words decode) */
2849
2850  c -> charCount = 0;
2851  c -> wordCount = 0;
2852  memset (c -> words, '\0', sizeof c -> words);
2853}
2854
2855
2856/* subroutines taken from the module put.c in the original Bellcore reference
2857   distribution */
2858
2859
2860/* Dictionary binary search */
2861static int
2862wsrch(w,low,high)
2863char *w;
2864int low, high;
2865{
2866  int i,j;
2867
2868  for(;;) {
2869    i = (low + high)/2;
2870    if((j = strncmp(w,Wp[i],4)) == 0)
2871      return i;       /* Found it */
2872    if(high == low+1){
2873      /* Avoid effects of integer truncation in /2 */
2874      if(strncmp(w,Wp[high],4) == 0)
2875	return high;
2876      else
2877	return -1;
2878    }
2879    if(low >= high)
2880      return -1;      /* I don't *think* this can happen...*/
2881    if(j < 0)
2882      high = i;       /* Search lower half */
2883    else
2884      low = i;        /* Search upper half */
2885  }
2886}
2887
2888static void
2889insert(s, x, start, length)
2890char *s;
2891int x;
2892int  start, length;
2893{
2894  unsigned char cl;
2895  unsigned char cc;
2896  unsigned char cr;
2897  unsigned long y;
2898  int shift;
2899
2900  assert(length <= 11);
2901  assert(start >= 0);
2902  assert(length >= 0);
2903  assert(start +length <= 66);
2904
2905  shift = ((8  -(( start + length) % 8))%8);
2906  y = (long) (x << shift);
2907  cl = (unsigned char) ((y >> 16) & 0xff);
2908  cc = (unsigned char) ((y >> 8) & 0xff);
2909  cr = (unsigned char) (y & 0xff);
2910  if(shift + length > 16) {
2911    s[start /8] |= cl;
2912    s[start/8 +1] |= cc;
2913    s[start/8 +2] |= cr;
2914  } else if(shift +length > 8) {
2915    s[start/8] |= cc;
2916    s[start/8 + 1] |= cr;
2917  } else {
2918    s[start/8] |= cr;
2919  }
2920}
2921
2922/* Extract 'length' bits from the char array 's' starting with bit 'start' */
2923static unsigned long
2924extract(s, start, length)
2925char *s;
2926int start, length;
2927{
2928  unsigned char cl;
2929  unsigned char cc;
2930  unsigned char cr;
2931  unsigned long x;
2932
2933  assert(length <= 11);
2934  assert(start >= 0);
2935  assert(length >= 0);
2936  assert(start +length <= 66);
2937
2938  cl = s[start/8];
2939  cc = s[start/8 +1];
2940  cr = s[start/8 +2];
2941  x = ((long)(cl<<8 | cc) <<8  | cr) ;
2942  x = x >> (24 - (length + (start %8)));
2943  x =( x & (0xffff >> (16-length) )   );
2944  return(x);
2945}
2946
2947