sbase

suckless unix tools
git clone git://git.suckless.org/sbase
Log | Files | Refs | README | 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 }