commit 6a4b7a68fadb19c6f2ed4af8e538dcbdcc9e2f5e Author: Alexander Popov Date: Sun Jul 30 11:24:54 2023 +0300 1.4 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..82279de --- /dev/null +++ b/Makefile @@ -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 \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 diff --git a/images/xd.png b/images/xd.png new file mode 100644 index 0000000..cb98196 Binary files /dev/null and b/images/xd.png differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..3bf845c --- /dev/null +++ b/index.html @@ -0,0 +1,237 @@ + + + + +xd: Extended Dump and Load Utility + + + + + + + + + + +

XD

+

Extended Dump and Load Utility

+ +
+ +

+This page describes, in Unix manual page style, +xd, a utility which dumps files in hexadecimal, +decimal, or octal, with file addresses shown in any of +those formats. xd 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, xd can transform a binary +file into a C data declaration which permits embedding +its contents into a program. xd is available as +C source code compatible with most Unix systems. +

+ +

NAME

+

+ xd – extended dump and load utility +

+ +

SYNOPSIS

+

+ xd [ −aaddrfmt −c + −dlabel −l −ndatafmt + −s ] [ infile [ outfile ] ] +

+ +

DESCRIPTION

+

+ 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. +

+ +

+ xd can 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 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, 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. xd + thus turns your existing text editor into a binary file editor + without requiring you to learn any new commands. +

+ +

+ Finally, 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. +

+ +

OPTIONS

+ +
+
−aaddrfmt
+
Displays addresses in the dumped file as specified by + addrfmt: d for decimal, h or + x for hexadecimal, and o for octal. By + default, addresses are shown in hexadecimal.
+ +
−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 xd treats as comment delimiters when loading a + file.
+ +
−dlabel
+
Dumps the file as a C language declaration of an array + of unsigned char which, when compiled, will + contain the same data as the binary input file. The C + array declaration is given the variable name + label, or xd_data 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 + sizeof may be applied to the array label + to obtain its length in bytes.
+ +
−l
+
Load file from dump. 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 −c option). If the + −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 −a + and −n options set the same as when the + file was dumped.
+ +
−ndatafmt
+
Edits bytes in the dumped file as specified by + datafmt: d for decimal, h or + x for hexadecimal, and o for octal. By + default, bytes are shown in hexadecimal.
+ +
−s
+
Stream input when loading file. If this option is + specified in conjunction with the −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 + 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 xd −l −s dumpfile + outfile.
+ +
−u
+
Print how-to-call information.
+
+ +

FILES

+

+ If no infile is specified, xd obtains its + input from standard input; if no outfile is given, + output is sent to standard output. The input and output are + processed in a strictly serial manner regardless of + options; consequently xd may be used in pipelines + without restrictions. +

+ +

BUGS

+

+ 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 −n option + when the file was dumped, separated by white space, and + that the −a and −n options must + be set the same when loading a file as when it was dumped. +

+ +

SEE ALSO

+

+ cc(1), od(1), iso_8859_1(7) +

+ +

[download] + Download xd-1.4.tar.gz (Gzipped TAR archive)

+ +

+The release archive contains source code, a Makefile +for building the program, and documentation in manual page and +HTML form. +

+ +

COPYING

+ +
+

+ 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. +

+
+ + + + +

+


+ +
+by John Walker
+Version 1.4
+October, 2017 +
+ + + diff --git a/log.txt b/log.txt new file mode 100644 index 0000000..fe4967c --- /dev/null +++ b/log.txt @@ -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 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. diff --git a/xd.1 b/xd.1 new file mode 100644 index 0000000..9cb781f --- /dev/null +++ b/xd.1 @@ -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. diff --git a/xd.c b/xd.c new file mode 100644 index 0000000..48b2854 --- /dev/null +++ b/xd.c @@ -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 +#include +#include +#ifdef _WIN32 +#include +#include +#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; +}