aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--uxd.19
-rw-r--r--uxd.c69
-rw-r--r--uxd.rst6
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.