diff options
Diffstat (limited to 'a8xd.c')
-rw-r--r-- | a8xd.c | 73 |
1 files changed, 59 insertions, 14 deletions
@@ -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; } } |