aboutsummaryrefslogtreecommitdiff
path: root/uxd.c
diff options
context:
space:
mode:
authorB. Watson <urchlay@slackware.uk>2024-12-15 05:06:41 -0500
committerB. Watson <urchlay@slackware.uk>2024-12-15 05:06:41 -0500
commit6d2ed7484a29e5a093f24dd5fbbe3522029b4816 (patch)
tree9daa91f4b0afea40057b66ac788414ef72809480 /uxd.c
parentcb94cb60fe5a750ed670d89efe3d9233bf0c9b38 (diff)
downloaduxd-6d2ed7484a29e5a093f24dd5fbbe3522029b4816.tar.gz
implement -s and -S (seek) options.
Diffstat (limited to 'uxd.c')
-rw-r--r--uxd.c69
1 files changed, 66 insertions, 3 deletions
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;