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