blob: f416874226bccd66f045df03908ad937565ae318 [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>
Eric Andersened3ef502001-01-27 08:24:39 +000026#include <stdlib.h>
Erik Andersen31638212000-01-15 22:28:50 +000027
Erik Andersen31638212000-01-15 22:28:50 +000028static int total_lines, total_words, total_chars, max_length;
29static int print_lines, print_words, print_chars, print_length;
30
Erik Andersene49d5ec2000-02-08 19:58:47 +000031void print_counts(int lines, int words, int chars, int length,
32 const char *name)
33{
Erik Andersen31638212000-01-15 22:28:50 +000034 char const *space = "";
Erik Andersene49d5ec2000-02-08 19:58:47 +000035
Erik Andersen31638212000-01-15 22:28:50 +000036 if (print_lines) {
Erik Andersene49d5ec2000-02-08 19:58:47 +000037 printf("%7d", lines);
Erik Andersen31638212000-01-15 22:28:50 +000038 space = " ";
39 }
40 if (print_words) {
Erik Andersene49d5ec2000-02-08 19:58:47 +000041 printf("%s%7d", space, words);
Erik Andersen31638212000-01-15 22:28:50 +000042 space = " ";
43 }
44 if (print_chars) {
Erik Andersene49d5ec2000-02-08 19:58:47 +000045 printf("%s%7d", space, chars);
Erik Andersen31638212000-01-15 22:28:50 +000046 space = " ";
47 }
48 if (print_length)
Erik Andersene49d5ec2000-02-08 19:58:47 +000049 printf("%s%7d", space, length);
Erik Andersen31638212000-01-15 22:28:50 +000050 if (*name)
Erik Andersene49d5ec2000-02-08 19:58:47 +000051 printf(" %s", name);
52 putchar('\n');
Erik Andersen31638212000-01-15 22:28:50 +000053}
54
Erik Andersene49d5ec2000-02-08 19:58:47 +000055static void wc_file(FILE * file, const char *name)
Erik Andersen31638212000-01-15 22:28:50 +000056{
57 int lines, words, chars, length;
58 int in_word = 0, linepos = 0;
59 int c;
Erik Andersene49d5ec2000-02-08 19:58:47 +000060
Erik Andersen31638212000-01-15 22:28:50 +000061 lines = words = chars = length = 0;
62 while ((c = getc(file)) != EOF) {
63 chars++;
64 switch (c) {
Erik Andersene49d5ec2000-02-08 19:58:47 +000065 case '\n':
66 lines++;
67 case '\r':
68 case '\f':
69 if (linepos > length)
70 length = linepos;
71 linepos = 0;
72 goto word_separator;
73 case '\t':
74 linepos += 8 - (linepos % 8);
75 goto word_separator;
76 case ' ':
77 linepos++;
78 case '\v':
79 word_separator:
80 if (in_word) {
81 in_word = 0;
82 words++;
83 }
84 break;
85 default:
86 linepos++;
87 in_word = 1;
88 break;
Erik Andersen31638212000-01-15 22:28:50 +000089 }
90 }
91 if (linepos > length)
92 length = linepos;
93 if (in_word)
94 words++;
Erik Andersene49d5ec2000-02-08 19:58:47 +000095 print_counts(lines, words, chars, length, name);
Erik Andersen31638212000-01-15 22:28:50 +000096 total_lines += lines;
97 total_words += words;
98 total_chars += chars;
99 if (length > max_length)
100 max_length = length;
101 fclose(file);
102 fflush(stdout);
103}
104
Erik Andersene49d5ec2000-02-08 19:58:47 +0000105int wc_main(int argc, char **argv)
106{
Erik Andersen31638212000-01-15 22:28:50 +0000107 FILE *file;
Mark Whitley39505962000-07-20 00:08:10 +0000108 unsigned int num_files_counted = 0;
Eric Andersen7a86e612000-10-09 18:21:44 +0000109 int opt, status = EXIT_SUCCESS;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000110
Erik Andersen31638212000-01-15 22:28:50 +0000111 total_lines = total_words = total_chars = max_length = 0;
112 print_lines = print_words = print_chars = print_length = 0;
113
Mark Whitley39505962000-07-20 00:08:10 +0000114 while ((opt = getopt(argc, argv, "clLw")) > 0) {
115 switch (opt) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000116 case 'c':
117 print_chars = 1;
118 break;
119 case 'l':
120 print_lines = 1;
121 break;
122 case 'L':
123 print_length = 1;
124 break;
125 case 'w':
126 print_words = 1;
127 break;
128 default:
Eric Andersen67991cf2001-02-14 21:23:06 +0000129 show_usage();
Erik Andersen31638212000-01-15 22:28:50 +0000130 }
131 }
132
133 if (!print_lines && !print_words && !print_chars && !print_length)
134 print_lines = print_words = print_chars = 1;
135
Mark Whitley39505962000-07-20 00:08:10 +0000136 if (argv[optind] == NULL || strcmp(argv[optind], "-") == 0) {
Erik Andersen31638212000-01-15 22:28:50 +0000137 wc_file(stdin, "");
Matt Kraaibbaef662000-09-27 02:43:35 +0000138 return EXIT_SUCCESS;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000139 } else {
Mark Whitley39505962000-07-20 00:08:10 +0000140 while (optind < argc) {
Eric Andersen7a86e612000-10-09 18:21:44 +0000141 if ((file = wfopen(argv[optind], "r")) != NULL)
142 wc_file(file, argv[optind]);
143 else
144 status = EXIT_FAILURE;
Mark Whitley39505962000-07-20 00:08:10 +0000145 num_files_counted++;
146 optind++;
Erik Andersen31638212000-01-15 22:28:50 +0000147 }
Mark Whitley39505962000-07-20 00:08:10 +0000148 }
149
150 if (num_files_counted > 1)
Erik Andersene49d5ec2000-02-08 19:58:47 +0000151 print_counts(total_lines, total_words, total_chars,
152 max_length, "total");
Mark Whitley39505962000-07-20 00:08:10 +0000153
Eric Andersen7a86e612000-10-09 18:21:44 +0000154 return status;
Erik Andersen31638212000-01-15 22:28:50 +0000155}