1.4
This commit is contained in:
commit
6a4b7a68fa
149
Makefile
Normal file
149
Makefile
Normal 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
BIN
images/xd.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.2 KiB |
237
index.html
Normal file
237
index.html
Normal 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> – extended dump and load utility
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>SYNOPSIS</h3>
|
||||||
|
<p>
|
||||||
|
<b>xd</b> [ <b>−a</b><i>addrfmt</i> <b>−c</b>
|
||||||
|
<b>−d</b><i>label</i> <b>−l</b> <b>−n</b><i>datafmt</i>
|
||||||
|
<b>−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>−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>−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>−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>−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>−c</b> option). If the
|
||||||
|
<b>−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>−a</b>
|
||||||
|
and <b>−n</b> options set the same as when the
|
||||||
|
file was dumped.</dd>
|
||||||
|
|
||||||
|
<dt><b>−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>−s</b></dt>
|
||||||
|
<dd>Stream input when loading file. If this option is
|
||||||
|
specified in conjunction with the <b>−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 −l −s</b> <i>dumpfile
|
||||||
|
outfile</i>.</dd>
|
||||||
|
|
||||||
|
<dt><b>−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>−n</b> option
|
||||||
|
when the file was dumped, separated by white space, and
|
||||||
|
that the <b>−a</b> and <b>−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 “as is” 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
49
log.txt
Normal 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
182
xd.1
Normal 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
407
xd.c
Normal 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;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user