-
-
Notifications
You must be signed in to change notification settings - Fork 49
/
Copy pathwc.c
132 lines (115 loc) · 2.77 KB
/
wc.c
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/**
* @brief wc - count bytes, characters, words, lines...
*
* @copyright
* This file is part of ToaruOS and is released under the terms
* of the NCSA / University of Illinois License - see LICENSE.md
* Copyright (C) 2018 K. Lange
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include <errno.h>
#include <toaru/decodeutf8.h>
int main(int argc, char * argv[]) {
int show_lines = 0;
int show_words = 0;
int show_chars = 0;
int show_bytes = 0;
int opt;
while ((opt = getopt(argc,argv,"cmlw")) != -1) {
switch (opt) {
case 'c':
show_bytes = 1;
break;
case 'm':
show_chars = 1;
break;
case 'l':
show_lines = 1;
break;
case 'w':
show_words = 1;
break;
}
}
int retval = 0;
int total_lines = 0;
int total_chars = 0;
int total_words = 0;
int just_stdin = 0;
if (optind == argc) {
argv[optind] = "";
argc++;
just_stdin = 1;
}
for (int i = optind; i < argc; ++i) {
if (!*argv[i] && !just_stdin) {
fprintf(stderr, "%s: invalid zero-length file name\n", argv[0]);
retval = 1;
continue;
}
FILE * f = (!strcmp(argv[i], "-") || just_stdin) ? stdin : fopen(argv[i], "r");
if (!f) {
fprintf(stderr, "%s: %s: %s\n", argv[0], argv[i], strerror(errno));
retval = 1;
continue;
}
int lines = 0;
int chars = 0;
int words = 0;
int ch;
uint32_t state, c;
int last_was_whitespace = 0;
while (!feof(f)) {
ch = getc(f);
if (ch < 0) break;
if (show_chars) {
if (!decode(&state, &c, ch)) {
} else if (state == UTF8_REJECT) {
state = 0;
}
} else {
c = ch;
}
chars++;
if (c == '\n') {
last_was_whitespace = 1;
lines++;
words++;
} else if (c == ' ') {
if (last_was_whitespace) continue;
last_was_whitespace = 1;
words++;
} else {
last_was_whitespace = 0;
}
}
if (!last_was_whitespace && chars > 0) words++;
if (!show_words && !show_chars && !show_bytes && !show_lines) {
fprintf(stdout, "%d %d %d %s\n", lines, words, chars, argv[i]);
} else {
if (show_lines) fprintf(stdout, "%d ", lines);
if (show_words) fprintf(stdout, "%d ", words);
if (show_bytes|show_chars) fprintf(stdout, "%d ", chars);
fprintf(stdout, "%s\n", argv[i]);
}
total_lines += lines;
total_words += words;
total_chars += chars;
if (f != stdin) fclose(f);
if (just_stdin) return 0;
}
if (optind + 1 < argc) {
if (!show_words && !show_chars && !show_bytes && !show_lines) {
fprintf(stdout, "%d %d %d %s\n", total_lines, total_words, total_chars, "total");
} else {
if (show_lines) fprintf(stdout, "%d ", total_lines);
if (show_words) fprintf(stdout, "%d ", total_words);
if (show_bytes|show_chars) fprintf(stdout, "%d ", total_chars);
fprintf(stdout, "%s\n", "total");
}
}
return retval;
}