strings.c - sbase - suckless unix tools
(HTM) git clone git://git.suckless.org/sbase
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
strings.c (1708B)
---
1 /* See LICENSE file for copyright and license details. */
2 #include <limits.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 #include "utf.h"
8 #include "util.h"
9
10 static char *format = "";
11
12 static void
13 strings(FILE *fp, const char *fname, size_t min)
14 {
15 Rune r, *rbuf;
16 size_t i, bread;
17 off_t off;
18
19 rbuf = ereallocarray(NULL, min, sizeof(*rbuf));
20
21 for (off = 0, i = 0; (bread = efgetrune(&r, fp, fname)); ) {
22 off += bread;
23 if (r == Runeerror)
24 continue;
25 if (!isprintrune(r)) {
26 if (i == min)
27 putchar('\n');
28 i = 0;
29 continue;
30 }
31 if (i == min) {
32 efputrune(&r, stdout, "<stdout>");
33 continue;
34 }
35 rbuf[i++] = r;
36 if (i < min)
37 continue;
38 printf(format, (long)off - i);
39 for (i = 0; i < min; i++)
40 efputrune(rbuf + i, stdout, "<stdout>");
41 }
42 free(rbuf);
43 }
44
45 static void
46 usage(void)
47 {
48 eprintf("usage: %s [-a] [-n num] [-t format] [file ...]\n", argv0);
49 }
50
51 int
52 main(int argc, char *argv[])
53 {
54 FILE *fp;
55 size_t min = 4;
56 int ret = 0;
57 char f;
58
59 ARGBEGIN {
60 case 'a':
61 break;
62 case 'n':
63 min = estrtonum(EARGF(usage()), 1, LLONG_MAX);
64 break;
65 case 't':
66 format = estrdup("%8l#: ");
67 f = *EARGF(usage());
68 if (f == 'd' || f == 'o' || f == 'x')
69 format[3] = f;
70 else
71 usage();
72 break;
73 default:
74 usage();
75 } ARGEND
76
77 if (!argc) {
78 strings(stdin, "<stdin>", min);
79 } else {
80 for (; *argv; argc--, argv++) {
81 if (!strcmp(*argv, "-")) {
82 *argv = "<stdin>";
83 fp = stdin;
84 } else if (!(fp = fopen(*argv, "r"))) {
85 weprintf("fopen %s:", *argv);
86 ret = 1;
87 continue;
88 }
89 strings(fp, *argv, min);
90 if (fp != stdin && fshut(fp, *argv))
91 ret = 1;
92 }
93 }
94
95 ret |= fshut(stdin, "<stdin>") | fshut(stdout, "<stdout>");
96
97 return ret;
98 }