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 }