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 }