blob: e6f753435610fa68bcd92a622c82bd8fbab83f32 [file] [log] [blame]
Erik Andersene49d5ec2000-02-08 19:58:47 +00001/* vi: set sw=4 ts=4: */
Erik Andersen31638212000-01-15 22:28:50 +00002/*
3 * Mini wc implementation for busybox
4 *
Eric Andersen1b355eb2000-09-05 17:37:48 +00005 * Copyright (C) 2000 Edward Betts <edward@debian.org>
Erik Andersen31638212000-01-15 22:28:50 +00006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22
Eric Andersen3570a342000-09-25 21:45:58 +000023#include "busybox.h"
Erik Andersen31638212000-01-15 22:28:50 +000024#include <stdio.h>
Mark Whitley39505962000-07-20 00:08:10 +000025#include <getopt.h>
Erik Andersen31638212000-01-15 22:28:50 +000026
Erik Andersen31638212000-01-15 22:28:50 +000027static int total_lines, total_words, total_chars, max_length;
28static int print_lines, print_words, print_chars, print_length;
29
Erik Andersene49d5ec2000-02-08 19:58:47 +000030void print_counts(int lines, int words, int chars, int length,
31 const char *name)
32{
Erik Andersen31638212000-01-15 22:28:50 +000033 char const *space = "";
Erik Andersene49d5ec2000-02-08 19:58:47 +000034
Erik Andersen31638212000-01-15 22:28:50 +000035 if (print_lines) {
Erik Andersene49d5ec2000-02-08 19:58:47 +000036 printf("%7d", lines);
Erik Andersen31638212000-01-15 22:28:50 +000037 space = " ";
38 }
39 if (print_words) {
Erik Andersene49d5ec2000-02-08 19:58:47 +000040 printf("%s%7d", space, words);
Erik Andersen31638212000-01-15 22:28:50 +000041 space = " ";
42 }
43 if (print_chars) {
Erik Andersene49d5ec2000-02-08 19:58:47 +000044 printf("%s%7d", space, chars);
Erik Andersen31638212000-01-15 22:28:50 +000045 space = " ";
46 }
47 if (print_length)
Erik Andersene49d5ec2000-02-08 19:58:47 +000048 printf("%s%7d", space, length);
Erik Andersen31638212000-01-15 22:28:50 +000049 if (*name)
Erik Andersene49d5ec2000-02-08 19:58:47 +000050 printf(" %s", name);
51 putchar('\n');
Erik Andersen31638212000-01-15 22:28:50 +000052}
53
Erik Andersene49d5ec2000-02-08 19:58:47 +000054static void wc_file(FILE * file, const char *name)
Erik Andersen31638212000-01-15 22:28:50 +000055{
56 int lines, words, chars, length;
57 int in_word = 0, linepos = 0;
58 int c;
Erik Andersene49d5ec2000-02-08 19:58:47 +000059
Erik Andersen31638212000-01-15 22:28:50 +000060 lines = words = chars = length = 0;
61 while ((c = getc(file)) != EOF) {
62 chars++;
63 switch (c) {
Erik Andersene49d5ec2000-02-08 19:58:47 +000064 case '\n':
65 lines++;
66 case '\r':
67 case '\f':
68 if (linepos > length)
69 length = linepos;
70 linepos = 0;
71 goto word_separator;
72 case '\t':
73 linepos += 8 - (linepos % 8);
74 goto word_separator;
75 case ' ':
76 linepos++;
77 case '\v':
78 word_separator:
79 if (in_word) {
80 in_word = 0;
81 words++;
82 }
83 break;
84 default:
85 linepos++;
86 in_word = 1;
87 break;
Erik Andersen31638212000-01-15 22:28:50 +000088 }
89 }
90 if (linepos > length)
91 length = linepos;
92 if (in_word)
93 words++;
Erik Andersene49d5ec2000-02-08 19:58:47 +000094 print_counts(lines, words, chars, length, name);
Erik Andersen31638212000-01-15 22:28:50 +000095 total_lines += lines;
96 total_words += words;
97 total_chars += chars;
98 if (length > max_length)
99 max_length = length;
100 fclose(file);
101 fflush(stdout);
102}
103
Erik Andersene49d5ec2000-02-08 19:58:47 +0000104int wc_main(int argc, char **argv)
105{
Erik Andersen31638212000-01-15 22:28:50 +0000106 FILE *file;
Mark Whitley39505962000-07-20 00:08:10 +0000107 unsigned int num_files_counted = 0;
Eric Andersen7a86e612000-10-09 18:21:44 +0000108 int opt, status = EXIT_SUCCESS;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000109
Erik Andersen31638212000-01-15 22:28:50 +0000110 total_lines = total_words = total_chars = max_length = 0;
111 print_lines = print_words = print_chars = print_length = 0;
112
Mark Whitley39505962000-07-20 00:08:10 +0000113 while ((opt = getopt(argc, argv, "clLw")) > 0) {
114 switch (opt) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000115 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);
Erik Andersen31638212000-01-15 22:28:50 +0000129 }
130 }
131
132 if (!print_lines && !print_words && !print_chars && !print_length)
133 print_lines = print_words = print_chars = 1;
134
Mark Whitley39505962000-07-20 00:08:10 +0000135 if (argv[optind] == NULL || strcmp(argv[optind], "-") == 0) {
Erik Andersen31638212000-01-15 22:28:50 +0000136 wc_file(stdin, "");
Matt Kraaibbaef662000-09-27 02:43:35 +0000137 return EXIT_SUCCESS;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000138 } else {
Mark Whitley39505962000-07-20 00:08:10 +0000139 while (optind < argc) {
Eric Andersen7a86e612000-10-09 18:21:44 +0000140 if ((file = wfopen(argv[optind], "r")) != NULL)
141 wc_file(file, argv[optind]);
142 else
143 status = EXIT_FAILURE;
Mark Whitley39505962000-07-20 00:08:10 +0000144 num_files_counted++;
145 optind++;
Erik Andersen31638212000-01-15 22:28:50 +0000146 }
Mark Whitley39505962000-07-20 00:08:10 +0000147 }
148
149 if (num_files_counted > 1)
Erik Andersene49d5ec2000-02-08 19:58:47 +0000150 print_counts(total_lines, total_words, total_chars,
151 max_length, "total");
Mark Whitley39505962000-07-20 00:08:10 +0000152
Eric Andersen7a86e612000-10-09 18:21:44 +0000153 return status;
Erik Andersen31638212000-01-15 22:28:50 +0000154}