3 * Copyright 2011 Rob Landley <rob@landley.net>
5 * See http://opengroup.org/onlinepubs/9699919799/utilities/wc.html
7 USE_WC(NEWTOY(wc, "mcwl", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE))
13 usage: wc -lwcm [FILE...]
15 Count lines, words, and characters in input.
22 By default outputs lines, words, bytes, and filename for each
23 argument (or from stdin if none). Displays only either bytes
31 unsigned long totals[4];
34 static void show_lengths(unsigned long *lengths, char *name)
36 int i, space = 7, first = 1;
38 for (i = 0; i<4; i++) if (toys.optflags == (1<<i)) space = 0;
39 for (i = 0; i<4; i++) {
40 if (toys.optflags&(1<<i)) {
41 printf(" %*ld"+first, space, lengths[i]);
44 TT.totals[i] += lengths[i];
46 if (*toys.optargs) printf(" %s", name);
50 static void do_wc(int fd, char *name)
52 int len = 0, clen = 1, space = 0;
53 unsigned long word = 0, lengths[] = {0,0,0,0};
55 // Speed up common case: wc -c normalfile is file length.
56 if (toys.optflags == FLAG_c) {
59 // On Linux, files in /proc often report their size as 0.
60 if (!fstat(fd, &st) && S_ISREG(st.st_mode) && st.st_size) {
61 lengths[2] = st.st_size;
67 int pos, done = 0, len2 = read(fd, toybuf+len, sizeof(toybuf)-len);
69 if (len2<0) perror_msg_raw(name);
73 for (pos = 0; pos<len; pos++) {
74 if (toybuf[pos]=='\n') lengths[0]++;
76 if (toys.optflags&FLAG_m) {
77 // If we've consumed next wide char
81 // next wide size, don't count invalid, fetch more data if necessary
82 clen = mbrtowc(&wchar, toybuf+pos, len-pos, 0);
83 if (clen == -1) continue;
84 if (clen == -2 && !done) break;
87 space = iswspace(wchar);
89 } else space = isspace(toybuf[pos]);
93 if (!word) lengths[1]++;
98 if (pos != len) memmove(toybuf, toybuf+pos, len-pos);
103 show_lengths(lengths, name);
108 if (!toys.optflags) toys.optflags = FLAG_l|FLAG_w|FLAG_c;
109 loopfiles(toys.optargs, do_wc);
110 if (toys.optc>1) show_lengths(TT.totals, "total");