fold.c (2225B)
1 /* See LICENSE file for copyright and license details. */ 2 #include <ctype.h> 3 #include <stdint.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <string.h> 7 8 #include "text.h" 9 #include "util.h" 10 11 static int bflag = 0; 12 static int sflag = 0; 13 static size_t width = 80; 14 15 static void 16 foldline(struct line *l) { 17 size_t i, col, last, spacesect, len; 18 19 for (i = 0, last = 0, col = 0, spacesect = 0; i < l->len; i++) { 20 if (!UTF8_POINT(l->data[i]) && !bflag) 21 continue; 22 if (col >= width) { 23 len = ((sflag && spacesect) ? spacesect : i) - last; 24 if (fwrite(l->data + last, 1, len, stdout) != len) 25 eprintf("fwrite <stdout>:"); 26 putchar('\n'); 27 last = (sflag && spacesect) ? spacesect : i; 28 col = 0; 29 spacesect = 0; 30 } 31 if (sflag && isspace(l->data[i])) 32 spacesect = i + 1; 33 if (!bflag && iscntrl(l->data[i])) { 34 switch(l->data[i]) { 35 case '\b': 36 col -= (col > 0); 37 break; 38 case '\r': 39 col = 0; 40 break; 41 case '\t': 42 col += (col + 1) % 8; 43 break; 44 } 45 } else { 46 col++; 47 } 48 } 49 if (l->len - last) 50 fwrite(l->data + last, 1, l->len - last, stdout); 51 } 52 53 static void 54 fold(FILE *fp, const char *fname) 55 { 56 static struct line line; 57 static size_t size = 0; 58 ssize_t len; 59 60 while ((len = getline(&line.data, &size, fp)) > 0) { 61 line.len = len; 62 foldline(&line); 63 } 64 if (ferror(fp)) 65 eprintf("getline %s:", fname); 66 } 67 68 static void 69 usage(void) 70 { 71 eprintf("usage: %s [-bs] [-w num | -num] [FILE ...]\n", argv0); 72 } 73 74 int 75 main(int argc, char *argv[]) 76 { 77 FILE *fp; 78 int ret = 0; 79 80 ARGBEGIN { 81 case 'b': 82 bflag = 1; 83 break; 84 case 's': 85 sflag = 1; 86 break; 87 case 'w': 88 width = estrtonum(EARGF(usage()), 1, MIN(LLONG_MAX, SIZE_MAX)); 89 break; 90 ARGNUM: 91 if (!(width = ARGNUMF())) 92 eprintf("illegal width value, too small\n"); 93 break; 94 default: 95 usage(); 96 } ARGEND 97 98 if (!argc) { 99 fold(stdin, "<stdin>"); 100 } else { 101 for (; *argv; argc--, argv++) { 102 if (!strcmp(*argv, "-")) { 103 *argv = "<stdin>"; 104 fp = stdin; 105 } else if (!(fp = fopen(*argv, "r"))) { 106 weprintf("fopen %s:", *argv); 107 ret = 1; 108 continue; 109 } 110 fold(fp, *argv); 111 if (fp != stdin && fshut(fp, *argv)) 112 ret = 1; 113 } 114 } 115 116 ret |= fshut(stdin, "<stdin>") | fshut(stdout, "<stdout>"); 117 118 return ret; 119 }