blob: e69f0d899f3ce1e749c5b54a78a2813ab5a5ec83 [file] [log] [blame]
Erik Andersen31638212000-01-15 22:28:50 +00001/*
2 * Mini wc implementation for busybox
3 *
4 * by Edward Betts <edward@debian.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include "internal.h"
23#include <stdio.h>
24
25static const char wc_usage[] = "wc [OPTION]... [FILE]...\n\n"
26"Print line, word, and byte counts for each FILE, and a total line if\n"
27"more than one FILE is specified. With no FILE, read standard input.\n"
28"\t-c\tprint the byte counts\n"
29"\t-l\tprint the newline counts\n"
30"\t-L\tprint the length of the longest line\n"
Erik Andersen31638212000-01-15 22:28:50 +000031"\t-w\tprint the word counts\n";
32
33static int total_lines, total_words, total_chars, max_length;
34static int print_lines, print_words, print_chars, print_length;
35
36void print_counts (int lines, int words, int chars, int length,
37 const char *name) {
38 char const *space = "";
39 if (print_lines) {
40 printf ("%7d", lines);
41 space = " ";
42 }
43 if (print_words) {
44 printf ("%s%7d", space, words);
45 space = " ";
46 }
47 if (print_chars) {
48 printf ("%s%7d", space, chars);
49 space = " ";
50 }
51 if (print_length)
52 printf ("%s%7d", space, length);
53 if (*name)
54 printf (" %s", name);
55 putchar ('\n');
56}
57
58static void wc_file(FILE *file, const char *name)
59{
60 int lines, words, chars, length;
61 int in_word = 0, linepos = 0;
62 int c;
63 lines = words = chars = length = 0;
64 while ((c = getc(file)) != EOF) {
65 chars++;
66 switch (c) {
67 case '\n':
68 lines++;
69 case '\r':
70 case '\f':
71 if (linepos > length)
72 length = linepos;
73 linepos = 0;
74 goto word_separator;
75 case '\t':
76 linepos += 8 - (linepos % 8);
77 goto word_separator;
78 case ' ':
79 linepos++;
80 case '\v':
81 word_separator:
82 if (in_word) {
83 in_word = 0;
84 words++;
85 }
86 break;
87 default:
88 linepos++;
89 in_word = 1;
90 break;
91 }
92 }
93 if (linepos > length)
94 length = linepos;
95 if (in_word)
96 words++;
97 print_counts (lines, words, chars, length, name);
98 total_lines += lines;
99 total_words += words;
100 total_chars += chars;
101 if (length > max_length)
102 max_length = length;
103 fclose(file);
104 fflush(stdout);
105}
106
107int wc_main(int argc, char **argv) {
108 FILE *file;
109 total_lines = total_words = total_chars = max_length = 0;
110 print_lines = print_words = print_chars = print_length = 0;
111
112 while (--argc && **(++argv) == '-') {
113 while (*++(*argv))
114 switch (**argv) {
115 case 'c':
116 print_chars = 1;
117 break;
118 case 'l':
119 print_lines = 1;
120 break;
121 case 'L':
122 print_length = 1;
123 break;
124 case 'w':
125 print_words = 1;
126 break;
127 default:
128 usage (wc_usage);
129 }
130 }
131
132 if (!print_lines && !print_words && !print_chars && !print_length)
133 print_lines = print_words = print_chars = 1;
134
135 if (argc == 0) {
136 wc_file(stdin, "");
137 exit(TRUE);
138 }
139 else if (argc == 1) {
140 file = fopen(*argv, "r");
141 if (file == NULL) {
142 perror(*argv);
143 exit(FALSE);
144 }
145 wc_file(file, *argv);
146 }
147 else {
148 while (argc-- > 0 && *argv != '\0' && strlen(*argv)) {
149 file = fopen(*argv, "r");
150 if (file == NULL) {
151 perror(*argv);
152 exit(FALSE);
153 }
154 wc_file(file, *argv);
155 argv++;
156 }
157 print_counts (total_lines, total_words, total_chars,
158 max_length, "total");
159 }
160 exit(TRUE);
161}