From 6d2ed7484a29e5a093f24dd5fbbe3522029b4816 Mon Sep 17 00:00:00 2001 From: "B. Watson" Date: Sun, 15 Dec 2024 05:06:41 -0500 Subject: implement -s and -S (seek) options. --- uxd.1 | 9 ++++++--- uxd.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- uxd.rst | 6 +++++- 3 files changed, 77 insertions(+), 7 deletions(-) diff --git a/uxd.1 b/uxd.1 index eb8b99c..67c1881 100644 --- a/uxd.1 +++ b/uxd.1 @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "UXD" 1 "2024-12-14" "0.1.0" "Urchlay's Utilities" +.TH "UXD" 1 "2024-12-15" "0.1.0" "Urchlay's Utilities" .SH NAME uxd \- UTF-8 hex dumper .SH SYNOPSIS @@ -60,7 +60,6 @@ over the environment. .B \-b Bold output. This may be more or less readable, depending on your terminal and its color settings. Ignored if \fB\-m\fP given. -NOT IMPLEMENTED YET. .TP .BI \-c \ nnnn Set the colors to use. Must be 2 to 4 digits, from 0 to 7. These are @@ -99,7 +98,11 @@ Seek in input before starting to dump. \fIpos\fP is bytes, not characters. Positive \fIpos\fP means seek from the start of the input. Negative \fIpos\fP only works on files (not standard input); it means seek backward from EOF. -NOT IMPLEMENTED YET. +.TP +.BI \-S \ pos +Same as \fB\-s\fP, but file offsets start at 0 rather than the +position after seeking. \fB\-S 100\fP is the same as \fB\-s 100 \-o \-100\fP\&. +Works with negative \fIpos\fP, too. .TP .B \-u Use uppercase hex digits A\-F. Default is lowercase. diff --git a/uxd.c b/uxd.c index c235777..866ad78 100644 --- a/uxd.c +++ b/uxd.c @@ -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; diff --git a/uxd.rst b/uxd.rst index 170c46f..c4e06be 100644 --- a/uxd.rst +++ b/uxd.rst @@ -87,7 +87,11 @@ over the environment. characters. Positive *pos* means seek from the start of the input. Negative *pos* only works on files (not standard input); it means seek backward from EOF. - NOT IMPLEMENTED YET. + +-S pos + Same as **-s**, but file offsets start at 0 rather than the + position after seeking. **-S 100** is the same as **-s 100 -o -100**. + Works with negative *pos*, too. -u Use uppercase hex digits A-F. Default is lowercase. -- cgit v1.2.3