wc.c - sbase - suckless unix tools
(HTM) git clone git://git.suckless.org/sbase
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) 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 }