From ad20c5466321f6c8bd3006953b3b37e50935cdb4 Mon Sep 17 00:00:00 2001 From: "B. Watson" Date: Sat, 29 Jun 2024 21:45:25 -0400 Subject: a8xd: implement -o, -s, -l, add more messages for -v. --- a8xd.1 | 14 +++++++++---- a8xd.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++------------- a8xd.rst | 14 +++++++++---- 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 -- cgit v1.2.3