wc.c - sbase - suckless unix tools | |
git clone git://git.suckless.org/sbase | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
wc.c (1853B) | |
--- | |
1 /* See LICENSE file for copyright and license details. */ | |
2 #include <string.h> | |
3 | |
4 #include "utf.h" | |
5 #include "util.h" | |
6 | |
7 static int lflag = 0; | |
8 static int wflag = 0; | |
9 static char cmode = 0; | |
10 static size_t tc = 0, tl = 0, tw = 0; | |
11 | |
12 static void | |
13 output(const char *str, size_t nc, size_t nl, size_t nw) | |
14 { | |
15 int first = 1; | |
16 | |
17 if (lflag) { | |
18 first = 0; | |
19 printf("%zu", nl); | |
20 } | |
21 if (wflag) { | |
22 if (!first) | |
23 putchar(' '); | |
24 first = 0; | |
25 printf("%zu", nw); | |
26 } | |
27 if (cmode) { | |
28 if (!first) | |
29 putchar(' '); | |
30 printf("%zu", nc); | |
31 } | |
32 if (str) | |
33 printf(" %s", str); | |
34 putchar('\n'); | |
35 } | |
36 | |
37 static void | |
38 wc(FILE *fp, const char *str) | |
39 { | |
40 int word = 0, rlen; | |
41 Rune c; | |
42 size_t nc = 0, nl = 0, nw = 0; | |
43 | |
44 while ((rlen = efgetrune(&c, fp, str))) { | |
45 nc += (cmode == 'c') ? rlen : (c != Runeerror); | |
46 if (c == '\n') | |
47 nl++; | |
48 if (!isspacerune(c)) | |
49 word = 1; | |
50 else if (word) { | |
51 word = 0; | |
52 nw++; | |
53 } | |
54 } | |
55 if (word) | |
56 nw++; | |
57 tc += nc; | |
58 tl += nl; | |
59 tw += nw; | |
60 output(str, nc, nl, nw); | |
61 } | |
62 | |
63 static void | |
64 usage(void) | |
65 { | |
66 eprintf("usage: %s [-c | -m] [-lw] [file ...]\n", argv0); | |
67 } | |
68 | |
69 int | |
70 main(int argc, char *argv[]) | |
71 { | |
72 FILE *fp; | |
73 int many; | |
74 int ret = 0; | |
75 | |
76 ARGBEGIN { | |
77 case 'c': | |
78 cmode = 'c'; | |
79 break; | |
80 case 'm': | |
81 cmode = 'm'; | |
82 break; | |
83 case 'l': | |
84 lflag = 1; | |
85 break; | |
86 case 'w': | |
87 wflag = 1; | |
88 break; | |
89 default: | |
90 usage(); | |
91 } ARGEND | |
92 | |
93 if (!lflag && !wflag && !cmode) { | |
94 cmode = 'c'; | |
95 lflag = 1; | |
96 wflag = 1; | |
97 } | |
98 | |
99 if (!argc) { | |
100 wc(stdin, NULL); | |
101 } else { | |
102 for (many = (argc > 1); *argv; argc--, argv++) { | |
103 if (!strcmp(*argv, "-")) { | |
104 *argv = "<stdin>"; | |
105 fp = stdin; | |
106 } else if (!(fp = fopen(*argv, "r"))) { | |
107 weprintf("fopen %s:", *argv); | |
108 ret = 1; | |
109 continue; | |
110 } | |
111 wc(fp, *argv); | |
112 if (fp != stdin && fshut(fp, *argv)) | |
113 ret = 1; | |
114 } | |
115 if (many) | |
116 output("total", tc, tl, tw); | |
117 } | |
118 | |
119 ret |= fshut(stdin, "<stdin>") | fshut(stdout, "<stdout>"); | |
120 | |
121 return ret; | |
122 } |