1 // Copyright 2020 Michael Reilly (mreilly@resiliware.com).
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions
5 // are met:
6 // 1. Redistributions of source code must retain the above copyright
7 //    notice, this list of conditions and the following disclaimer.
8 // 2. Redistributions in binary form must reproduce the above copyright
9 //    notice, this list of conditions and the following disclaimer in the
10 //    documentation and/or other materials provided with the distribution.
11 // 3. Neither the names of the copyright holders nor the names of the
12 //    contributors may be used to endorse or promote products derived from
13 //    this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 // ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
18 // PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
19 // OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 
27 #define SRCNAME "hexpeek_constants.c"
28 
29 #include <hexpeek.h>
30 
31 //---------------------------- Basic Information -----------------------------//
32 
33 char const LicenseString[] =
34 "Copyright 2020 Michael Reilly (mreilly@resiliware.com).\n"
35 "\n"
36 "Redistribution and use in source and binary forms, with or without\n"
37 "modification, are permitted provided that the following conditions\n"
38 "are met:\n"
39 "1. Redistributions of source code must retain the above copyright\n"
40 "   notice, this list of conditions and the following disclaimer.\n"
41 "2. Redistributions in binary form must reproduce the above copyright\n"
42 "   notice, this list of conditions and the following disclaimer in the\n"
43 "   documentation and/or other materials provided with the distribution.\n"
44 "3. Neither the names of the copyright holders nor the names of the\n"
45 "   contributors may be used to endorse or promote products derived from\n"
46 "   this software without specific prior written permission.\n"
47 "\n"
48 "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
49 "``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
50 "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\n"
51 "PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n"
52 "OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n"
53 "EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n"
54 "PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n"
55 "OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n"
56 "WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n"
57 "OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n"
58 "ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
59 ;
60 
61 #ifdef HEXPEEK_MODIFIED
62     #define MOD_STRING HEXPEEK_MODIFIED
63 #else
64     #define MOD_STRING ""
65 #endif
66 
67 #ifdef HEXPEEK_BETA
68     #define BETA_STRING " [beta]"
69 #else
70     #define BETA_STRING ""
71 #endif
72 
73 char const VersionShort[] = HEXPEEK_PROGRAM_VERSION "\n";
74 
75 #define VERSION_STRING \
76     PRGNM MOD_STRING " version " HEXPEEK_PROGRAM_VERSION BETA_STRING "\n"
77 
78 char const VersionLong[] =
79 VERSION_STRING
80 ;
81 
82 #define COPYRIGHT_SUMMARY \
83 "Copyright 2020 Michael Reilly." " ALL WARRANTIES DISCLAIMED.\n"
84 
85 char const AuthorshipString[] =
86 COPYRIGHT_SUMMARY
87 "Do you like this software? Visit " HEXPEEK_URL " for more!\n"
88 ;
89 
90 char const UsageStringShort[] =
91 "usage: " PRGNM " [OPTIONS] INFILE0 [INFILE1]\n"
92 "  Open up to " MS(MAX_INFILES)
93               " files and do as specified by options or enter prompt mode.\n"
94 "Basic options:\n"
95 "  -h , -help      Print short or extended help text; then exit.\n"
96 "  -v , -version   Print short or long version string; then exit.\n"
97 "  -license        Print license text; then exit.\n"
98 "  -r              Open subsequent infiles read-only.\n"
99 "  -x <CMDS>       Execute semicolon-delimited commands.\n"
100 "  -dump           Dump a whole single file in hexadecimal.\n"
101 "  -pack           Treat infile as a "PRGNM" dump and pack it back into binary.\n"
102 "  -diff           Diff two files in hexadecimal.\n"
103 "  -s <START>      With -dump or -diff, start output at given file offset.\n"
104 "  -l <LEN>        Like -s, but stop output after <LEN> octets are processed.\n"
105 "  -o <OUTFILE>    Write output to the given file.\n"
106 "  -b , -bits      Switch to bits display mode.\n"
107 "  -c , -cols      Set column width.\n"
108 "  -g , -group     Set group width.\n"
109 "  -p              Output data in plain mode.\n"
110 "  -recover        Prompt to revert operations recorded in backup files.\n"
111 ;
112 
113 char const UsageStringExtended[] =
114 "NAME\n"
115 "\n"
116 "    "PRGNM" - edit, dump, pack, and diff binary files in hex and bits\n"
117 "\n"
118 "SYNOPSIS\n"
119 "\n"
120 "    "PRGNM" [OPTIONS] INFILE0 [INFILE1]\n"
121 "    "viwNM" [OPTIONS] INFILE0 [INFILE1]\n"
122 "    "DmpNM" [OPTIONS] INFILE0 [INFILE1]\n"
123 "    "pckNM" [OPTIONS] INFILE0 [INFILE1]\n"
124 "    "dffNM" [OPTIONS] INFILE0 [INFILE1]\n"
125 "\n"
126 "DESCRIPTION\n"
127 "\n"
128 "    "PRGNM" (TM) is a binary editor designed for efficient operation on huge\n"
129 "    files, but works on any file. It is not plagued by size-related crashes,\n"
130 "    freezes, and glitches because it does not attempt to map files into its\n"
131 "    memory; instead, it operates on files directly to fulfill user commands.\n"
132 "\n"
133 "    "PRGNM" has four main modes of operation: prompt, command, pack, and\n"
134 "    recovery. Prompt mode is entered by default, subject to OPTIONS. When\n"
135 "    invoked as "viwNM", "DmpNM", "pckNM", or "dffNM", "PRGNM" runs as if given\n"
136 "    one of the flags -r, -dump, -pack, or -diff respectively.\n"
137 "\n"
138 "    Except when specifically indicated otherwise, "PRGNM" input and output are\n"
139 "    in unprefixed hexadecimal. This allows the user to work in hexadecimal\n"
140 "    without needing to prefix every number with \"0x\".\n"
141 "\n"
142 #ifdef HEXPEEK_BETA
143 "    This is an experimental beta release. Program functionality may change in\n"
144 "    future releases.\n"
145 "\n"
146 #endif
147 "    Thank you for trying "PRGNM". Send your comments to " HEXPEEK_EMAIL ".\n"
148 "\n"
149 "OPTIONS\n"
150 "\n"
151 "    Flags starting with \"+\" invert the respective flags with \"-\".\n"
152 "\n"
153 "    -h              Print usage text about commonly used options; then exit.\n"
154 "\n"
155 "    -help           Print more complete help text; then exit.\n"
156 "\n"
157 "    -v              Print short version string; then exit.\n"
158 "\n"
159 "    -version        Print long version string; then exit.\n"
160 "\n"
161 "    -license        Print license text; then exit.\n"
162 "\n"
163 "    -d <FD>         Treat <FD>, a _decimal_ integer, as an already-open file\n"
164 "                    descriptor and use it as the next file. Functionality on\n"
165 "                    non-seekable files is limited (see LIMITATIONS below).\n"
166 "\n"
167 "    -r              Open subsequent infiles read-only.\n"
168 "\n"
169 "    -w              Open subsequent infiles writeable.\n"
170 "\n"
171 "    -W              Like -w, but do not creat infiles that do not exist.\n"
172 "\n"
173 "    +ik             Disable insert and kill commands.\n"
174 "\n"
175 "    -x <CMDS>       Execute semicolon-delimited commands (see COMMANDS below).\n"
176 "\n"
177 "    -dump           Dump a whole single infile. Same as \"-x 0:max\".\n"
178 "\n"
179 "    -pack           Treat infile as a "PRGNM" dump and pack it back into the\n"
180 "                    outfile as binary. For best results, run with the same\n"
181 "                    option flags with which the original dump was created.\n"
182 "\n"
183 "    -diff           Diff two files. Same as \"-x '$0@0:max~$1@0:max'\".\n"
184 "\n"
185 "    -s <START>      With -dump or -diff, start output at given file offset.\n"
186 "\n"
187 "    -l <LEN>        Like -s, but stop output after <LEN> octets are processed.\n"
188 "\n"
189 "    -o <OUTFILE>    Write output to the given file.\n"
190 "\n"
191 "    [-|+]SET [ARG]  Set the given setting (for all applicable display modes).\n"
192 "                    SET may be one of: endian, hex, bits, rlen, slen, line,\n"
193 "                    cols, group, margin, scalar, prefix, autoskip, diffskip,\n"
194 "                    text, and ruler. These options accept the same arguments\n"
195 "                    and have the same effect as the commands of the same names\n"
196 "                    (see COMMANDS below).\n"
197 "\n"
198 "    -b , -c , -g    Synonyms of -bits , -cols , and -group respectively.\n"
199 "\n"
200 "    -p              Output data in plain mode, which is the equivalent of\n"
201 "                    \"-c 0 -g 0 -margin 0 +autoskip +diffskip +text +ruler\".\n"
202 "\n"
203 "    +lineterm       Skip line breaks in output.\n"
204 "\n"
205 "    -format <FMT>   Specify group delimiters. This both controls print output\n"
206 "                    and allows the delimiters to be silently ignored in data\n"
207 "                    input. Default: \"" GroupFmtLiTern " "
208                               GroupFmtGroup "\", which prints a leading space\n"
209 "                    before each group except the zeroth group (if margin > 0,\n"
210 "                    a space will be printed as part of the margin separator).\n"
211 "\n"
212 #ifdef HEXPEEK_UNIQUE_INFILES
213 "    -unique         Skip uniqueness check - assume all infiles are unique.\n"
214 "                    See warning in LIMITATIONS.\n"
215 "\n"
216 #endif
217 "    +tty            Skip TTY check - assume standard streams are not TTYs.\n"
218 "\n"
219 "    -pedantic       Generate a user-level error if filezone information is\n"
220 "                    unspecified or ambiguous (instead of auto-inferring what to\n"
221 "                    do) or if a print or diff (except with \":max\") attempts\n"
222 "                    to read beyond end of file (instead of printing nothing).\n"
223 "\n"
224 "    [-|+]strict     Toggle strict failure mode, which, when enabled, causes\n"
225 "                    "PRGNM" to fail for user-level errors (like a malformed\n"
226 "                    command string). This mode is enabled by default when\n"
227 "                    "PRGNM" is run non-interactively.\n"
228 "\n"
229 "    -backup <DEPTH> Backup depth may be 0 (to disable), max ("
230                                             MS(MAX_BACKUP_DEPTH) "), or any\n"
231 "                    number therebetween. The default depth is "
232                                       MS(DEFAULT_BACKUP_DEPTH) ".\n"
233 "\n"
234 "    -backup sync    Aggressively sync backup to disk.\n"
235 "\n"
236 "    -recover        Prompt to revert operations recorded in backup files.\n"
237 "\n"
238 #ifdef HEXPEEK_TRACE
239 "    -trace <FILE>   Trace to the given file.\n"
240 "\n"
241 #endif
242 "    --              Denote end of option flags.\n"
243 ;
244 
245 //------------------------------- Help Strings -------------------------------//
246 
247 char const HelpCmdList[] =
248 "help <topic> shows helptext about a specific topic.\n"
249 "help -all shows helptext about all available topics.\n"
250 "Available help topics:\n"
251 "    quit, stop, help, files, reset, settings, endian, hex, bits, rlen, slen,\n"
252 "    line, cols, group, margin, scalar, prefix, autoskip, diffskip, text, ruler,\n"
253 "    Numeric, print, offset, search, ~, replace, insert, kill, ops, undo.\n"
254 ;
255 
256 char const HelpCmdHdr[] = "COMMANDS\n\n";
257 
258 char const * HelpText[] =
259 {
260 "" // CMD_NONE
261 ,
262 "    q[uit]          Quit the program.\n"
263 ,
264 "    stop            Exit without unlinking backup files.\n"
265 ,
266 "    h[elp] [TOPIC]  Show general or specific helptext.\n"
267 ,
268 "    files           List open files with their paths (with C escapes for\n"
269 "                    non-printable characters), writeability, lengths, and\n"
270 "                    current offsets.\n"
271 ,
272 "    reset [$FILE]   Reset the current offset of FILE if specified, otherwise\n"
273 "                    reset the current offsets of all open infiles.\n"
274 ,
275 "    settings        List the values of various settings.\n"
276 ,
277 "    endian<b|l>     Set big- (default) or little-endian mode. Little-endian\n"
278 "                    mode is not compatible with zero group width.\n"
279 ,
280 "    hex[l|u]        Switch to hexadecimal display mode. The optional last\n"
281 "                    character may be used to set the case of hex numerals to\n"
282 "                    lower (default) or upper.\n"
283 ,
284 "    bits            Switch to bits display mode. This affects file data only,\n"
285 "                    not scalar (control) information.\n"
286 ,
287 "    rlen <WIDTH>    Set default read length for the current display mode.\n"
288 ,
289 "    slen <WIDTH>    Set search print length for the current display mode.\n"
290 "                    If 0, print only address of search match.\n"
291 ,
292 "    line <WIDTH>    Set line width for the current display mode; 0 disables.\n"
293 ,
294 "    cols <WIDTH>    Set rlen, slen, and line.\n"
295 ,
296 "    group <WIDTH>   Set group width for the current display mode; 0 disables.\n"
297 "                    This option controls how many octets are printed between\n"
298 "                    spaces (or other delimiters specified by -format).\n"
299 ,
300 
301 "    margin <WIDTH>  Set octet width of printed file offset; 0 disables; \"full\"\n"
302 "                    sets to maximum available width (default).\n"
303 ,
304 "    scalar <BASE>   Interpret scalar input according to the given <BASE>. Valid\n"
305 "                    arguments are "
306                   MS(DEF_SCALAR_BASE) " (default) and 0. If 0, scalar input are\n"
307 "                    interpreted as decimal unless prefixed with \"0x\" (hex) or\n"
308 "                    \"0\" (octal). This flag does not affect scalar output.\n"
309 ,
310 "    [+]prefix       Print scalars with a \"0x\" prefix (default off).\n"
311 ,
312 "    [+]autoskip     Toggle autoskip mode. If on (default when interactive),\n"
313 "                    repeated lines in dumps are replaced with \""
314                                                   AutoskipOutput "\".\n"
315 ,
316 "    [+]diffskip     Toggle diffskip mode. If on, identical lines in diffs are\n"
317 "                    skipped.\n"
318 ,
319 "    [+]text[=CODE]  Toggle dump of text characters in a column to the right of\n"
320 "                    print output. The optional argument controls the character\n"
321 "                    encoding and should be ascii or ebcdic. Defaults on when\n"
322 "                    interactive and line width is non-zero.\n"
323 ,
324 "    [+]ruler        Toggle octet ruler.\n"
325 ,
326 "    Numeric         [+][$FILE@][HEXOFF][,HEXLEN][+][SUBCOMMAND]\n"
327 "                    [+][$FILE@][HEXOFF][:HEXLIM][+][SUBCOMMAND]\n"
328 "                       ^--------filezone-------^\n"
329 "\n"
330 "        Execute a subcommand over a given filezone. If specified, FILE must be\n"
331 "        a numeric index; otherwise, file $0 will be used. HEXOFF may be used\n"
332 "        to specify an absolute file offset if positive, a relative offset from\n"
333 "        file end if negative, or the current offset if \"@@\" or not given.\n"
334 "\n"
335 "        HEXLEN is an optional length argument to the subcommand.\n"
336 "        HEXLIM specifies a length of HEXLIM - HEXOFF, or may be \"max\".\n"
337 "\n"
338 "        SUBCOMMAND may be one of: p, /, ~, r, i, k, their long forms, and\n"
339 "        offset. If no subcommand is specified, an implicit print is done.\n"
340 "\n"
341 "        If \"+\" precedes the filezone, file offset will be incremented before\n"
342 "        subcommand is run by the number of octets to be processed. If instead\n"
343 "        \"+\" follows, file offset will be incremented after subcommand is run\n"
344 "        by the number of octets processed.\n"
345 "\n"
346 "        An empty line at the prompt is equivalent to \"+\", and may be used to\n"
347 "        page through a file.\n"
348 ,
349 "    p[rint][v] , v\n"
350 "\n"
351 "        Output data starting at file offset. If HEXLEN is specified, that many\n"
352 "        octets are read; otherwise, the default number of octets are read. The\n"
353 "        output includes a left margin with file offset information. When \"p\"\n"
354 "        is given explicitly, offset start is outputted before file data.\n"
355 "\n"
356 "        Including \"v\" prints verbosely: each output line shows the file offset\n"
357 "        and data for just one octet with hexadecimal, decimal, octal, bits,\n"
358 "        high bit/low bit/bit count, and text formats shown side-by-side.\n"
359 "\n"
360 "        If autoskip is enabled, repeated lines are replaced with a single \""
361                                                              AutoskipOutput "\".\n"
362 ,
363 "    offset\n"
364 "\n"
365 "        Seek to the filezone offset and print it. Useful in scripts.\n"
366 ,
367 "    search <PATTERN> , /<PATTERN>\n"
368 "\n"
369 "        Search for the argument data within the specified filezone (or to file\n"
370 "        end if unspecified). A valid PATTERN is either:\n"
371 "            (1) fully specified octets in hexadecimal or bits (depending on\n"
372 "                mode), any number of spaces between octets, and the \".\"\n"
373 "                character (which  matches any value); or\n"
374 "            (2) a filezone of the form described above, in which case data\n"
375 "                from that zone is used as search input. If filezone length is\n"
376 "                unspecified, the default length of 1 is used.\n"
377 "\n"
378 "        If the search succeeds, the file offset is set to the beginning of the\n"
379 "        first found match; unless \"+\" follows the filezone, in which case the\n"
380 "        file offset is set to immediately _after_ the first found match or\n"
381 "        to immediately _after_ the search area if there was no match.\n"
382 ,
383 "    ~[ ][FILEZONE]\n"
384 "\n"
385 "        Perform a diff of two filezones. If no argument is given and two files\n"
386 "        are open, the diff is done between the two files. If two octets at a\n"
387 "        given relative offset are the same, they are printed as underscores.\n"
388 "        If diffskip is enabled, identical lines are not printed.\n"
389 "\n"
390 "    /~[ ][FILEZONE]\n"
391 "\n"
392 "        Search for the next difference between two filezones.\n"
393 ,
394 "    r[eplace ]<PATTERN>\n"
395 "\n"
396 "        Replace octets in the filezone with the argument data. The argument\n"
397 "        is of the same form as for the search command, but the \".\" matching\n"
398 "        character is not recognized. If HEXLEN is specified and is greater than\n"
399 "        the octet length of the input data, the data will be repeated to fill\n"
400 "        HEXLEN octets.\n"
401 ,
402 "    i[nsert ]<PATTERN>\n"
403 "\n"
404 "        Like replace, but expand file at file offset by number of octets to\n"
405 "        be written, thus preserving existing data.\n"
406 ,
407 "    k[ill] , delete\n"
408 "\n"
409 "        Remove the data in the specified filezone. If HEXLEN is unspecified,\n"
410 "        one octet will be removed. Note that a space is required between any\n"
411 "        numeric portion of the command and \"delete\".\n"
412 ,
413 "    ops\n"
414 "\n"
415 "        Show operations available to be undone. For each operation the depth,\n"
416 "        operation number, and command string are printed.\n"
417 ,
418 "    u[ndo] [DEPTH]\n"
419 "\n"
420 "        Undo the number of operations specified by DEPTH (defaults to 1).\n"
421 ,
422 };
423 
424 char const HelpOther[] =
425 "EXAMPLES\n"
426 "\n"
427 "    0               From beginning of file, print default number of octets.\n"
428 "\n"
429 "    10,40           Print 40 octets starting at the 10th octet in the file.\n"
430 "\n"
431 "    ,2p             Print two octets starting at current file offset.\n"
432 "\n"
433 "    7:C/.1          Within domain starting at file offset 7 and ending at B\n"
434 "                    inclusively, search for the first octet the second nibble\n"
435 "                    of which is 1.\n"
436 "\n"
437 "    0:100 r 00      Zero out the first 100 octets.\n"
438 "\n"
439 "    100 r 1122      Replace the 100th octet with value 11 and the 101st octet\n"
440 "                    with value 22.\n"
441 "\n"
442 "    -1r33           Replace the last octet in the file with the value 33.\n"
443 "\n"
444 "    i 44            Insert one octet with value 44 before the current offset.\n"
445 "\n"
446 "    -0i 5566        Append two octets to the end of file with values 55 and 66.\n"
447 "\n"
448 "    k               Remove one octet at the current file offset.\n"
449 "\n"
450 "    1:3k            Remove the first and second octets of the file.\n"
451 "\n"
452 "    20:60 r @30,3   Replace the 40 octet chunk starting at 20 with the values\n"
453 "                    located in 30:33 repeated.\n"
454 "\n"
455 "DEFAULTS\n"
456 "\n"
457 "    Unless set on the command line, column width defaults to the greatest\n"
458 "    power of 2 number of octets that fit in an "
459                               MS(TERMINAL_WIDTH) " character terminal.\n"
460 "\n"
461 "LIMITATIONS\n"
462 "\n"
463 #ifdef HEXPEEK_UNIQUE_INFILES
464 "    "PRGNM" requires (and attempts to enforce) that each infile refers to a\n"
465 "    unique file. Data corruption may result if the same file is opened as\n"
466 "    multiple infiles during a "PRGNM" run.\n"
467 "\n"
468 #endif
469 "    Functionality on non-seekable files is inherently limited because "PRGNM"\n"
470 "    operates on them with a one-way seek. Thus, you can not seek backwards and\n"
471 "    post-incrementation for reads is always in effect. Moreover, the current\n"
472 "    offset has no impact on write operations (a duplex connection is assumed).\n"
473 "    Finally, the backup function does not work with non-seekable files for\n"
474 "    obvious reasons.\n"
475 "\n"
476 "    The insert and kill commands are inherently inefficient because they must\n"
477 "    move all the data after the point of insertion or deletion. Consider\n"
478 "    combining repeated insertions (or kills) into one large operation to limit\n"
479 "    the amount of time spent in file rearrangement.\n"
480 "\n"
481 "    Maximum line, group, and search argument octet width are "
482 #if (MAXW_LINE == MAXW_GROUP && MAXW_LINE == SRCHSZ)
483      MS(MAXW_LINE) ".\n"
484 #else
485      MS(MAXW_LINE) ", " MS(MAXW_GROUP) ",\n    and " MS(SRCHSZ) ", respectively.\n"
486 #endif
487 "\n"
488 
489 "BACKUP AND RECOVERY\n"
490 "\n"
491 "    When in write mode, unless backup depth is 0, "PRGNM" creates "
492                                              MS(BACKUP_FILE_COUNT) " hidden\n"
493 "    backup files with file extension " BACKUP_EXT ". Before executing any\n"
494 "    writeable command, "PRGNM" writes information to a backup file which is\n"
495 "    sufficient to recover previous data file state in case of program crash or\n"
496 "    user error.\n"
497 "\n"
498 "    When an error occurs, use the undo command to revert it; or use stop and\n"
499 "    then invoke '"PRGNM" -recover'. Otherwise, on successful exit, "PRGNM"\n"
500 "    automatically unlinks the backup files. A redo can be performed with the\n"
501 "    command line history functionality (if built with support).\n"
502 "\n"
503 "VERSION\n"
504 "\n"
505 "    " VERSION_STRING
506 "\n"
507 "AUTHOR\n"
508 "\n"
509 "    " COPYRIGHT_SUMMARY
510 "\n"
511 "    " "hexpeek is a trademark of Michael Reilly." "\n"
512 "\n"
513 "SEE ALSO\n"
514 "\n"
515 "    " HEXPEEK_URL "\n"
516 ;
517 
518 //----------------------------- Conversion Data ------------------------------//
519 
520 char const *BinLookup_hexl[OCTET_COUNT] =
521 {
522     "00",     "01",     "02",     "03",     "04",     "05",     "06",     "07",     "08",     "09",     "0a",     "0b",     "0c",     "0d",     "0e",     "0f",
523     "10",     "11",     "12",     "13",     "14",     "15",     "16",     "17",     "18",     "19",     "1a",     "1b",     "1c",     "1d",     "1e",     "1f",
524     "20",     "21",     "22",     "23",     "24",     "25",     "26",     "27",     "28",     "29",     "2a",     "2b",     "2c",     "2d",     "2e",     "2f",
525     "30",     "31",     "32",     "33",     "34",     "35",     "36",     "37",     "38",     "39",     "3a",     "3b",     "3c",     "3d",     "3e",     "3f",
526     "40",     "41",     "42",     "43",     "44",     "45",     "46",     "47",     "48",     "49",     "4a",     "4b",     "4c",     "4d",     "4e",     "4f",
527     "50",     "51",     "52",     "53",     "54",     "55",     "56",     "57",     "58",     "59",     "5a",     "5b",     "5c",     "5d",     "5e",     "5f",
528     "60",     "61",     "62",     "63",     "64",     "65",     "66",     "67",     "68",     "69",     "6a",     "6b",     "6c",     "6d",     "6e",     "6f",
529     "70",     "71",     "72",     "73",     "74",     "75",     "76",     "77",     "78",     "79",     "7a",     "7b",     "7c",     "7d",     "7e",     "7f",
530     "80",     "81",     "82",     "83",     "84",     "85",     "86",     "87",     "88",     "89",     "8a",     "8b",     "8c",     "8d",     "8e",     "8f",
531     "90",     "91",     "92",     "93",     "94",     "95",     "96",     "97",     "98",     "99",     "9a",     "9b",     "9c",     "9d",     "9e",     "9f",
532     "a0",     "a1",     "a2",     "a3",     "a4",     "a5",     "a6",     "a7",     "a8",     "a9",     "aa",     "ab",     "ac",     "ad",     "ae",     "af",
533     "b0",     "b1",     "b2",     "b3",     "b4",     "b5",     "b6",     "b7",     "b8",     "b9",     "ba",     "bb",     "bc",     "bd",     "be",     "bf",
534     "c0",     "c1",     "c2",     "c3",     "c4",     "c5",     "c6",     "c7",     "c8",     "c9",     "ca",     "cb",     "cc",     "cd",     "ce",     "cf",
535     "d0",     "d1",     "d2",     "d3",     "d4",     "d5",     "d6",     "d7",     "d8",     "d9",     "da",     "db",     "dc",     "dd",     "de",     "df",
536     "e0",     "e1",     "e2",     "e3",     "e4",     "e5",     "e6",     "e7",     "e8",     "e9",     "ea",     "eb",     "ec",     "ed",     "ee",     "ef",
537     "f0",     "f1",     "f2",     "f3",     "f4",     "f5",     "f6",     "f7",     "f8",     "f9",     "fa",     "fb",     "fc",     "fd",     "fe",     "ff",
538 };
539 
540 char const *BinLookup_hexu[OCTET_COUNT] =
541 {
542     "00",     "01",     "02",     "03",     "04",     "05",     "06",     "07",     "08",     "09",     "0A",     "0B",     "0C",     "0D",     "0E",     "0F",
543     "10",     "11",     "12",     "13",     "14",     "15",     "16",     "17",     "18",     "19",     "1A",     "1B",     "1C",     "1D",     "1E",     "1F",
544     "20",     "21",     "22",     "23",     "24",     "25",     "26",     "27",     "28",     "29",     "2A",     "2B",     "2C",     "2D",     "2E",     "2F",
545     "30",     "31",     "32",     "33",     "34",     "35",     "36",     "37",     "38",     "39",     "3A",     "3B",     "3C",     "3D",     "3E",     "3F",
546     "40",     "41",     "42",     "43",     "44",     "45",     "46",     "47",     "48",     "49",     "4A",     "4B",     "4C",     "4D",     "4E",     "4F",
547     "50",     "51",     "52",     "53",     "54",     "55",     "56",     "57",     "58",     "59",     "5A",     "5B",     "5C",     "5D",     "5E",     "5F",
548     "60",     "61",     "62",     "63",     "64",     "65",     "66",     "67",     "68",     "69",     "6A",     "6B",     "6C",     "6D",     "6E",     "6F",
549     "70",     "71",     "72",     "73",     "74",     "75",     "76",     "77",     "78",     "79",     "7A",     "7B",     "7C",     "7D",     "7E",     "7F",
550     "80",     "81",     "82",     "83",     "84",     "85",     "86",     "87",     "88",     "89",     "8A",     "8B",     "8C",     "8D",     "8E",     "8F",
551     "90",     "91",     "92",     "93",     "94",     "95",     "96",     "97",     "98",     "99",     "9A",     "9B",     "9C",     "9D",     "9E",     "9F",
552     "A0",     "A1",     "A2",     "A3",     "A4",     "A5",     "A6",     "A7",     "A8",     "A9",     "AA",     "AB",     "AC",     "AD",     "AE",     "AF",
553     "B0",     "B1",     "B2",     "B3",     "B4",     "B5",     "B6",     "B7",     "B8",     "B9",     "BA",     "BB",     "BC",     "BD",     "BE",     "BF",
554     "C0",     "C1",     "C2",     "C3",     "C4",     "C5",     "C6",     "C7",     "C8",     "C9",     "CA",     "CB",     "CC",     "CD",     "CE",     "CF",
555     "D0",     "D1",     "D2",     "D3",     "D4",     "D5",     "D6",     "D7",     "D8",     "D9",     "DA",     "DB",     "DC",     "DD",     "DE",     "DF",
556     "E0",     "E1",     "E2",     "E3",     "E4",     "E5",     "E6",     "E7",     "E8",     "E9",     "EA",     "EB",     "EC",     "ED",     "EE",     "EF",
557     "F0",     "F1",     "F2",     "F3",     "F4",     "F5",     "F6",     "F7",     "F8",     "F9",     "FA",     "FB",     "FC",     "FD",     "FE",     "FF",
558 };
559 
560 char const *BinLookup_bits[OCTET_COUNT] =
561 {
562     "00000000", "00000001", "00000010", "00000011", "00000100", "00000101", "00000110", "00000111", "00001000", "00001001", "00001010", "00001011", "00001100", "00001101", "00001110", "00001111",
563     "00010000", "00010001", "00010010", "00010011", "00010100", "00010101", "00010110", "00010111", "00011000", "00011001", "00011010", "00011011", "00011100", "00011101", "00011110", "00011111",
564     "00100000", "00100001", "00100010", "00100011", "00100100", "00100101", "00100110", "00100111", "00101000", "00101001", "00101010", "00101011", "00101100", "00101101", "00101110", "00101111",
565     "00110000", "00110001", "00110010", "00110011", "00110100", "00110101", "00110110", "00110111", "00111000", "00111001", "00111010", "00111011", "00111100", "00111101", "00111110", "00111111",
566     "01000000", "01000001", "01000010", "01000011", "01000100", "01000101", "01000110", "01000111", "01001000", "01001001", "01001010", "01001011", "01001100", "01001101", "01001110", "01001111",
567     "01010000", "01010001", "01010010", "01010011", "01010100", "01010101", "01010110", "01010111", "01011000", "01011001", "01011010", "01011011", "01011100", "01011101", "01011110", "01011111",
568     "01100000", "01100001", "01100010", "01100011", "01100100", "01100101", "01100110", "01100111", "01101000", "01101001", "01101010", "01101011", "01101100", "01101101", "01101110", "01101111",
569     "01110000", "01110001", "01110010", "01110011", "01110100", "01110101", "01110110", "01110111", "01111000", "01111001", "01111010", "01111011", "01111100", "01111101", "01111110", "01111111",
570     "10000000", "10000001", "10000010", "10000011", "10000100", "10000101", "10000110", "10000111", "10001000", "10001001", "10001010", "10001011", "10001100", "10001101", "10001110", "10001111",
571     "10010000", "10010001", "10010010", "10010011", "10010100", "10010101", "10010110", "10010111", "10011000", "10011001", "10011010", "10011011", "10011100", "10011101", "10011110", "10011111",
572     "10100000", "10100001", "10100010", "10100011", "10100100", "10100101", "10100110", "10100111", "10101000", "10101001", "10101010", "10101011", "10101100", "10101101", "10101110", "10101111",
573     "10110000", "10110001", "10110010", "10110011", "10110100", "10110101", "10110110", "10110111", "10111000", "10111001", "10111010", "10111011", "10111100", "10111101", "10111110", "10111111",
574     "11000000", "11000001", "11000010", "11000011", "11000100", "11000101", "11000110", "11000111", "11001000", "11001001", "11001010", "11001011", "11001100", "11001101", "11001110", "11001111",
575     "11010000", "11010001", "11010010", "11010011", "11010100", "11010101", "11010110", "11010111", "11011000", "11011001", "11011010", "11011011", "11011100", "11011101", "11011110", "11011111",
576     "11100000", "11100001", "11100010", "11100011", "11100100", "11100101", "11100110", "11100111", "11101000", "11101001", "11101010", "11101011", "11101100", "11101101", "11101110", "11101111",
577     "11110000", "11110001", "11110010", "11110011", "11110100", "11110101", "11110110", "11110111", "11111000", "11111001", "11111010", "11111011", "11111100", "11111101", "11111110", "11111111",
578 };
579 
580 //------------------------- Textual Representations --------------------------//
581 
582 #define UNP '.'
583 
584 static char asciiCodes[OCTET_COUNT] =
585 {
586  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
587  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
588  ' ', '!', '"', '#', '$', '%', '&','\'', '(', ')', '*', '+', ',', '-', '.', '/',
589  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
590  '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
591  'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[','\\', ']', '^', '_',
592  '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
593  'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', UNP,
594  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
595  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
596  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
597  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
598  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
599  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
600  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
601  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
602 };
603 
604 static char const *asciiStrings[OCTET_COUNT] =
605 {
606   "'\\0'",    "SOH",    "STX",    "ETX",    "EOT",    "ENQ",    "ACK",  "'\\a'",  "'\\b'",  "'\\t'",  "'\\n'",  "'\\v'",  "'\\f'",  "'\\r'",     "SO",     "SI",
607     "DLE",    "DC1",    "DC2",    "DC3",    "DC4",    "NAK",    "SYN",    "ETB",    "CAN",     "EM",    "SUB",    "ESC",     "FS",     "GS",     "RS",     "US",
608     "' '",    "'!'",   "'\"'",    "'#'",    "'$'",    "'%'",    "'&'",  "'\\''",    "'('",    "')'",    "'*'",    "'+'",    "','",    "'-'",    "'.'",    "'/'",
609     "'0'",    "'1'",    "'2'",    "'3'",    "'4'",    "'5'",    "'6'",    "'7'",    "'8'",    "'9'",    "':'",    "';'",    "'<'",    "'='",    "'>'",    "'?'",
610     "'@'",    "'A'",    "'B'",    "'C'",    "'D'",    "'E'",    "'F'",    "'G'",    "'H'",    "'I'",    "'J'",    "'K'",    "'L'",    "'M'",    "'N'",    "'O'",
611     "'P'",    "'Q'",    "'R'",    "'S'",    "'T'",    "'U'",    "'V'",    "'W'",    "'X'",    "'Y'",    "'Z'",    "'['", "'\\\\'",    "']'",    "'^'",    "'_'",
612     "'`'",    "'a'",    "'b'",    "'c'",    "'d'",    "'e'",    "'f'",    "'g'",    "'h'",    "'i'",    "'j'",    "'k'",    "'l'",    "'m'",    "'n'",    "'o'",
613     "'p'",    "'q'",    "'r'",    "'s'",    "'t'",    "'u'",    "'v'",    "'w'",    "'x'",    "'y'",    "'z'",    "'{'",    "'|'",    "'}'",    "'~'",    "DEL",
614      NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,
615      NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,
616      NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,
617      NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,
618      NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,
619      NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,
620      NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,
621      NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,
622 };
623 
624 static char ebcdicCodes[OCTET_COUNT] =
625 {
626  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
627  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
628  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
629  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
630  ' ', UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, '.', '<', '(', '+', '|',
631  '&', UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, '!', '$', '*', ')', ';', UNP,
632  '-', '/', UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, ',', UNP, '_', '>', '?',
633  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, ':', '#', '@','\'', '=', '"',
634  UNP, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', UNP, UNP, UNP, UNP, UNP, UNP,
635  UNP, 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', UNP, UNP, UNP, UNP, UNP, UNP,
636  UNP, UNP, 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', UNP, UNP, UNP, UNP, UNP, UNP,
637  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
638  UNP, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', UNP, UNP, UNP, UNP, UNP, UNP,
639  UNP, 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', UNP, UNP, UNP, UNP, UNP, UNP,
640 '\\', UNP, 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', UNP, UNP, UNP, UNP, UNP, UNP,
641  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', UNP, UNP, UNP, UNP, UNP, UNP,
642 };
643 
644 static char const *ebcdicStrings[OCTET_COUNT] =
645 {
646   "'\\0'",    "SOH",    "STX",    "ETX",    "SEL",  "'\\t'",    "RNL",    "DEL",     "GE",    "SPS",    "RPT",  "'\\v'",  "'\\f'",  "'\\r'",     "SO",     "SI",
647     "DLE",    "DC1",    "DC2",    "DC3",    "RES",     "NL",  "'\\b'",    "POC",    "CAN",     "EM",    "UBS",    "CU1",    "IFS",    "IGS",    "IRS",    "ITB",
648      "DS",    "SOS",     "FS",    "WUS",    "BYP",  "'\\n'",    "ETB",    "ESC",     "SA",    "SFE",     "SM",    "CSP",    "MFA",    "ENQ",    "ACK",  "'\\a'",
649      NULL,     NULL,    "SYN",     "IR",     "PP",    "TRN",    "NBS",    "EOT",    "SBS",     "IT",    "RFF",    "CU3",    "DC4",    "NAK",     NULL,    "SUB",
650     "' '",    "RSP",     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,    "'.'",    "'<'",    "'('",    "'+'",    "'|'",
651     "'&'",     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,    "'!'",    "'$'",    "'*'",    "')'",    "';'",     NULL,
652     "'-'",    "'/'",     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,    "','",     NULL,    "'_'",    "'>'",    "'?'",
653      NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,    "':'",    "'#'",    "'@'",  "'\\''",    "'='",   "'\"'",
654      NULL,    "'a'",    "'b'",    "'c'",    "'d'",    "'e'",    "'f'",    "'g'",    "'h'",    "'i'",     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,
655      NULL,    "'j'",    "'k'",    "'l'",    "'m'",    "'n'",    "'o'",    "'p'",    "'q'",    "'r'",     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,
656      NULL,     NULL,    "'s'",    "'t'",    "'u'",    "'v'",    "'w'",    "'x'",    "'y'",    "'z'",     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,
657      NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,
658      NULL,    "'A'",    "'B'",    "'C'",    "'D'",    "'E'",    "'F'",    "'G'",    "'H'",    "'I'",     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,
659      NULL,    "'J'",    "'K'",    "'L'",    "'M'",    "'N'",    "'O'",    "'P'",    "'Q'",    "'R'",     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,
660  "'\\\\'",     NULL,    "'S'",    "'T'",    "'U'",    "'V'",    "'W'",    "'X'",    "'Y'",    "'Z'",     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,
661     "'0'",    "'1'",    "'2'",    "'3'",    "'4'",    "'5'",    "'6'",    "'7'",    "'8'",    "'9'",     NULL,     NULL,     NULL,     NULL,     NULL,     NULL,
662 };
663 
664 static char unknownCodes[OCTET_COUNT] =
665 {
666  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
667  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
668  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
669  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
670  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
671  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
672  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
673  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
674  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
675  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
676  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
677  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
678  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
679  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
680  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
681  UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP, UNP,
682 };
683 
684 static char const *unknownStrings[OCTET_COUNT] =
685 {
686 "'\\x00'","'\\x01'","'\\x02'","'\\x03'","'\\x04'","'\\x05'","'\\x06'","'\\x07'","'\\x08'","'\\x09'","'\\x0A'","'\\x0B'","'\\x0C'","'\\x0D'","'\\x0E'","'\\x0F'",
687 "'\\x10'","'\\x11'","'\\x12'","'\\x13'","'\\x14'","'\\x15'","'\\x16'","'\\x17'","'\\x18'","'\\x19'","'\\x1A'","'\\x1B'","'\\x1C'","'\\x1D'","'\\x1E'","'\\x1F'",
688 "'\\x20'","'\\x21'","'\\x22'","'\\x23'","'\\x24'","'\\x25'","'\\x26'","'\\x27'","'\\x28'","'\\x29'","'\\x2A'","'\\x2B'","'\\x2C'","'\\x2D'","'\\x2E'","'\\x2F'",
689 "'\\x30'","'\\x31'","'\\x32'","'\\x33'","'\\x34'","'\\x35'","'\\x36'","'\\x37'","'\\x38'","'\\x39'","'\\x3A'","'\\x3B'","'\\x3C'","'\\x3D'","'\\x3E'","'\\x3F'",
690 "'\\x40'","'\\x41'","'\\x42'","'\\x43'","'\\x44'","'\\x45'","'\\x46'","'\\x47'","'\\x48'","'\\x49'","'\\x4A'","'\\x4B'","'\\x4C'","'\\x4D'","'\\x4E'","'\\x4F'",
691 "'\\x50'","'\\x51'","'\\x52'","'\\x53'","'\\x54'","'\\x55'","'\\x56'","'\\x57'","'\\x58'","'\\x59'","'\\x5A'","'\\x5B'","'\\x5C'","'\\x5D'","'\\x5E'","'\\x5F'",
692 "'\\x60'","'\\x61'","'\\x62'","'\\x63'","'\\x64'","'\\x65'","'\\x66'","'\\x67'","'\\x68'","'\\x69'","'\\x6A'","'\\x6B'","'\\x6C'","'\\x6D'","'\\x6E'","'\\x6F'",
693 "'\\x70'","'\\x71'","'\\x72'","'\\x73'","'\\x74'","'\\x75'","'\\x76'","'\\x77'","'\\x78'","'\\x79'","'\\x7A'","'\\x7B'","'\\x7C'","'\\x7D'","'\\x7E'","'\\x7F'",
694 "'\\x80'","'\\x81'","'\\x82'","'\\x83'","'\\x84'","'\\x85'","'\\x86'","'\\x87'","'\\x88'","'\\x89'","'\\x8A'","'\\x8B'","'\\x8C'","'\\x8D'","'\\x8E'","'\\x8F'",
695 "'\\x90'","'\\x91'","'\\x92'","'\\x93'","'\\x94'","'\\x95'","'\\x96'","'\\x97'","'\\x98'","'\\x99'","'\\x9A'","'\\x9B'","'\\x9C'","'\\x9D'","'\\x9E'","'\\x9F'",
696 "'\\xA0'","'\\xA1'","'\\xA2'","'\\xA3'","'\\xA4'","'\\xA5'","'\\xA6'","'\\xA7'","'\\xA8'","'\\xA9'","'\\xAA'","'\\xAB'","'\\xAC'","'\\xAD'","'\\xAE'","'\\xAF'",
697 "'\\xB0'","'\\xB1'","'\\xB2'","'\\xB3'","'\\xB4'","'\\xB5'","'\\xB6'","'\\xB7'","'\\xB8'","'\\xB9'","'\\xBA'","'\\xBB'","'\\xBC'","'\\xBD'","'\\xBE'","'\\xBF'",
698 "'\\xC0'","'\\xC1'","'\\xC2'","'\\xC3'","'\\xC4'","'\\xC5'","'\\xC6'","'\\xC7'","'\\xC8'","'\\xC9'","'\\xCA'","'\\xCB'","'\\xCC'","'\\xCD'","'\\xCE'","'\\xCF'",
699 "'\\xD0'","'\\xD1'","'\\xD2'","'\\xD3'","'\\xD4'","'\\xD5'","'\\xD6'","'\\xD7'","'\\xD8'","'\\xD9'","'\\xDA'","'\\xDB'","'\\xDC'","'\\xDD'","'\\xDE'","'\\xDF'",
700 "'\\xE0'","'\\xE1'","'\\xE2'","'\\xE3'","'\\xE4'","'\\xE5'","'\\xE6'","'\\xE7'","'\\xE8'","'\\xE9'","'\\xEA'","'\\xEB'","'\\xEC'","'\\xED'","'\\xEE'","'\\xEF'",
701 "'\\xF0'","'\\xF1'","'\\xF2'","'\\xF3'","'\\xF4'","'\\xF5'","'\\xF6'","'\\xF7'","'\\xF8'","'\\xF9'","'\\xFA'","'\\xFB'","'\\xFC'","'\\xFD'","'\\xFE'","'\\xFF'",
702 };
703 
getEncoded(int codepage,uint8_t * in,size_t len,char * out)704 char *getEncoded(int codepage, uint8_t *in, size_t len, char *out)
705 {
706     char *datasrc = NULL;
707     switch(codepage)
708     {
709     case CODEPAGE_EBCDIC: datasrc = ebcdicCodes; break;
710     case CODEPAGE_ASCII:  datasrc = asciiCodes; break;
711     default:              datasrc = unknownCodes; break;
712     }
713     for(size_t ix = 0; ix < len; ix++)
714         out[ix] = datasrc[in[ix]];
715     out[len] = '\0';
716     return out;
717 }
718 
getEncodedVerbose(int codepage,uint8_t data)719 char const *getEncodedVerbose(int codepage, uint8_t data)
720 {
721     char const *result = NULL;
722     switch(codepage)
723     {
724     case CODEPAGE_EBCDIC: result = ebcdicStrings[data]; break;
725     case CODEPAGE_ASCII:  result = asciiStrings[data]; break;
726     }
727     if(result)
728         return result;
729     else
730         return unknownStrings[data];
731 }
732 
encodingName(int codepage)733 char const *encodingName(int codepage)
734 {
735     switch(codepage)
736     {
737     case CODEPAGE_EBCDIC: return "Ebcdic";
738     case CODEPAGE_ASCII:  return "Ascii";
739     default:              return "UNKNOWN";
740     }
741 }
742