-
Notifications
You must be signed in to change notification settings - Fork 57
/
p-wc.cc
95 lines (84 loc) · 2.63 KB
/
p-wc.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include "u-lib.hh"
static int unparse_counts(char* buf, size_t bufsz, int mode,
const size_t* counts, const char* fname) {
const char* sep = strlen(fname) ? " " : "";
if (mode < 0) {
return snprintf(buf, bufsz, "%8zu %7zu %7zu%s%s\n",
counts[0], counts[1], counts[2], sep, fname);
} else if (*sep) {
return snprintf(buf, bufsz, "%8zu%s%s\n",
counts[mode], sep, fname);
} else {
return snprintf(buf, bufsz, "%zu\n", counts[mode]);
}
}
void process_main(int argc, char** argv) {
static char buf[4096];
int mode = -1;
int argno = 1;
if (argno < argc) {
if (strcmp(argv[argno], "-c") == 0) {
mode = 0;
++argno;
} else if (strcmp(argv[argno], "-w") == 0) {
mode = 1;
++argno;
} else if (strcmp(argv[argno], "-l") == 0) {
mode = 2;
++argno;
} else if (argv[argno][0] == '-' && argv[argno][1]) {
sys_write(2, "wc: bad argument\n", 17);
sys_exit(1);
}
}
size_t totals[3] = {0, 0, 0};
unsigned nfiles = 0;
while (argno < argc || nfiles == 0) {
int fd = 0;
bool newfd = false;
if (argno < argc && strcmp(argv[argno], "-") != 0) {
fd = sys_open(argv[argno], OF_READ);
if (fd < 0) {
dprintf(2, "%s: error %d\n", argv[argno], fd);
sys_exit(1);
}
newfd = true;
}
size_t counts[3] = {0, 0, 0};
bool inword = false;
while (true) {
ssize_t n = sys_read(fd, buf, sizeof(buf));
if (n == 0 || (n < 0 && n != E_AGAIN)) {
break;
}
for (ssize_t i = 0; i < n; ++i) {
++counts[0];
if (!inword && !isspace(buf[i])) {
++counts[1];
}
inword = !isspace(buf[i]);
if (buf[i] == '\n') {
++counts[2];
}
}
}
if (newfd) {
sys_close(fd);
}
int n = unparse_counts(buf, sizeof(buf), mode, counts,
argno < argc ? argv[argno] : "");
ssize_t w = sys_write(1, buf, n);
assert(w == n);
for (int i = 0; i < 3; ++i) {
totals[i] += counts[i];
}
++nfiles;
++argno;
}
if (nfiles > 1) {
int n = unparse_counts(buf, sizeof(buf), mode, totals, "total");
ssize_t w = sys_write(1, buf, n);
assert(w == n);
}
sys_exit(0);
}