This commit is contained in:
Alexander Popov 2023-07-30 11:24:54 +03:00
commit 6a4b7a68fa
Signed by: iiiypuk
GPG Key ID: E47FE0AB36CD5ED6
6 changed files with 1024 additions and 0 deletions

149
Makefile Normal file
View File

@ -0,0 +1,149 @@
# Unix Makefile for xd
VERSION = 1.4
# C compiler
CC = gcc
# For production
CFLAGS = -O -Wall
# For debugging
#CFLAGS = -g -Wall
xd: xd.o
$(CC) $(CFLAGS) xd.o -o xd
clean:
rm -f xd *.bak *.cat core *.out *.o *.shar *.gz *.tar *.zip *.opt *.ncb *.plg
RELEASE = Makefile xd.1 xd.c index.html log.txt images
dist:
rm -f *.tar *.tar.gz
tar cfvz xd-$(VERSION).tar.gz $(RELEASE)
manpage:
nroff -man xd.1 | more
printman:
ptroff -man xd.1
catman:
nroff -man xd.1 | col -b >xd.cat
# The following tests should produce no error messages from XD or CMP
check: testb testad testao testdd testdo
testb: xd
xd xd xd1.bak
xd -l xd1.bak xd2.bak
cmp xd2.bak xd
xd -c xd xd3.bak
xd -l xd3.bak xd4.bak
cmp xd4.bak xd
xd -l -s xd3.bak xd4.bak
cmp xd4.bak xd
sed 's/........//' xd3.bak >xd5.bak
xd -l -s xd5.bak xd6.bak
cmp xd6.bak xd
echo Hello there >xd10.bak
xd xd10.bak >xd7.bak
sed '1d' xd3.bak >>xd7.bak
xd -l -s xd7.bak xd8.bak
cp xd10.bak xd9.bak
tail --bytes=+17 xd >>xd9.bak
cmp xd8.bak xd9.bak
cat xd | xd -dDeFile >xd10.c
echo "#include <unistd.h>\nint main() {write(1,DeFile,sizeof DeFile); return 0;}" >>xd10.c
$(CC) xd10.c -o xd10.bak
chmod 755 xd10.bak
./xd10.bak >xd11.bak
cmp xd11.bak xd
rm xd*.bak xd10.c
testad: xd
xd -ad xd xd1.bak
xd -ad -l xd1.bak xd2.bak
cmp xd2.bak xd
xd -ad -c xd xd3.bak
xd -ad -l xd3.bak xd4.bak
cmp xd4.bak xd
xd -ad -l -s xd3.bak xd4.bak
cmp xd4.bak xd
sed 's/........//' xd3.bak >xd5.bak
xd -ad -l -s xd5.bak xd6.bak
cmp xd6.bak xd
echo Hello there >xd10.bak
xd -ad xd10.bak >xd7.bak
sed '1d' xd3.bak >>xd7.bak
xd -ad -l -s xd7.bak xd8.bak
cp xd10.bak xd9.bak
tail --bytes=+17 xd >>xd9.bak
cmp xd8.bak xd9.bak
rm xd*.bak
testao: xd
xd -ao xd xd1.bak
xd -ao -l xd1.bak xd2.bak
cmp xd2.bak xd
xd -ao -c xd xd3.bak
xd -ao -l xd3.bak xd4.bak
cmp xd4.bak xd
xd -ao -l -s xd3.bak xd4.bak
cmp xd4.bak xd
sed 's/........//' xd3.bak >xd5.bak
xd -ao -l -s xd5.bak xd6.bak
cmp xd6.bak xd
echo Hello there >xd10.bak
xd -ao xd10.bak >xd7.bak
sed '1d' xd3.bak >>xd7.bak
xd -ao -l -s xd7.bak xd8.bak
cp xd10.bak xd9.bak
tail --bytes=+17 xd >>xd9.bak
cmp xd8.bak xd9.bak
rm xd*.bak
testdd: xd
xd -nd -ad xd xd1.bak
xd -nd -ad -l xd1.bak xd2.bak
cmp xd2.bak xd
xd -nd -ad -c xd xd3.bak
xd -nd -ad -l xd3.bak xd4.bak
cmp xd4.bak xd
xd -nd -ad -l -s xd3.bak xd4.bak
cmp xd4.bak xd
sed 's/........//' xd3.bak >xd5.bak
xd -nd -ad -l -s xd5.bak xd6.bak
cmp xd6.bak xd
echo Hello there >xd10.bak
xd -nd -ad xd10.bak >xd7.bak
sed '1d' xd3.bak >>xd7.bak
xd -nd -ad -l -s xd7.bak xd8.bak
cp xd10.bak xd9.bak
tail --bytes=+17 xd >>xd9.bak
cmp xd8.bak xd9.bak
rm xd*.bak
testdo: xd
xd -no -ah xd xd1.bak
xd -no -ah -l xd1.bak xd2.bak
cmp xd2.bak xd
xd -no -ah -c xd xd3.bak
xd -no -ah -l xd3.bak xd4.bak
cmp xd4.bak xd
xd -no -ah -l -s xd3.bak xd4.bak
cmp xd4.bak xd
sed 's/........//' xd3.bak >xd5.bak
xd -no -ah -l -s xd5.bak xd6.bak
cmp xd6.bak xd
echo Hello there >xd10.bak
xd -no -ah xd10.bak >xd7.bak
sed '1d' xd3.bak >>xd7.bak
xd -no -ah -l -s xd7.bak xd8.bak
cp xd10.bak xd9.bak
tail --bytes=+17 xd >>xd9.bak
cmp xd8.bak xd9.bak
rm xd*.bak

BIN
images/xd.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

237
index.html Normal file
View File

@ -0,0 +1,237 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>xd: Extended Dump and Load Utility</title>
<meta name="keywords" content="xd, dump, hexadecimal, octal, decimal, ASCII, ISO" />
<meta name="description" content="xd: Extended Dump and Load Utility" />
<meta name="author" content="John Walker" />
<meta name="robots" content="index" />
<link rel="stylesheet" href="https://www.fourmilab.ch/documents/styles/standard_screen.css"
type="text/css" />
<style type="text/css">
blockquote.rights {
text-align: justify;
font-size: smaller;
font-family: sans-serif;
}
dl.options :first-child {
margin-top: 0px;
}
dl.options dd {
text-align: justify;
}
dl.options dt {
margin-top: 1ex;
padding-bottom: 0px;
}
h3.subtitle {
color: #0000FF;
font-style: italic;
margin-top: 0px;
text-align: center;
}
p {
text-align: justify;
}
</style>
</head>
<body class="standard">
<h1 class="c" style="margin-bottom: 0px;"><img src="images/xd.png"
width="257" height="123" alt="XD" /></h1>
<h3 class="subtitle">Extended Dump and Load Utility</h3>
<hr />
<p>
This page describes, in Unix manual page style,
<b>xd</b>, a utility which dumps files in hexadecimal,
decimal, or octal, with file addresses shown in any of
those formats. <b>xd</b> can read files in any of the
formats it writes, recreating binary files, including
modifications made by editing the dump with any text
editor. In addition, <b>xd</b> can transform a binary
file into a C data declaration which permits embedding
its contents into a program. <b>xd</b> is available as
C source code compatible with most Unix systems.
</p>
<h3>NAME</h3>
<p>
<b>xd</b> &ndash; extended dump and load utility
</p>
<h3>SYNOPSIS</h3>
<p>
<b>xd</b> [ <b>&minus;a</b><i>addrfmt</i> <b>&minus;c</b>
<b>&minus;d</b><i>label</i> <b>&minus;l</b> <b>&minus;n</b><i>datafmt</i>
<b>&minus;s</b> ] [ <i>infile</i> [ <i>outfile</i> ] ]
</p>
<h3>DESCRIPTION</h3>
<p>
<b>xd</b> dumps files in hexadecimal, decimal, or octal, optionally with
ISO characters side by side. File addresses can likewise be
displayed in hex, decimal, or octal notation.
</p>
<p>
<b>xd</b> can <em>read</em> dump files in the same formats it writes and create
binary files from the data therein. This allows you to dump a
binary file with <b>xd</b>, edit it with your favourite text editor,
then make a new binary file containing whatever changes you've
made. When creating a binary file, <b>xd</b> normally assumes you've
only modified data in place (neither expanding nor contracting
the file) and verifies file addresses to guarantee this.
However, a "stream" option is available which ignores file
addresses so you're free to insert and delete bytes at will. <b>xd</b>
thus turns your existing text editor into a binary file editor
without requiring you to learn any new commands.
</p>
<p>
Finally, <b>xd</b> can read a binary file and emit a C language data
declaration which contains the data from the file. This is handy
when you wish to embed binary data within C programs.
</p>
<h3>OPTIONS</h3>
<dl class="options">
<dt><b>&minus;a</b><i>addrfmt</i></dt>
<dd>Displays addresses in the dumped file as specified by
<i>addrfmt</i>: <b>d</b> for decimal, <b>h</b> or
<b>x</b> for hexadecimal, and <b>o</b> for octal. By
default, addresses are shown in hexadecimal.</dd>
<dt><b>&minus;c</b></dt>
<dd>Display ISO characters alongside the numeric
dump. Non-printing characters (according to ISO
8859/1) are shown as periods. The ISO characters are
separated from the dump by vertical bar characters,
which <b>xd</b> treats as comment delimiters when loading a
file.</dd>
<dt><b>&minus;d</b><i>label</i></dt>
<dd>Dumps the file as a C language declaration of an array
of <tt>unsigned char</tt> which, when compiled, will
contain the same data as the binary input file. The C
array declaration is given the variable name
<i>label</i>, or <tt>xd_data</tt> if no label
specification is given. Data are declared as individual
bytes to guarantee portability across architectures with
different byte ordering conventions, and are expressed
as decimal numbers in lines of less than 80 characters
for maximum portability among compilers. The C operator
<tt>sizeof</tt> may be applied to the array <i>label</i>
to obtain its length in bytes.</dd>
<dt><b>&minus;l</b></dt>
<dd>Load file from dump. <b>xd</b> reads a file in the same
format it writes, creating a binary output file. Each
line is assumed to begin with a file address terminated
by a colon. Data bytes are separated by white space,
and any characters after a vertical bar are ignored
(thus discarding any ISO characters included in the dump
with the <b>&minus;c</b> option). If the
<b>&minus;s</b> option is not specified, each file
address is checked against the number of bytes written
so far to guarantee that no bytes have been added or
deleted. Files must be loaded with the <b>&minus;a</b>
and <b>&minus;n</b> options set the same as when the
file was dumped.</dd>
<dt><b>&minus;n</b><i>datafmt</i></dt>
<dd>Edits bytes in the dumped file as specified by
<i>datafmt</i>: <b>d</b> for decimal, <b>h</b> or
<b>x</b> for hexadecimal, and <b>o</b> for octal. By
default, bytes are shown in hexadecimal.</dd>
<dt><b>&minus;s</b></dt>
<dd>Stream input when loading file. If this option is
specified in conjunction with the <b>&minus;l</b> option, file
addresses are not verified when loading a file and, in
fact, need not be specified at all. The input file is
treated as a stream of byte values separated by white
space. This option allows you to create a dump with
<b>xd</b>, edit it as you wish with any text editor,
inserting and deleting bytes in the file wherever you
like, then create a binary file from the modified dump
with the command <b>xd &minus;l &minus;s</b> <i>dumpfile
outfile</i>.</dd>
<dt><b>&minus;u</b></dt>
<dd>Print how-to-call information.</dd>
</dl>
<h3>FILES</h3>
<p>
If no <i>infile</i> is specified, <b>xd</b> obtains its
input from standard input; if no <i>outfile</i> is given,
output is sent to standard output. The input and output are
processed in a strictly serial manner regardless of
options; consequently <b>xd</b> may be used in pipelines
without restrictions.
</p>
<h3>BUGS</h3>
<p>
Input error checking in load mode might be improved. Note
that each byte in load mode must be specified as a number
in the same format selected by the <b>&minus;n</b> option
when the file was dumped, separated by white space, and
that the <b>&minus;a</b> and <b>&minus;n</b> options must
be set the same when loading a file as when it was dumped.
</p>
<h3>SEE ALSO</h3>
<p>
<b>cc</b>(1), <b>od</b>(1), <b>iso_8859_1</b>(7)
</p>
<h2><a href="xd-1.4.tar.gz"><img src="https://www.fourmilab.ch/images/icons/file.png"
alt="[download]" class="button" width="40" height="40" /></a>
<a href="xd-1.4.tar.gz">Download xd-1.4.tar.gz</a> (Gzipped TAR archive)</h2>
<p>
The release archive contains source code, a <tt>Makefile</tt>
for building the program, and documentation in manual page and
HTML form.
</p>
<h3>COPYING</h3>
<blockquote class="rights">
<p>
This software is in the public domain. Permission to use,
copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby
granted, without any conditions or restrictions. This
software is provided &ldquo;as is&rdquo; without express or
implied warranty.
</p>
</blockquote>
<h3 class="nav"><a href="http://www.fourmilab.ch/?topic=unix">Other
Unix Utilities at Fourmilab</a></h3>
<h3 class="nav"><a href="http://www.fourmilab.ch/">Fourmilab Home Page</a></h3>
<p />
<hr />
<address>
by <a href="http://www.fourmilab.ch/">John Walker</a><br />
Version 1.4<br />
October, 2017
</address>
</body>
</html>

49
log.txt Normal file
View File

@ -0,0 +1,49 @@
XD
Development Log
2000 August 29
Added _WIN32 code to xd.c to set input and output text/binary
modes and force modes of standard input and output depending on
the operation being performed. Input is set to binary except
when a "-l" option load is selected, in which case the input
file is text mode and the output is binary.
2000 September 10
Remade logo using Snap ITC font as before, changing background
colour to be white as used in the updated HTML file. Note that
due to an error in this font's bounding box calculation one
must prefix "XD" with a space to avoid truncation of the left
part of the "X".
2000 September 10
Version 1.3.
2017 October 16
Updated Makefile so that the test target works with current versions
of Linux. The options on "tail" have changed since Solaris days in
2000, and we need to include <unistd.h> in the embedded test program
to avoid natters from GCC. Added -Wall to C compiler options.
Eliminated Win32 binaries from the release. They, like the operating
system on which they ran and its regrettable vendor, are impotent and
obsolete.
Removed "lint" target from Makefile. It's obsolete.
Removed "zip" target. We don't support legacy systems.
Cleaned up "tar" target to use tar's built in gzip and renamed
to "dist".
Renamed the "test" target to the more standard "check".
Modified the individual test targets to create their temporary
files in the working directory instead of /tmp, and to clean
up the temporary files at the end of each test.
Version 1.4.

182
xd.1 Normal file
View File

@ -0,0 +1,182 @@
'\" t
.TH XD 1 "29 AUG 2000"
.UC 4
.SH NAME
xd \- extended dump and load utility
.SH SYNOPSIS
.B xd
[
.BI \-a addrfmt
.B \-c
.BI \-d label
.B \-l
.BI \-n datafmt
.B \-s
] [
.I infile
[
.I outfile
] ]
.SH DESCRIPTION
.B xd
dumps files in hexadecimal, decimal, or octal, optionally with ISO characters side by
side.
File addresses can likewise be displayed in hex, decimal, or octal notation.
.PP
.B xd
can
.I read
dump files in the same formats it writes and create binary files from
the data therein. This allows you to dump a binary file with
.BR xd ,
edit it with your favourite text editor, then
make a new binary file containing whatever changes you've made. When
creating a binary file,
.B xd
normally assumes you've only modified data in place (neither expanding
nor contracting the file) and verifies file addresses to guarantee
this. However, a ``stream'' option is available which ignores file
addresses so you're free to insert and delete bytes at
will.
.B xd
thus turns your existing text editor into a binary file editor without
requiring you to learn any new commands.
.PP
Finally,
.B xd
can read a binary file and emit a C language data declaration which
contains the data from the file. This is handy when you wish to embed
binary data within C programs.
.SH OPTIONS
.TP 10
.BI \-a addrfmt
Displays addresses in the dumped file as specified by
.IR addrfmt :
.B d
for decimal,
.B h
or
.B x
for hexadecimal, and
.B o
for octal. By default, addresses are shown in hexadecimal.
.TP
.B \-c
Display ISO characters alongside the numeric dump. Non-printing
characters (according to ISO 8859/1) are shown as periods. The ISO
characters are separated from the dump by vertical bar
characters, which
.B xd
treats as comment delimiters when loading a file.
.TP
.BI \-d label
Dumps the file as a C language declaration of an array of
.B unsigned char
which, when compiled, will contain the same data as the binary input file.
The C array declaration is given the variable name
.IR label ,
or
.B xd_data
if no
.I label
specification is given. Data are declared as individual bytes to
guarantee portability across architectures with different byte ordering
conventions, and are expressed as decimal numbers in lines of less than
80 characters for maximum portability among compilers. The
C operator
.B sizeof
may be applied to the array
.I label
to obtain its length in bytes.
.TP
.B \-l
Load file from dump.
.B xd
reads a file in the same format it writes, creating a binary output
file. Each line is assumed to begin with a file address terminated by
a colon. Data bytes are separated by white space,
and any characters after a vertical bar
are ignored (thus discarding any ISO characters included in the
dump with the
.B \-c
option). If the
.B \-s
option is not specified, each file address is checked against the
number of bytes written so far to guarantee that no bytes have been
added or deleted.
Files must be loaded with the
.B \-a
and
.B \-n
options set the same as when the file was dumped.
.TP
.BI \-n datafmt
Edits bytes in the dumped file as specified by
.IR datafmt :
.B d
for decimal,
.B h
or
.B x
for hexadecimal, and
.B o
for octal. By default, bytes are shown in hexadecimal.
.TP
.B \-s
Stream input when loading file. If this option is specified in conjunction
with the
.B \-l
option, file addresses are not verified when loading a file and, in fact,
need not be specified at all. The input file is treated as a stream
of byte values separated by white space. This option allows
you to create a dump with
.BR xd ,
edit it as you wish with any text editor, inserting and deleting bytes
in the file wherever you like, then create a binary file from the
modified dump with the command
.B xd \-l \-s
.IR "dumpfile outfile" .
.TP
.B \-u
Print how-to-call information.
.SH FILES
If no
.I infile
is specified,
.B xd
obtains its input from standard input; if no
.I outfile
is given, output is sent to standard output. The input and
output are processed in a strictly serial manner regardless
of options; consequently
.B xd
may be used in pipelines without restrictions.
.SH BUGS
.PP
Input error checking in load mode might be improved. Note that each
byte in load mode must be specified as a number in the same format
selected by the
.B \-n
option when the file was dumped,
separated by white space, and that the
.B \-a
and
.B \-n
options must be set the same when loading a file as
when it was dumped.
.SH "SEE ALSO"
.PD
.BR cc (1),
.BR od (1),
.BR iso_8859_1 (7)
.ne 10
.SH AUTHOR
.ce 2
John Walker
http://www.fourmilab.ch/
.PP
This software is in the public domain.
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
without any conditions or restrictions. This software is provided ``as
is'' without express or implied warranty.

407
xd.c Normal file
View File

@ -0,0 +1,407 @@
/*
Extended dump and load utility
by John Walker
http://www.fourmilab.ch/
This program is in the public domain.
*/
#define Version \
"1.4 -- October 2017"
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#ifdef _WIN32
#include <fcntl.h>
#include <io.h>
#endif
#define FALSE 0
#define TRUE 1
#define EOS '\0'
static char addrformat[80] = "%6X";
static char scanaddr[80] = "%lx%c";
static char dataformat1[80] = "%02X";
static char scandata[80] = "%x%n%c";
static int bytesperline = 16, doublechar = FALSE,
dflen = 2, loading = FALSE, streaming = FALSE;
static unsigned long fileaddr;
static unsigned char lineecho[32];
/* OUTLINE -- Edit a line of binary data into the selected output
format. */
static void outline(out, dat, len)
FILE *out;
unsigned char *dat;
int len;
{
char oline[132];
int i;
sprintf(oline, addrformat, fileaddr);
strcat(oline, ":");
for (i = 0; i < len; i++) {
char outedit[80];
sprintf(outedit, dataformat1, dat[i]);
strcat(oline, (i == (bytesperline / 2)) ? " " : " ");
strcat(oline, outedit);
}
if (doublechar) {
char oc[2];
int shortfall = ((bytesperline - len) * (dflen + 1)) +
(len <= (bytesperline / 2) ? 1 : 0);
while (shortfall-- > 0) {
strcat(oline, " ");
}
oc[1] = EOS;
strcat(oline, " | ");
for (i = 0; i < len; i++) {
int b = dat[i];
/* Map non-printing characters to "." according to the
definitions for ISO 8859/1 Latin-1. */
if ((b < ' ') || (b > '~' && b < 160)) {
b = '.';
}
/* Many existing systems which support Latin-1 lack
a definition for character 160, the non-breaking
space. Translate this to a space to avoid
confusion. */
if (b == 160) {
b = ' ';
}
oc[0] = (char) b;
strcat(oline, oc);
}
}
strcat(oline, "\n");
fputs(oline, out);
}
/* INTERPLINE -- Interpret a line of input. */
static int interpline(line, lineno, out)
char *line;
int lineno;
FILE *out;
{
char *cp = line;
char c;
unsigned long lfaddr;
int gfaddr = FALSE;
/* Scan the line for a possible alternative format information
following a vertical bar and delete it. */
while ((c = *cp++) != EOS) {
if (c == '|') {
cp[-1] = EOS;
break;
}
}
/* Scan the line for a file address terminated by a colon. Save
the file address. */
cp = line;
while ((c = *cp++) != EOS) {
if (c == ':') {
int sa;
char tchar;
cp[-1] = EOS;
sa = sscanf(line, scanaddr, &lfaddr, &tchar);
if (sa == 0 || (sa > 1 && tchar != EOS)) {
fprintf(stderr,
"Bad file address \"%s\" on line %d:\n",
line, lineno);
return FALSE;
}
gfaddr = TRUE;
cp[-1] = ':';
break;
}
}
if (!gfaddr) {
cp = line;
}
if (!streaming) {
if (!gfaddr) {
fprintf(stderr, "File address missing on line %d:\n", lineno);
fprintf(stderr, "%s\n", line);
return FALSE;
}
if (lfaddr != fileaddr) {
fprintf(stderr, "File address sequence error on line %d.\n",
lineno);
fprintf(stderr, " Expected ");
fprintf(stderr, addrformat, fileaddr);
fprintf(stderr, ", received ");
fprintf(stderr, addrformat, lfaddr);
fprintf(stderr, ".\n");
fprintf(stderr, "%s\n", line);
return FALSE;
}
}
while ((c = *cp++) != EOS) {
if (!isspace(c)) {
int scanl, nscan, dvalue;
char termchar;
if (((scanl = sscanf(cp - 1, scandata, &dvalue, &nscan, &termchar)) == 0) ||
(dvalue < 0) || (dvalue > 255) ||
(scanl == 2 && !isspace(termchar))) {
fprintf(stderr, "Improper value, \"%s\" on line %d:\n",
cp - 1, lineno);
fprintf(stderr, "%s\n", line);
fprintf(stderr, "Bytes must be specified as digits separated by white space.\n");
return FALSE;
}
putc((char) dvalue, out);
fileaddr++;
cp += nscan;
}
}
return TRUE;
}
/* Main program */
int main(argc, argv)
int argc; char *argv[];
{
int i, b, bp, cdata = FALSE, f = 0;
char *cp, *clabel, opt;
FILE *in = stdin, *out = stdout;
for (i = 1; i < argc; i++) {
cp = argv[i];
if (*cp == '-') {
opt = *(++cp);
if (islower(opt)) {
opt = (char) toupper(opt);
}
switch (opt) {
case 'A': /* -Af -- Set address format */
opt = cp[1];
if (islower(opt)) {
opt = (char) toupper(opt);
}
switch (opt) {
case 'D':
strcpy(addrformat, "%8d");
strcpy(scanaddr, "%ld%c");
break;
case 'H':
case 'X':
strcpy(addrformat, "%6X");
strcpy(scanaddr, "%lx%c");
break;
case 'O':
strcpy(addrformat, "%8o");
strcpy(scanaddr, "%lo%c");
break;
default:
fprintf(stderr,
"Invalid address format '%c'. Must be D, H, or O.\n", cp[1]);
return 2;
}
break;
case 'C':
doublechar = TRUE;
break;
case 'D':
cdata = TRUE;
clabel = cp + 1;
break;
case 'L':
loading = TRUE;
break;
case 'N': /* -Nf -- Set numeric dump format */
opt = cp[1];
if (islower(opt)) {
opt = (char) toupper(opt);
}
switch (opt) {
case 'D':
strcpy(dataformat1, "%3d");
strcpy(scandata, "%d%n%c");
break;
case 'H':
case 'X':
strcpy(dataformat1, "%02X");
strcpy(scandata, "%x%n%c");
break;
case 'O':
strcpy(dataformat1, "%03o");
strcpy(scandata, "%o%n%c");
break;
default:
fprintf(stderr,
"Invalid numeric dump format '%c'. Must be D, H, or O.\n", cp[1]);
return 2;
}
break;
case 'S':
streaming = TRUE;
break;
case '?':
case 'H':
case 'U':
fprintf(stderr, "XD -- Extended dump. Call with xd [input [output]]\n");
fprintf(stderr, "\n");
fprintf(stderr, " Options:\n");
fprintf(stderr, " -af Print addresses in f = Decimal, Hex, or Octal\n");
fprintf(stderr, " -c Dump as ISO characters\n");
fprintf(stderr, " -dlabel Dump as a C data declaration\n");
fprintf(stderr, " -l Load file from hex dump\n");
fprintf(stderr, " -nf Numeric dump in f = Decimal, Hex, or Octal\n");
fprintf(stderr, " -s Stream load (don't check file addresses)\n");
fprintf(stderr, " -u Print this message\n");
fprintf(stderr, "\nBy John Walker, http://www.fourmilab.ch/\n");
fprintf(stderr,"Version %s\n", Version);
return 0;
}
} else {
switch (f) {
case 0:
/** Warning! On systems which distinguish text mode and
binary I/O (MS-DOS, Macintosh, etc.) the modes in these
open statements will have to be made conditional based
upon whether an encode or decode is being done, which
will have to be specified earlier. But it's worse: if
input or output is from standard input or output, the
mode will have to be changed on the fly, which is
generally system and compiler dependent. 'Twasn't me
who couldn't conform to Unix CR/LF convention, so
don't ask me to write the code to work around
Apple and Microsoft's incompatible standards.
This file contains code, conditional on _WIN32, which
sets binary mode using the method prescribed by
Microsoft Visual C 1.52 ("Monkey C"); this may
require modification if you're using a different
compiler or release of Monkey C. */
if ((in = fopen(cp, loading ? "r" : "rb")) == NULL) {
fprintf(stderr, "Cannot open input file %s\n", cp);
return 2;
}
f++;
break;
case 1:
if ((out = fopen(cp, loading ? "wb" : "w")) == NULL) {
fprintf(stderr, "Cannot open output file %s\n", cp);
return 2;
}
f++;
break;
default:
fprintf(stderr, "Too many file names specified.\n");
}
}
}
#ifdef _WIN32
/* If input is from standard input and we aren't loading
from a dump file, set the input file mode to binary. */
if ((in == stdin) && (!loading)) {
_setmode(_fileno(in), _O_BINARY);
}
/* If output is to standard output and we're loading a
binary file from a dump, set the output file mode to
binary. */
if ((out == stdout) && (loading)) {
_setmode(_fileno(out), _O_BINARY);
}
#endif
bp = 0;
fileaddr = 0;
if (loading) {
char in_line[256];
int lineno = 0;
while (fgets(in_line, (sizeof in_line) - 2, in)) {
lineno++;
if (!interpline(in_line, lineno, out)) {
fclose(out);
return 2;
}
}
} else {
if (cdata) {
char cout[80];
fprintf(out, "unsigned char %s[] = {\n",
clabel[0] == EOS ? "xd_data" : clabel);
strcpy(cout, " ");
while ((b = getc(in)) != EOF) {
if (strlen(cout) > 72) {
fprintf(out, "%s\n", cout);
strcpy(cout, " ");
}
sprintf(cout + strlen(cout), "%d,", b);
}
if (strlen(cout) > 4) {
cout[strlen(cout) - 1] = EOS; /* Strip trailing comma */
fprintf(out, "%s\n", cout);
}
fprintf(out, "};\n");
} else {
while ((b = getc(in)) != EOF) {
if (bp >= bytesperline) {
outline(out, lineecho, bp);
bp = 0;
fileaddr += bytesperline;
}
lineecho[bp++] = (char) b;
}
if (bp > 0) {
outline(out, lineecho, bp);
}
}
}
return 0;
}