diff options
Diffstat (limited to 'uxd.c')
-rw-r--r-- | uxd.c | 69 |
1 files changed, 66 insertions, 3 deletions
@@ -42,6 +42,10 @@ extern int optind; #define VERSION "(unknown version)" #endif +#ifndef BUFSIZ +#define BUFSIZ 4096 +#endif + /* ANSI colors */ #define BLACK 0 /* don't use (could be the background color) */ #define RED 1 @@ -77,7 +81,8 @@ int bold = 0; /* -b */ int hilite_multi = 0; /* -r */ int mono = 0; /* -m */ long display_offset = 0; /* -o */ -long seekpos = 0; /* -s */ +long seekpos = 0; /* -s, -S */ +int seek_offset_zero = 0; /* -S */ long limit; /* -l */ const char *hex_byte_fmt = "%02x"; /* -u */ const char *hex_word_fmt = "%04x: "; /* " */ @@ -121,7 +126,7 @@ void parse_options(int argc, char **argv) { version(); } - while((opt = my_getopt(argc, argv, "bl:rmo:s:uhv")) != -1) { + while((opt = my_getopt(argc, argv, "bl:rmo:S:s:uhv")) != -1) { switch(opt) { case 'b': bold = 1; break; @@ -133,8 +138,12 @@ void parse_options(int argc, char **argv) { mono = 1; break; case 'o': display_offset = parse_number(optarg); break; + case 'S': + seek_offset_zero = 1; + /* fall thru */ case 's': - seekpos = parse_number(optarg); break; + seekpos = parse_number(optarg); + break; case 'u': hex_byte_fmt = "%02X"; hex_word_fmt = "%04X: "; break; case 'h': @@ -381,7 +390,61 @@ int dump_utf8_char(void) { return 1; } +/* this only gets called when reading stdin. */ +void skip_input(unsigned int bytes) { + char tmp[BUFSIZ]; + + if(fread(tmp, 1, bytes, input) < bytes) { + if(feof(input)) return; + + /* this probably never happens when reading from stdin: */ + fprintf(stderr, "%s: ", self); + perror("fread()"); + exit(1); + } +} + +/* this only gets called when reading stdin. */ +void fake_seek(void) { + long i = seekpos; + + while(i >= BUFSIZ) { + skip_input(BUFSIZ); + if(feof(input)) return; + i -= BUFSIZ; + } + + skip_input(i); +} + +/* used by -s option */ +void seek_input(void) { + int whence = SEEK_SET; + + if(seekpos < 0) { + whence = SEEK_END; + } + + if(fseek(input, seekpos, whence) == 0) { + filepos = ftell(input); + return; + } + + /* fseek() failed, likely we're reading stdin. fake it, if we can. */ + if(whence == SEEK_SET) { + clearerr(input); + fake_seek(); + filepos = seekpos; + } else { + perror(self); + exit(1); + } +} + void dump_file(void) { + if(seekpos) seek_input(); + if(seek_offset_zero) filepos = 0; + while(dump_utf8_char()) if(limit && (filepos >= limit)) break; |