unexpand.c (1989B)
1 /* See LICENSE file for copyright and license details. */ 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <wchar.h> 5 6 #include "utf.h" 7 #include "util.h" 8 9 static void unexpand(const char *, FILE *); 10 11 static int aflag = 0; 12 static int tabsize = 8; 13 14 static void 15 usage(void) 16 { 17 eprintf("usage: %s [-a] [-t n] [file ...]\n", argv0); 18 } 19 20 int 21 main(int argc, char *argv[]) 22 { 23 FILE *fp; 24 int ret = 0; 25 26 ARGBEGIN { 27 case 't': 28 tabsize = estrtol(EARGF(usage()), 0); 29 if (tabsize <= 0) 30 eprintf("unexpand: invalid tabsize\n"); 31 /* Fallthrough: -t implies -a */ 32 case 'a': 33 aflag = 1; 34 break; 35 default: 36 usage(); 37 } ARGEND; 38 39 if (argc == 0) { 40 unexpand("<stdin>", stdin); 41 } else { 42 for (; argc > 0; argc--, argv++) { 43 if (!(fp = fopen(argv[0], "r"))) { 44 weprintf("fopen %s:", argv[0]); 45 ret = 1; 46 continue; 47 } 48 unexpand(argv[0], fp); 49 fclose(fp); 50 } 51 } 52 return ret; 53 } 54 55 static void 56 unexpandspan(unsigned int n, unsigned int col) 57 { 58 unsigned int off = (col-n) % tabsize; 59 Rune r; 60 61 if (n + off >= tabsize && n > 1) 62 n += off; 63 64 r = '\t'; 65 for (; n >= tabsize; n -= tabsize) 66 writerune("<stdout>", stdout, &r); 67 r = ' '; 68 while (n--) 69 writerune("<stdout>", stdout, &r); 70 } 71 72 static void 73 unexpand(const char *file, FILE *fp) 74 { 75 unsigned int n = 0, col = 0; 76 Rune r; 77 int bol = 1; 78 79 while (1) { 80 if (!readrune(file, fp, &r)) 81 break; 82 83 switch (r) { 84 case ' ': 85 if (bol || aflag) 86 n++; 87 col++; 88 break; 89 case '\t': 90 if (bol || aflag) 91 n += tabsize - col % tabsize; 92 col += tabsize - col % tabsize; 93 break; 94 case '\b': 95 if (bol || aflag) 96 unexpandspan(n, col); 97 col -= (col > 0); 98 n = 0; 99 bol = 0; 100 break; 101 case '\n': 102 if (bol || aflag) 103 unexpandspan(n, col); 104 n = col = 0; 105 bol = 1; 106 break; 107 default: 108 if (bol || aflag) 109 unexpandspan(n, col); 110 n = 0; 111 col++; 112 bol = 0; 113 } 114 if ((r != ' ' && r != '\t') || (!aflag && !bol)) 115 writerune("<stdout>", stdout, &r); 116 } 117 if (n > 0 && (bol || aflag)) 118 unexpandspan(n, col); 119 }