xv6, line by line
user/wc.c

user/wc.c

C · 55 lines · annotated 100% · user program / library · upstream

About this file

wc (“word count”) counts the lines, words and bytes of each file named on its command line, or of standard input if there are none, and prints them in that order followed by the name: wc README prints 48 336 2441 README in a freshly built xv6, and echo hi there | wc prints 1 2 9 (the name is empty for standard input).

It reads input with the same loop as user/cat.c, but instead of writing each chunk out it scans it byte by byte. Lines are counted by newlines. Words are counted with a two-state machine: “inside a word” or “between words”; a word starts each time the state changes from “between” to “inside”.

Read before: user/cat.c. Read next: user/grep.c, which also processes its input line by line.

6char buf[512];
8void
9wc(int fd, char *name)
11 int i, n;
12 int l, w, c, inword;
14 l = w = c = 0;
15 inword = 0;
16 while ((n = read(fd, buf, sizeof(buf))) > 0) {
17 for (i = 0; i < n; i++) {
18 c++;
19 if (buf[i] == '\n')
20 l++;
21 if (strchr(" \r\t\n\v", buf[i]))
22 inword = 0;
23 else if (!inword) {
24 w++;
25 inword = 1;
26 }
27 }
28 }
29 if (n < 0) {
30 printf("wc: read error\n");
31 exit(1);
32 }
33 printf("%d %d %d %s\n", l, w, c, name);
36int
37main(int argc, char *argv[])
39 int fd, i;
41 if (argc <= 1) {
42 wc(0, "");
43 exit(0);
44 }
46 for (i = 1; i < argc; i++) {
47 if ((fd = open(argv[i], O_RDONLY)) < 0) {
48 printf("wc: cannot open %s\n", argv[i]);
49 exit(1);
50 }
51 wc(fd, argv[i]);
53 }
54 exit(0);