sbase

suckless unix tools
git clone git://git.2f30.org/sbase
Log | Files | Refs | README | LICENSE

strings.c (1760B)


      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 len)
     14 {
     15 	Rune r, *rbuf;
     16 	size_t i, bread;
     17 	off_t off;
     18 
     19 	rbuf = ereallocarray(NULL, len, 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 > len)
     27 				putchar('\n');
     28 			i = 0;
     29 			continue;
     30 		}
     31 		if (i < len) {
     32 			rbuf[i++] = r;
     33 			continue;
     34 		} else if (i > len) {
     35 			efputrune(&r, stdout, "<stdout>");
     36 			continue;
     37 		}
     38 		printf(format, (long)off - i);
     39 		for (i = 0; i < len; i++)
     40 			efputrune(rbuf + i, stdout, "<stdout>");
     41 		efputrune(&r, stdout, "<stdout>");
     42 		i++;
     43 	}
     44 	free(rbuf);
     45 }
     46 
     47 static void
     48 usage(void)
     49 {
     50 	eprintf("usage: %s [-a] [-n num] [-t format] [file ...]\n", argv0);
     51 }
     52 
     53 int
     54 main(int argc, char *argv[])
     55 {
     56 	FILE *fp;
     57 	size_t len = 4;
     58 	int ret = 0;
     59 	char f;
     60 
     61 	ARGBEGIN {
     62 	case 'a':
     63 		break;
     64 	case 'n':
     65 		len = estrtonum(EARGF(usage()), 1, LLONG_MAX);
     66 		break;
     67 	case 't':
     68 		format = estrdup("%8l#: ");
     69 		f = *EARGF(usage());
     70 		if (f == 'd' || f == 'o' || f == 'x')
     71 			format[3] = f;
     72 		else
     73 			usage();
     74 		break;
     75 	default:
     76 		usage();
     77 	} ARGEND
     78 
     79 	if (!argc) {
     80 		strings(stdin, "<stdin>", len);
     81 	} else {
     82 		for (; *argv; argc--, argv++) {
     83 			if (!strcmp(*argv, "-")) {
     84 				*argv = "<stdin>";
     85 				fp = stdin;
     86 			} else if (!(fp = fopen(*argv, "r"))) {
     87 				weprintf("fopen %s:", *argv);
     88 				ret = 1;
     89 				continue;
     90 			}
     91 			strings(fp, *argv, len);
     92 			if (fp != stdin && fshut(fp, *argv))
     93 				ret = 1;
     94 		}
     95 	}
     96 
     97 	ret |= fshut(stdin, "<stdin>") | fshut(stdout, "<stdout>");
     98 
     99 	return ret;
    100 }