2 Copyright (c) 2005-2018, John Hurst
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 /*! \file kmrandgen.cpp
29 \brief psuedo-random number generation utility
33 #include <KM_fileio.h>
39 const ui32_t RandBlockSize = 16;
40 const char* PROGRAM_NAME = "kmrandgen";
42 // Increment the iterator, test for an additional non-option command line argument.
43 // Causes the caller to return if there are no remaining arguments or if the next
44 // argument begins with '-'.
45 #define TEST_EXTRA_ARG(i,c) if ( ++i >= argc || argv[(i)][0] == '-' ) \
47 fprintf(stderr, "Argument not found for option -%c.\n", (c)); \
51 static const char* _letterwords_list[] = {
52 "Alfa", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot", "Golf",
53 "Hotel", "India", "Juliett", "Kilo",
54 "Lima", "Mike", "November", "Oscar", "Papa",
55 "Quebec", "Romeo", "Sierra",
56 "Tango", "Uniform", "Victor",
62 static const char* _word_list[] = {
63 "ABED", "ABET", "ABEY", "ABLE", "ABUT", "ACE", "ACHE", "ACID",
64 "ACME", "ACRE", "ACT", "ACTS", "ADD", "ADDS", "ADO", "ADRY",
65 "AEON", "AERO", "AFAR", "AFRO", "AGAR", "AGE", "AGED", "AGIO",
66 "AGO" , "AHEM", "AHOY", "AID", "AIDE", "AIL", "AIM", "AIR",
67 "AIRY", "AJAR", "AKIN", "ALAS", "ALCO", "ALE", "ALF", "ALFA",
68 "ALL" , "ALLY", "ALMA", "ALMS", "ALOE", "ALOW", "ALSO", "ALT",
69 "ALTO", "ALUM", "AM", "AMES", "AMID", "AN", "AND", "ANEW",
70 "ANT" , "ANTE", "ANY", "APE", "APEX", "APT", "AQUA", "ARC",
71 "ARCH", "ARE", "AREA", "ARGO", "ARID", "ARK", "ARM", "ARMS",
72 "ART" , "ARTS", "ARTY", "AS", "ASH", "ASK", "ASKS", "ASP",
73 "AT" , "ATE", "ATOM", "ATOP", "AUNT", "AURA", "AUTO", "AVER",
74 "AVID", "AVOW", "AWAY", "AWE", "AWL", "AXE", "AXED", "AXES",
75 "AXIS", "AXLE", "AXON", "AYE", "BABE", "BABU", "BABY", "BACK",
76 "BAD" , "BADE", "BAG", "BAIL", "BAIT", "BAKE", "BALD", "BALE",
77 "BALK", "BALL", "BALM", "BAM", "BAN", "BAND", "BANE", "BANG",
78 "BANK", "BAR", "BARB", "BARD", "BARE", "BARK", "BARM", "BARN",
79 "BARU", "BASE", "BASH", "BASK", "BASS", "BAT", "BATH", "BATS",
80 "BAWL", "BAY", "BE", "BEAD", "BEAK", "BEAM", "BEAN", "BEAR",
81 "BEAT", "BEAU", "BECK", "BED", "BEE", "BEEF", "BEEK", "BEEN",
82 "BEER", "BEES", "BEET", "BEG", "BELL", "BELT", "BEND", "BENT",
83 "BERG", "BERM", "BEST", "BET", "BETA", "BIAS", "BIB", "BID",
84 "BIDE", "BIER", "BIG", "BIKE", "BILE", "BILK", "BILL", "BIN",
85 "BIND", "BING", "BIOS", "BIRD", "BIT", "BITE", "BITS", "BIZ",
86 "BLAB", "BLED", "BLOB", "BLOC", "BLOK", "BLOT", "BLUE", "BLUR",
87 "BOA" , "BOAR", "BOAT", "BOB", "BOCE", "BOCK", "BODE", "BODY",
88 "BOG" , "BOIL", "BOLD", "BOLO", "BOLT", "BOND", "BONE", "BONY",
89 "BOO" , "BOOK", "BOOL", "BOOM", "BOON", "BOOR", "BOOT", "BORE",
90 "BORG", "BORN", "BOSS", "BOTH", "BOUT", "BOW", "BOWL", "BOXY",
91 "BOY" , "BRAG", "BRAN", "BRAT", "BRAY", "BRED", "BREW", "BRIE",
92 "BRIG", "BRIM", "BRIT", "BROW", "BUCK", "BUD", "BUFF", "BUG",
93 "BULB", "BULK", "BULL", "BUMP", "BUN", "BUNK", "BUNT", "BUOY",
94 "BUR" , "BURG", "BURL", "BURN", "BURP", "BURR", "BURY", "BUS",
95 "BUSH", "BUSK", "BUSS", "BUSY", "BUT", "BUY", "BY", "BYE",
96 "BYTE", "CAB", "CAD", "CAFE", "CAGE", "CAIN", "CAKE", "CAL",
97 "CALF", "CALL", "CALM", "CAM", "CAMP", "CAN", "CANE", "CANT",
98 "CAP" , "CAPE", "CAR", "CARD", "CARE", "CARP", "CART", "CASE",
99 "CASH", "CASK", "CAST", "CAT", "CAVE", "CEDE", "CEIL", "CELL",
100 "CENT", "CHAP", "CHAT", "CHEF", "CHEW", "CHIC", "CHIN", "CHIP",
101 "CHIT", "CHOP", "CHOW", "CHUG", "CHUM", "CINE", "CITE", "CITY",
102 "CLAD", "CLAM", "CLAN", "CLAP", "CLAW", "CLAY", "CLEF", "CLIP",
103 "CLOD", "CLOG", "CLOT", "CLOY", "CLUB", "CLUE", "COAL", "COAT",
104 "COAX", "COB", "COD", "CODA", "CODE", "COG", "COIL", "COIN",
105 "COKE", "COLA", "COLD", "COLE", "COLT", "COMB", "COOK", "COOL",
106 "COP" , "COPE", "COPY", "CORD", "CORE", "CORK", "CORN", "CORP",
107 "COST", "COSY", "COT", "COUP", "COVE", "COW", "COWL", "COY",
108 "COZY", "CRAB", "CRAG", "CRAM", "CRAW", "CRAY", "CREW", "CRIB",
109 "CROC", "CROP", "CROW", "CRUX", "CRY", "CUB", "CUBE", "CUE",
110 "CUFF", "CUP", "CUR", "CURB", "CURD", "CURE", "CURL", "CURT",
111 "CUT" , "CUTE", "CYAN", "CYST", "CZAR", "DAB", "DAD", "DADA",
112 "DADO", "DAIS", "DALE", "DALI", "DAM", "DAME", "DAMP", "DARE",
113 "DARK", "DARN", "DART", "DASH", "DATA", "DATE", "DAUB", "DAWN",
114 "DAY" , "DAYS", "DAZE", "DAZY", "DEAL", "DEAR", "DEBT", "DECK",
115 "DEED", "DEEM", "DEER", "DEFT", "DEFY", "DELI", "DELL", "DEMO",
116 "DEN" , "DENT", "DENY", "DESK", "DEW", "DIAL", "DIBS", "DICE",
117 "DID" , "DIG", "DIGS", "DILL", "DIM", "DIME", "DIN", "DINE",
118 "DIP" , "DIRE", "DIRT", "DISC", "DISH", "DISK", "DIVE", "DO",
119 "DOCK", "DOE", "DOES", "DOG", "DOGS", "DOLE", "DOLL", "DOME",
120 "DON" , "DONE", "DOOM", "DOOR", "DORM", "DOSE", "DOT", "DOTE",
121 "DOUR", "DOVE", "DOWN", "DOZE", "DRAB", "DRAG", "DRAM", "DRAT",
122 "DRAW", "DREW", "DRIB", "DRIP", "DROP", "DRUB", "DRUM", "DRY",
123 "DUAL", "DUB", "DUBS", "DUCK", "DUCT", "DUD", "DUE", "DUET",
124 "DUG" , "DUKE", "DULL", "DULY", "DUMP", "DUNE", "DUNK", "DUPE",
125 "DUSK", "DUST", "DUTY", "DYAD", "EACH", "EAR", "EARL", "EARN",
126 "EASE", "EAST", "EASY", "EAT", "EATS", "EBB", "ECHO", "EDDY",
127 "EDGE", "EDGY", "EDIT", "EEL", "EGG", "EGO", "ELF", "ELK",
128 "ELM" , "ELSE", "EMIT", "END", "ENDS", "ENSE", "ENVY", "EPIC",
129 "ERA" , "ERG", "EVE", "EVEN", "EVER", "EWE", "EXAM", "EXIT",
130 "EYE" , "EYED", "FACE", "FACT", "FAD", "FADE", "FADY", "FAIL",
131 "FAIR", "FAKE", "FALL", "FAME", "FAN", "FANG", "FAR", "FARE",
132 "FARM", "FAST", "FATE", "FAWN", "FAZE", "FEAR", "FEAT", "FED",
133 "FEE" , "FEED", "FEEL", "FEET", "FELL", "FELT", "FEND", "FERN",
134 "FEST", "FEUD", "FEW", "FEZ", "FIAT", "FIB", "FIFE", "FIG",
135 "FIGS", "FILE", "FILL", "FILM", "FIN", "FIND", "FINE", "FINK",
136 "FIR" , "FIRE", "FIRM", "FISH", "FIT", "FITS", "FIVE", "FIX",
137 "FLAG", "FLAK", "FLAP", "FLAT", "FLAW", "FLAX", "FLED", "FLEE",
138 "FLEW", "FLEX", "FLIP", "FLIT", "FLOE", "FLOG", "FLOP", "FLOW",
139 "FLU" , "FLUB", "FLUE", "FLUX", "FLY", "FOAL", "FOAM", "FOE",
140 "FOG" , "FOIL", "FOLD", "FOLK", "FOND", "FONT", "FOOD", "FOOL",
141 "FOOT", "FORD", "FORE", "FORK", "FORM", "FORT", "FOUL", "FOUR",
142 "FOW" , "FOWL", "FOX", "FRAY", "FRED", "FREE", "FRET", "FROG",
143 "FROM", "FRY", "FUEL", "FUGU", "FULL", "FUME", "FUN", "FUND",
144 "FUNK", "FUR", "FURY", "FUSE", "FUSS", "FUZZ", "GAB", "GAG",
145 "GAGE", "GAIN", "GAIT", "GAL", "GALA", "GALE", "GALL", "GAME",
146 "GAMY", "GANG", "GAP", "GARB", "GAS", "GASP", "GATE", "GAVE",
147 "GAWK", "GAZE", "GEAR", "GEEK", "GEL", "GEM", "GENE", "GENT",
148 "GERM", "GET", "GETS", "GIFT", "GIG", "GILD", "GILL", "GILT",
149 "GIN" , "GIRD", "GIRL", "GIST", "GIT", "GIVE", "GLAD", "GLAM",
150 "GLEE", "GLEN", "GLIB", "GLOB", "GLOM", "GLOP", "GLOW", "GLUE",
151 "GLUG", "GLUM", "GLUT", "GNAT", "GNAW", "GNU", "GO", "GOAD",
152 "GOAL", "GOAT", "GOB", "GOBO", "GOES", "GOLD", "GOLF", "GONE",
153 "GONG", "GOO", "GOOD", "GOOF", "GOON", "GOSH", "GOT", "GOWN",
154 "GRAB", "GRAD", "GRAM", "GRAY", "GREW", "GREY", "GRID", "GRIM",
155 "GRIN", "GRIP", "GRIT", "GROG", "GROW", "GRUB", "GRUE", "GULF",
156 "GULL", "GULP", "GUM", "GUNK", "GURU", "GUSH", "GUST", "GUT",
157 "GUY" , "GYM", "HACK", "HAD", "HAH", "HAIL", "HAIR", "HALE",
158 "HALF", "HALL", "HALO", "HALT", "HAM", "HAND", "HANG", "HANK",
159 "HARD", "HARE", "HARK", "HARM", "HARP", "HAS", "HASH", "HASP",
160 "HAT" , "HATH", "HAUL", "HAVE", "HAWK", "HAY", "HAZE", "HAZY",
161 "HE" , "HEAL", "HEAP", "HEAR", "HEAT", "HECK", "HEED", "HEEL",
162 "HEFT", "HEIR", "HELD", "HELM", "HELP", "HEM", "HEMP", "HEN",
163 "HER" , "HERB", "HERD", "HERE", "HERO", "HERS", "HEW", "HEWN",
164 "HEX" , "HEY", "HI", "HID", "HIDE", "HIGH", "HIKE", "HILL",
165 "HILT", "HIM", "HIND", "HINT", "HIP", "HIRE", "HIS", "HISS",
166 "HIT" , "HIVE", "HOAX", "HOCK", "HOE", "HOG", "HOLD", "HOLE",
167 "HOME", "HONE", "HONK", "HOOD", "HOOF", "HOOK", "HOOP", "HOOT",
168 "HOP" , "HOPE", "HORN", "HOSE", "HOST", "HOT", "HOUR", "HOW",
169 "HOWL", "HUB", "HUE", "HUED", "HUFF", "HUG", "HUGE", "HUH",
170 "HULK", "HULL", "HUM", "HUNK", "HUNT", "HURL", "HURT", "HUSH",
171 "HUSK", "HUT", "HYMN", "HYPO", "ICE", "ICON", "ICY", "ID",
172 "IDEA", "IDES", "IDLE", "IDLY", "IDOL", "IF", "IFFY", "ILK",
173 "ILL" , "IMP", "IN", "INCH", "INDY", "INK", "INN", "INTO",
174 "ION" , "IONS", "IOTA", "IRIS", "IRON", "IS", "ISLE", "IT",
175 "ITEM", "IVY", "JADE", "JAG", "JAM", "JAR", "JAVA", "JAW",
176 "JAZZ", "JEDI", "JEEP", "JEST", "JET", "JIB", "JIG", "JILT",
177 "JIVE", "JOB", "JOBS", "JOG", "JOIN", "JOKE", "JOLT", "JOT",
178 "JUDO", "JUG", "JULY", "JUMP", "JUNE", "JUNK", "JURY", "JUST",
179 "JUT" , "KAHN", "KALE", "KANE", "KEEL", "KEEN", "KEEP", "KEG",
180 "KELP", "KENO", "KEPT", "KERF", "KERN", "KEY", "KEYS", "KHAN",
181 "KICK", "KID", "KILN", "KILO", "KILT", "KIN", "KIND", "KING",
182 "KINO", "KIT", "KITE", "KNEE", "KNEW", "KNIT", "KNOT", "KNOW",
183 "KOI" , "LAB", "LACE", "LACK", "LAD", "LADY", "LAG", "LAIR",
184 "LAKE", "LAM", "LAMB", "LAME", "LAMP", "LAND", "LANE", "LAP",
185 "LARD", "LARK", "LASH", "LASS", "LAST", "LATE", "LAUD", "LAVA",
186 "LAW" , "LAWN", "LAWS", "LAX", "LAY", "LAZY", "LEAD", "LEAF",
187 "LEAK", "LEAN", "LEAP", "LED", "LEDE", "LEED", "LEEK", "LEFT",
188 "LEG" , "LEND", "LENS", "LENT", "LESS", "LEST", "LET", "LETS",
189 "LIAR", "LID", "LIEN", "LIEU", "LIFE", "LIFO", "LIFT", "LIKE",
190 "LILT", "LILY", "LIMA", "LIME", "LINE", "LINK", "LINT", "LION",
191 "LIP" , "LIST", "LIT", "LIVE", "LOAD", "LOAF", "LOAN", "LOB",
192 "LOBE", "LOCK", "LODE", "LOFT", "LOG", "LOGE", "LOIN", "LONE",
193 "LONG", "LOOK", "LOON", "LOOP", "LOOT", "LORE", "LOSE", "LOSS",
194 "LOST", "LOT", "LOTS", "LOUD", "LOVE", "LOW", "LOX", "LUCK",
195 "LUG" , "LULL", "LUMP", "LUSH", "LUTE", "LUX", "LYE", "LYNX",
196 "MAD" , "MADE", "MAID", "MAIL", "MAIN", "MAKE", "MALE", "MALL",
197 "MALT", "MAN", "MANY", "MAP", "MARE", "MARK", "MART", "MASH",
198 "MASK", "MASS", "MAST", "MAT", "MATE", "MATH", "MAUL", "MAW",
199 "MAY" , "MAZE", "ME", "MEAD", "MEAL", "MEAN", "MEAT", "MEEK",
200 "MEET", "MELD", "MELT", "MEME", "MEMO", "MEN", "MEND", "MENU",
201 "MERE", "MESH", "MESS", "MET", "MICA", "MICE", "MID", "MIKE",
202 "MILD", "MILE", "MILK", "MILL", "MIME", "MIND", "MINE", "MINK",
203 "MINT", "MIRE", "MISS", "MIST", "MITE", "MITT", "MIX", "MOAT",
204 "MOB" , "MOCK", "MOD", "MODE", "MOLD", "MOLE", "MOLT", "MONK",
205 "MONO", "MOOD", "MOON", "MOOT", "MOP", "MOPE", "MORE", "MORN",
206 "MOSS", "MOST", "MOTE", "MOTH", "MOVE", "MOW", "MOWN", "MUCH",
207 "MUCK", "MUD", "MUG", "MULE", "MULL", "MULT", "MUM", "MUMP",
208 "MURK", "MUSE", "MUSH", "MUSK", "MUSS", "MUST", "MUTE", "MUTT",
209 "MY" , "MYTH", "NAB", "NAG", "NAIF", "NAIL", "NAME", "NAP",
210 "NAPE", "NARY", "NEAR", "NEAT", "NEE", "NEED", "NEON", "NEST",
211 "NET" , "NEW", "NEWS", "NEWT", "NEXT", "NIB", "NIBS", "NICE",
212 "NICK", "NIL", "NINE", "NIX", "NO", "NOD", "NODE", "NONE",
213 "NOOK", "NOON", "NOPE", "NOR", "NORI", "NORM", "NOSE", "NOSY",
214 "NOT" , "NOTE", "NOUN", "NOVA", "NOW", "NULL", "NUMB", "NUN",
215 "OAK" , "OAR", "OAT", "OATH", "OBOE", "ODD", "ODDS", "ODE",
216 "OF" , "OFF", "OFT", "OGRE", "OH", "OHIO", "OHM", "OIL",
217 "OILY", "OK", "OKAY", "OKRA", "OLD", "OMEN", "OMIT", "ON",
218 "ONCE", "ONE", "ONES", "ONLY", "ONTO", "ONUS", "ONYX", "OPAL",
219 "OPEN", "OPT", "OPUS", "OR", "ORB", "ORC", "ORE", "OUCH",
220 "OUR" , "OURS", "OUST", "OUT", "OUTS", "OVAL", "OVEN", "OVER",
221 "OWE" , "OWL", "OWN", "OWNS", "OX", "PACK", "PACT", "PAD",
222 "PAGE", "PAIL", "PAIN", "PAIR", "PAL", "PALE", "PALL", "PALM",
223 "PAN" , "PANE", "PAPA", "PAR", "PARK", "PART", "PASS", "PAST",
224 "PAT" , "PATE", "PATH", "PAVE", "PAW", "PAWN", "PAX", "PAY",
225 "PEA" , "PEAK", "PEAL", "PEAR", "PEAT", "PECK", "PEEL", "PEEN",
226 "PEER", "PELT", "PEN", "PEND", "PENT", "PEP", "PER", "PERK",
227 "PEST", "PET", "PEW", "PHI", "PI", "PICK", "PIE", "PIER",
228 "PIG" , "PIKE", "PILE", "PILL", "PIN", "PINE", "PING", "PINT",
229 "PIPE", "PIT", "PITY", "PLAN", "PLAY", "PLEA", "PLED", "PLOD",
230 "PLOP", "PLOT", "PLOW", "PLOY", "PLUG", "PLUM", "PLUS", "PLY",
231 "POD" , "POEM", "POET", "POKE", "POLE", "POLL", "POLO", "POMP",
232 "POND", "PONY", "POOF", "POOL", "POOR", "POP", "PORE", "PORK",
233 "PORT", "POSE", "POSH", "POST", "POT", "POUR", "POW", "POX",
234 "POXY", "PRAM", "PRAT", "PRAY", "PREP", "PREY", "PRIG", "PRIM",
235 "PROP", "PRY", "PUB", "PUCE", "PUCK", "PUFF", "PUG", "PULL",
236 "PULP", "PUMP", "PUN", "PUNK", "PUNT", "PUNY", "PUP", "PURE",
237 "PURR", "PUSH", "PUT", "PUTT", "QUAD", "QUIP", "QUIT", "QUIZ",
238 "QUO" , "RACE", "RAFT", "RAID", "RAIL", "RAIN", "RAKE", "RAM",
239 "RAMP", "RAN", "RANG", "RANK", "RAP", "RAPT", "RARE", "RASH",
240 "RASP", "RAT", "RATE", "RATH", "RAVE", "RAW", "RAY", "RAZE",
241 "RAZZ", "READ", "REAK", "REAL", "REAM", "REAP", "REAR", "RED",
242 "REDO", "REED", "REEF", "REEL", "REIN", "REND", "RENT", "REST",
243 "REV" , "RIB", "RICE", "RICH", "RICK", "RID", "RIDE", "RIFE",
244 "RIFF", "RIFT", "RIG", "RILE", "RIM", "RIND", "RING", "RINK",
245 "RIOT", "RIP", "RIPE", "RISE", "RISK", "RITE", "ROAD", "ROAM",
246 "ROAR", "ROBE", "ROCK", "ROD", "RODE", "ROE", "ROIL", "ROLL",
247 "ROME", "ROOF", "ROOM", "ROOT", "ROPE", "ROSE", "ROSY", "ROT",
248 "ROUT", "ROVE", "ROW", "ROWS", "RUB", "RUBY", "RUG", "RUIN",
249 "RULE", "RUM", "RUN", "RUNE", "RUNG", "RUNS", "RUNT", "RUSE",
250 "RUSH", "RUST", "RUT", "RYE", "SACK", "SAD", "SAFE", "SAGA",
251 "SAGE", "SAID", "SAIL", "SAKE", "SALE", "SALT", "SAME", "SAND",
252 "SANE", "SANG", "SANK", "SANS", "SAP", "SASH", "SAT", "SATE",
253 "SAVE", "SAW", "SAWN", "SAX", "SAY", "SAYS", "SCAD", "SCAM",
254 "SCAN", "SCAR", "SCUM", "SEA", "SEAL", "SEAM", "SEAR", "SEAT",
255 "SEE" , "SEED", "SEEK", "SEEM", "SEEN", "SEEP", "SEES", "SELF",
256 "SELL", "SEND", "SENT", "SET", "SETS", "SEW", "SEWN", "SHAW",
257 "SHE" , "SHED", "SHIM", "SHIN", "SHIP", "SHOD", "SHOE", "SHOO",
258 "SHOP", "SHOT", "SHOW", "SHUN", "SHUT", "SHY", "SIC", "SICK",
259 "SIDE", "SIFT", "SIGH", "SIGN", "SILK", "SILL", "SILO", "SILT",
260 "SIN" , "SINE", "SING", "SINK", "SIR", "SIRE", "SIS", "SIT",
261 "SITE", "SITH", "SITS", "SITU", "SIX", "SIZE", "SKEW", "SKI",
262 "SKID", "SKIM", "SKIN", "SKIP", "SKIT", "SKY", "SLAB", "SLAG",
263 "SLAM", "SLAP", "SLAT", "SLAW", "SLAY", "SLED", "SLEW", "SLID",
264 "SLIM", "SLIP", "SLOG", "SLOP", "SLOT", "SLOW", "SLUG", "SLUM",
265 "SLUR", "SLY", "SMOG", "SMUG", "SNAG", "SNAP", "SNOB", "SNOT",
266 "SNOW", "SNUB", "SNUG", "SO", "SOAK", "SOAP", "SOAR", "SOB",
267 "SOCK", "SOD", "SODA", "SOFA", "SOFT", "SOHO", "SOIL", "SOLD",
268 "SOLE", "SOLO", "SOME", "SON", "SONG", "SONS", "SOON", "SOOT",
269 "SOP" , "SOPE", "SORE", "SORT", "SORY", "SOUL", "SOUP", "SOUR",
270 "SOW" , "SOWN", "SOY", "SPA", "SPAN", "SPAR", "SPAT", "SPAY",
271 "SPEC", "SPED", "SPEW", "SPIN", "SPIT", "SPOT", "SPRY", "SPUD",
272 "SPUR", "SPY", "STAB", "STAG", "STAR", "STAY", "STEM", "STEP",
273 "STEW", "STIM", "STIR", "STOP", "STOW", "STUB", "STUD", "STUN",
274 "SUB" , "SUCH", "SUDS", "SUE", "SUET", "SUIT", "SULK", "SUM",
275 "SUMP", "SUMS", "SUN", "SUNG", "SUNK", "SURE", "SURF", "SWAB",
276 "SWAD", "SWAG", "SWAM", "SWAN", "SWAP", "SWAT", "SWAY", "SWIG",
277 "SWIM", "SWUM", "SYNC", "TAB", "TACK", "TACT", "TAD", "TAG",
278 "TAIL", "TAKE", "TALC", "TALE", "TALK", "TALL", "TAME", "TAMP",
279 "TAN" , "TANG", "TANK", "TAP", "TAPE", "TAPS", "TAR", "TARE",
280 "TARP", "TART", "TASK", "TAUT", "TAX", "TAXI", "TEA", "TEAK",
281 "TEAL", "TEAM", "TEAR", "TECH", "TEE", "TEEM", "TEEN", "TELL",
282 "TEMP", "TEN", "TEND", "TENT", "TERM", "TEST", "TEXT", "THAN",
283 "THAT", "THAW", "THE", "THEE", "THEM", "THEN", "THEY", "THIN",
284 "THIS", "THOU", "THOW", "THUD", "THY", "TIC", "TICK", "TIDE",
285 "TIDY", "TIE", "TIED", "TIER", "TIFF", "TILE", "TILL", "TILT",
286 "TIME", "TIN", "TINE", "TINT", "TINY", "TIP", "TIRE", "TO",
287 "TOAD", "TOE", "TOFU", "TOG", "TOGA", "TOGS", "TOIL", "TOKE",
288 "TOLD", "TOLE", "TOLL", "TOMB", "TON", "TONE", "TONG", "TONY",
289 "TOO" , "TOOK", "TOOL", "TOOT", "TOP", "TOPS", "TORE", "TORN",
290 "TORT", "TOTE", "TOTO", "TOUR", "TOUT", "TOW", "TOWN", "TOY",
291 "TRAM", "TRAP", "TRAY", "TREE", "TREK", "TRIM", "TRIO", "TROD",
292 "TROT", "TRUE", "TRY", "TUB", "TUBA", "TUBE", "TUCK", "TUFT",
293 "TUG" , "TULE", "TUNA", "TUNE", "TURF", "TURN", "TUSK", "TUT",
294 "TUTU", "TUX", "TWAS", "TWEE", "TWIG", "TWIN", "TWIT", "TWO",
295 "TYPE", "TYPO", "UGLY", "UNDO", "UNIT", "UNTO", "UP", "UPON",
296 "URGE", "URN", "US", "USE", "USED", "USER", "USES", "VAIN",
297 "VALE", "VAN", "VANE", "VARY", "VASE", "VAST", "VAT", "VEAL",
298 "VEER", "VEIL", "VEIN", "VEND", "VENT", "VERB", "VERY", "VEST",
299 "VET" , "VETO", "VEX", "VIA", "VICE", "VIE", "VIEW", "VILA",
300 "VINE", "VISA", "VISE", "VOID", "VOLT", "VOTE", "VOW", "WAD",
301 "WADE", "WAFT", "WAG", "WAGE", "WAIK", "WAIL", "WAIT", "WAKE",
302 "WALK", "WALL", "WAND", "WANE", "WANT", "WAR", "WARD", "WARE",
303 "WARM", "WARN", "WARP", "WART", "WARY", "WAS", "WASH", "WASP",
304 "WATT", "WAVE", "WAVY", "WAX", "WAXY", "WAY", "WAYS", "WE",
305 "WEAK", "WEAL", "WEAN", "WEAR", "WEB", "WED", "WEE", "WEED",
306 "WEEK", "WEEP", "WEIR", "WELD", "WELL", "WELT", "WEND", "WENT",
307 "WEPT", "WERE", "WEST", "WET", "WEVE", "WHAM", "WHAT", "WHEN",
308 "WHET", "WHEY", "WHIM", "WHIP", "WHIZ", "WHO", "WHOA", "WHOM",
309 "WHY" , "WICK", "WIDE", "WIFE", "WIG", "WILD", "WILL", "WILT",
310 "WILY", "WIN", "WIND", "WINE", "WING", "WINK", "WIPE", "WIRE",
311 "WISE", "WISH", "WISP", "WIT", "WITH", "WOK", "WOKE", "WOLF",
312 "WON" , "WONT", "WOO", "WOOD", "WOOL", "WORD", "WORE", "WORK",
313 "WORM", "WORN", "WORT", "WOT", "WOW", "WRAP", "WREN", "WRIT",
314 "WRY" , "WUSS", "YAGI", "YAK", "YAM", "YANK", "YAP", "YARD",
315 "YARN", "YAW", "YAWN", "YEA", "YEAH", "YEAR", "YELL", "YELP",
316 "YES" , "YET", "YOGA", "YOGI", "YOKE", "YOLK", "YORE", "YORK",
317 "YOU" , "YOUD", "YOUR", "YOWL", "YURT", "ZERO", "ZEST", "ZETA",
318 "ZINC", "ZING", "ZINK", "ZIP", "ZONE", "ZOO", "ZORK", "ZOOM"
324 banner(FILE* stream = stdout)
327 %s (asdcplib %s)\n\n\
328 Copyright (c) 2003-2018 John Hurst\n\n\
329 %s is part of the asdcp DCP tools package.\n\
330 asdcplib may be copied only under the terms of the license found at\n\
331 the top of every file in the asdcplib distribution kit.\n\n\
332 Specify the -h (help) option for further information about %s\n\n",
333 PROGRAM_NAME, Kumu::Version(), PROGRAM_NAME, PROGRAM_NAME);
338 usage(FILE* stream = stdout)
341 USAGE: %s [-b|-B|-c|-x] [-n] [-s <size>] [-v]\n\
343 %s [-h|-help] [-V]\n\
345 -b - Output a stream of binary data\n\
346 -B - Output a Base64 string\n\
347 -c - Output a C-language struct containing the values\n\
348 -C - Encode as a list of code words (for each code word, 20 bits of\n\
349 entropy are consumed, 4 are discarded)\n\
350 -h | -help - Show help\n\
351 -n - Suppress newlines\n\
352 -s <size> - Number of random bytes to generate (default 32)\n\
353 -v - Verbose. Prints informative messages to stderr\n\
354 -V - Show version information\n\
355 -w - Encode as a list of dictionary words (for each dictionary word,\n\
356 11 bits of entropy are consumed, 1 is discarded)\n\
357 -W <expr> - Word separator, for use with -C and -w (default '-')\n\
358 -x - Output hexadecimal (default)\n\
360 NOTES: o There is no option grouping, all options must be distinct arguments.\n\
361 o All option arguments must be separated from the option by whitespace.\n\
362 \n", PROGRAM_NAME, PROGRAM_NAME);
365 enum OutputFormat_t {
380 bool error_flag; // true if the given options are in error or not complete
381 bool no_newline_flag; //
382 bool verbose_flag; // true if the verbose option was selected
383 bool version_flag; // true if the version display option was selected
384 bool help_flag; // true if the help display option was selected
385 OutputFormat_t format; //
387 bool size_provided; // if true, the -s option has been used
388 std::string separator; // word separator value for OF_DICTWORD and CODEWORD modes
391 CommandOptions(int argc, const char** argv) :
392 error_flag(true), no_newline_flag(false), verbose_flag(false),
393 version_flag(false), help_flag(false), format(OF_HEX), request_size(RandBlockSize*2),
394 size_provided(false), separator("-")
396 for ( int i = 1; i < argc; i++ )
399 if ( (strcmp( argv[i], "-help") == 0) )
405 if ( argv[i][0] == '-' && isalpha(argv[i][1]) && argv[i][2] == 0 )
407 switch ( argv[i][1] )
409 case 'b': format = OF_BINARY; break;
410 case 'B': format = OF_BASE64; break;
411 case 'c': format = OF_CSTRUCT; break;
412 case 'C': format = OF_CODEWORD; break;
413 case 'n': no_newline_flag = true; break;
414 case 'h': help_flag = true; break;
417 TEST_EXTRA_ARG(i, 's');
418 request_size = Kumu::xabs(strtol(argv[i], 0, 10));
419 size_provided = true;
422 case 'v': verbose_flag = true; break;
423 case 'V': version_flag = true; break;
424 case 'w': format = OF_DICTWORD; break;
427 TEST_EXTRA_ARG(i, 'W');
431 case 'x': format = OF_HEX; break;
434 fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
440 fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
445 if ( help_flag || version_flag )
448 if ( ! size_provided )
450 if ( format == OF_CODEWORD )
454 else if ( format == OF_DICTWORD )
459 else if ( request_size == 0 )
461 fprintf(stderr, "Please use a non-zero request size\n");
472 main(int argc, const char** argv)
474 CommandOptions Options(argc, argv);
476 if ( Options.version_flag )
479 if ( Options.help_flag )
482 if ( Options.version_flag || Options.help_flag )
485 if ( Options.error_flag )
487 fprintf(stderr, "There was a problem. Type %s -h for help.\n", PROGRAM_NAME);
492 ByteString Buf(Kumu::Kilobyte);
494 if ( Options.verbose_flag )
495 fprintf(stderr, "Generating %d random byte%s.\n", Options.request_size, (Options.request_size == 1 ? "" : "s"));
497 if ( Options.format == OF_BINARY )
499 if ( KM_FAILURE(Buf.Capacity(Options.request_size)) )
501 fprintf(stderr, "randbuf: %s\n", RESULT_ALLOC.Label());
505 RandGen.FillRandom(Buf.Data(), Options.request_size);
506 fwrite((byte_t*)Buf.Data(), 1, Options.request_size, stdout);
508 else if ( Options.format == OF_CSTRUCT )
510 ui32_t line_count = 0;
511 byte_t* p = Buf.Data();
512 printf("byte_t rand_buf[%u] = {\n", Options.request_size);
514 if ( Options.request_size > 128 )
515 fputs(" // 0x00000000\n", stdout);
517 while ( Options.request_size > 0 )
519 if ( line_count > 0 && (line_count % (RandBlockSize*8)) == 0 )
520 fprintf(stdout, " // 0x%08x\n", line_count);
522 RandGen.FillRandom(p, RandBlockSize);
525 for ( ui32_t i = 0; i < RandBlockSize && Options.request_size > 0; i++, Options.request_size-- )
526 printf(" 0x%02x,", p[i]);
529 line_count += RandBlockSize;
534 if ( ! Options.no_newline_flag )
537 else if ( Options.format == OF_BASE64 )
539 if ( KM_FAILURE(Buf.Capacity(Options.request_size)) )
541 fprintf(stderr, "randbuf: %s\n", RESULT_ALLOC.Label());
546 ui32_t e_len = base64_encode_length(Options.request_size) + 1;
548 if ( KM_FAILURE(Strbuf.Capacity(e_len)) )
550 fprintf(stderr, "strbuf: %s\n", RESULT_ALLOC.Label());
554 RandGen.FillRandom(Buf.Data(), Options.request_size);
556 if ( base64encode(Buf.RoData(), Options.request_size, (char*)Strbuf.Data(), Strbuf.Capacity()) == 0 )
558 fprintf(stderr, "encode error\n");
562 fputs((const char*)Strbuf.RoData(), stdout);
564 if ( ! Options.no_newline_flag )
567 else if ( Options.format == OF_DICTWORD )
569 byte_t* p = Buf.Data();
573 while ( Options.request_size > 0 )
575 ui32_t x_len = xmin(Options.request_size, RandBlockSize);
576 RandGen.FillRandom(p, RandBlockSize);
578 // process 3 words at a time, each containing two 12-bit segments
579 for ( int i = 0; i+3 < x_len; i+=3 )
581 // ignore the high bit of each 12-bit segment, thus each output
582 // word has 11 bits of the entropy
583 int index1 = ( ( p[i] & 0x07f ) << 4 ) | ( p[i+1] >> 4 );
585 int index2 = ( ( p[i+1] & 0x07 ) << 8 ) | p[i+2];
589 (word_count==0?"":Options.separator.c_str()),
591 Options.separator.c_str(),
597 Options.request_size -= x_len;
600 if ( ! Options.no_newline_flag )
605 else if ( Options.format == OF_CODEWORD )
607 const char word_chars[] = "123456789ABCDEFGHJKLMNPRSTUVWXYZ";
608 byte_t* p = Buf.Data();
612 while ( Options.request_size > 0 )
614 ui32_t x_len = xmin(Options.request_size, RandBlockSize);
615 RandGen.FillRandom(p, RandBlockSize);
617 // process 3 words at a time, derive a code word with 20 bits of entropy.
618 for ( int i = 0; i+3 < x_len; i+=3 )
620 int index1 = p[i] >> 3; // MSB bits 87654
622 int index2 = ( ( p[i] & 0x07 ) << 2 ) | ( p[i+1] >> 6 ); // MSB bits 321 & MSB+1 bits 78
624 int index3 = ( p[i+1] & 0x3e ) >> 1; // MSB+1 bits 65432
626 int index4 = p[i+2] & 0x1f; // MSB+2 bits 54321
630 (word_count==0?"":Options.separator.c_str()),
631 word_chars[index1], word_chars[index2],
632 word_chars[index3], word_chars[index4]);
637 Options.request_size -= x_len;
640 if ( ! Options.no_newline_flag )
647 byte_t* p = Buf.Data();
650 while ( Options.request_size > 0 )
652 ui32_t x_len = xmin(Options.request_size, RandBlockSize);
653 RandGen.FillRandom(p, RandBlockSize);
654 bin2hex(p, x_len, hex_buf, 64);
655 fputs(hex_buf, stdout);
657 Options.request_size -= x_len;
659 if ( ! Options.no_newline_flag )