aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--a8xd.114
-rw-r--r--a8xd.c73
-rw-r--r--a8xd.rst14
3 files changed, 79 insertions, 22 deletions
diff --git a/a8xd.1 b/a8xd.1
index 385983e..1995470 100644
--- a/a8xd.1
+++ b/a8xd.1
@@ -73,7 +73,7 @@ Print XL/XE International Character Set conversions instead of ATASCII.
.INDENT 0.0
.TP
.B \-l \fIlen\fP
-\fB*\fP Stop after dumping \fIlen\fP bytes. \fIlen\fP may be given in decimal or hex (with
+Stop after dumping \fIlen\fP bytes. \fIlen\fP may be given in decimal or hex (with
leading \fI0x\fP or \fI$\fP).
.UNINDENT
.INDENT 0.0
@@ -86,10 +86,12 @@ set are still displayed in inverse.
.TP
.B \-o \fIoffset\fP
Add \fIoffset\fP to displayed file position. \fIoffset\fP can be given in decimal
-or hex (with leading \fI0x\fP or \fI$\fP).
+or hex (with leading \fI0x\fP or \fI$\fP). Negative offsets are allowed, but they
+will be printed as very large positive numbers in the output (this matches
+\fBxxd\fP\(aqs behaviour).
.TP
.B \-s \fI[\-]seek\fP
-\fB*\fP Start at \fIseek\fP bytes. Without \fI\-\fP, this is an absolute offset. With \fI\-\fP,
+Start at \fIseek\fP bytes. Without \fI\-\fP, this is an absolute offset. With \fI\-\fP,
it\(aqs relative to the end of the file. The \fI\-\fP option won\(aqt work when
reading from standard input. \fIseek\fP may be given in decimal or hex
(with leading \fI0x\fP or \fI$\fP).
@@ -100,7 +102,8 @@ reading from standard input. \fIseek\fP may be given in decimal or hex
Use uppercase letters for hex digits; the default is lowercase.
.TP
.B \-v
-Verbose. Currently, this option is accepted, but it doesn\(aqt do anything yet.
+Verbose. Shows various debug messages that are probably only useful
+if you\(aqre hacking on \fBa8xd\fP\&.
.UNINDENT
.INDENT 0.0
.TP
@@ -134,6 +137,9 @@ missing are:
.IP \(bu 2
\fB\-b\fP (bits mode).
.UNINDENT
+.sp
+Another difference is that \fBa8xd\fP doesn\(aqt support files larger than
+2GB. This won\(aqt be a problem for Atari 8\-bit\-related files!
.SH COPYRIGHT
.sp
WTFPL. See \fI\%http://www.wtfpl.net/txt/copying/\fP for details.
diff --git a/a8xd.c b/a8xd.c
index c322624..f051c4b 100644
--- a/a8xd.c
+++ b/a8xd.c
@@ -54,7 +54,6 @@ void parse_seek_arg(const char *arg) {
if(*arg == '-') {
seek_whence = SEEK_END;
- arg++;
}
seekpos = parse_num_arg(arg);
@@ -64,8 +63,6 @@ int parse_offset_arg(const char *arg) {
int got;
got = parse_num_arg(arg);
- if(got < 0)
- die("negative arguments to -o (offset) are not supported.");
return got;
}
@@ -84,22 +81,24 @@ FILE *open_input(const char *file) {
FILE *input;
if(file[0] == '-' && file[1] == 0) {
- if(verbose)
- fprintf(stderr, "%s: reading from standard input.\n", self);
if(freopen(NULL, "rb", stdin)) {
input = stdin;
} else {
+ fprintf(stderr, "%s: ", self);
perror("(standard input)");
return NULL;
}
- } else if(!(input = fopen(file, "rb"))) {
- perror(file);
- return NULL;
+ if(verbose)
+ fprintf(stderr, "%s: reading from standard input.\n", self);
+ } else {
+ if(!(input = fopen(file, "rb"))) {
+ perror(file);
+ return NULL;
+ }
+ if(verbose)
+ fprintf(stderr, "%s: reading from file '%s'.\n", self, file);
}
- if(verbose)
- fprintf(stderr, "%s: reading from file '%s'.\n", self, file);
-
return input;
}
@@ -128,6 +127,44 @@ char *get_color(unsigned char c) {
return outbuf;
}
+void fake_seek(FILE *input) {
+ char junkbuf[1024];
+ int pos = 0, chunksize;
+
+ if(verbose)
+ fprintf(stderr, "%s: faking fseek() for stdin, skipping %d bytes.\n", self, seekpos);
+
+ while(pos < seekpos) {
+ chunksize = seekpos - pos;
+ if(chunksize > 1024) chunksize = 1024;
+ if(fread(junkbuf, 1, chunksize, input) != chunksize)
+ die("can't seek past end of input");
+ pos += chunksize;
+ }
+}
+
+void seek_input(FILE *input) {
+ if(verbose)
+ fprintf(stderr, "%s: seeking %d bytes (whence = %d) in input.\n", self, seekpos, seek_whence);
+ if(input == stdin) {
+ /* can't fseek() a stream, fake it */
+ if(seek_whence != SEEK_SET)
+ die("can't seek from the end of standard input.");
+ fake_seek(input);
+ } else {
+ if(fseek(input, seekpos, seek_whence) < 0) {
+ fprintf(stderr, "%s: ", self);
+ perror("fseek() failed");
+ exit(1);
+ }
+ if((filepos = ftell(input)) < 0) {
+ fprintf(stderr, "%s: ", self);
+ perror("ftell() failed");
+ exit(1);
+ }
+ }
+}
+
void dump_line(const unsigned char *buf, int len) {
char hex[1024], asc[1024];
int hpos = 0, apos = 0, count = len;
@@ -165,13 +202,17 @@ void dump_line(const unsigned char *buf, int len) {
int a8xd(const char *file) {
FILE *input;
- int c, len = 0;
+ int c, len = 0, count = 0;
unsigned char buf[16];
if( !(input = open_input(file)) )
return 1;
+ if(seekpos) seek_input(input);
+
while( (c = fgetc(input)) != EOF ) {
+ if(limit && (count == limit)) break;
+ count++;
if(len && (len % 16 == 0)) {
dump_line(buf, len);
len = 0;
@@ -181,6 +222,10 @@ int a8xd(const char *file) {
if(len) dump_line(buf, len);
+ if(verbose)
+ fprintf(stderr, "%s: dumped %d (0x%04x) bytes from '%s'.\n", self, count, count, file);
+
+ fclose(input);
return 0;
}
@@ -199,7 +244,7 @@ int main(int argc, char **argv) {
exit(0);
}
- while( (opt = getopt(argc, argv, "vimus:o:l")) != -1) {
+ while( (opt = getopt(argc, argv, "vimus:o:l:")) != -1) {
switch(opt) {
case 'v': verbose = 1; break;
case 'i': table = ics2utf; break;
@@ -207,7 +252,7 @@ int main(int argc, char **argv) {
case 'u': word_format = "%04X"; byte_format = "%02X"; break;
case 's': parse_seek_arg(optarg); break;
case 'o': disp_offset = parse_offset_arg(optarg); break;
- case 'l': disp_offset = parse_limit_arg(optarg); break;
+ case 'l': limit = parse_limit_arg(optarg); break;
default: print_help(); exit(1); break;
}
}
diff --git a/a8xd.rst b/a8xd.rst
index ebe3364..4803acc 100644
--- a/a8xd.rst
+++ b/a8xd.rst
@@ -47,7 +47,7 @@ Options marked with **\*** are not yet implemented.
Print XL/XE International Character Set conversions instead of ATASCII.
-l *len*
- **\*** Stop after dumping *len* bytes. *len* may be given in decimal or hex (with
+ Stop after dumping *len* bytes. *len* may be given in decimal or hex (with
leading *0x* or *$*).
-m
@@ -56,10 +56,12 @@ Options marked with **\*** are not yet implemented.
-o *offset*
Add *offset* to displayed file position. *offset* can be given in decimal
- or hex (with leading *0x* or *$*).
+ or hex (with leading *0x* or *$*). Negative offsets are allowed, but they
+ will be printed as very large positive numbers in the output (this matches
+ **xxd**\'s behaviour).
-s *[-]seek*
- **\*** Start at *seek* bytes. Without *-*, this is an absolute offset. With *-*,
+ Start at *seek* bytes. Without *-*, this is an absolute offset. With *-*,
it's relative to the end of the file. The *-* option won't work when
reading from standard input. *seek* may be given in decimal or hex
(with leading *0x* or *$*).
@@ -68,7 +70,8 @@ Options marked with **\*** are not yet implemented.
Use uppercase letters for hex digits; the default is lowercase.
-v
- Verbose. Currently, this option is accepted, but it doesn't do anything yet.
+ Verbose. Shows various debug messages that are probably only useful
+ if you're hacking on **a8xd**.
**--**
End of options; the nex argument is the filename. Use this if you're
@@ -100,4 +103,7 @@ missing are:
- **-b** (bits mode).
+Another difference is that **a8xd** doesn't support files larger than
+2GB. This won't be a problem for Atari 8-bit-related files!
+
.. include:: manftr.rst