blob: 695e7e7d4e4b765b1954d5ecb5d9ea11f1128a10 [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
Erik Andersen31638212000-01-15 22:28:50 +000023#include <stdio.h>
Mark Whitley39505962000-07-20 00:08:10 +000024#include <getopt.h>
Eric Anderseneba8ed72001-03-09 14:36:42 +000025#include <string.h>
Eric Andersened3ef502001-01-27 08:24:39 +000026#include <stdlib.h>
Eric Andersencbe31da2001-02-20 06:14:08 +000027#include "busybox.h"
Erik Andersen31638212000-01-15 22:28:50 +000028
Erik Andersen31638212000-01-15 22:28:50 +000029static int total_lines, total_words, total_chars, max_length;
30static int print_lines, print_words, print_chars, print_length;
31
Eric Andersen3e6ff902001-03-09 21:24:12 +000032static void print_counts(int lines, int words, int chars, int length,
33 const char *name)
Erik Andersene49d5ec2000-02-08 19:58:47 +000034{
Erik Andersen31638212000-01-15 22:28:50 +000035 char const *space = "";
Erik Andersene49d5ec2000-02-08 19:58:47 +000036
Erik Andersen31638212000-01-15 22:28:50 +000037 if (print_lines) {
Erik Andersene49d5ec2000-02-08 19:58:47 +000038 printf("%7d", lines);
Erik Andersen31638212000-01-15 22:28:50 +000039 space = " ";
40 }
41 if (print_words) {
Erik Andersene49d5ec2000-02-08 19:58:47 +000042 printf("%s%7d", space, words);
Erik Andersen31638212000-01-15 22:28:50 +000043 space = " ";
44 }
45 if (print_chars) {
Erik Andersene49d5ec2000-02-08 19:58:47 +000046 printf("%s%7d", space, chars);
Erik Andersen31638212000-01-15 22:28:50 +000047 space = " ";
48 }
49 if (print_length)
Erik Andersene49d5ec2000-02-08 19:58:47 +000050 printf("%s%7d", space, length);
Erik Andersen31638212000-01-15 22:28:50 +000051 if (*name)
Erik Andersene49d5ec2000-02-08 19:58:47 +000052 printf(" %s", name);
53 putchar('\n');
Erik Andersen31638212000-01-15 22:28:50 +000054}
55
Erik Andersene49d5ec2000-02-08 19:58:47 +000056static void wc_file(FILE * file, const char *name)
Erik Andersen31638212000-01-15 22:28:50 +000057{
58 int lines, words, chars, length;
59 int in_word = 0, linepos = 0;
60 int c;
Erik Andersene49d5ec2000-02-08 19:58:47 +000061
Erik Andersen31638212000-01-15 22:28:50 +000062 lines = words = chars = length = 0;
63 while ((c = getc(file)) != EOF) {
64 chars++;
65 switch (c) {
Erik Andersene49d5ec2000-02-08 19:58:47 +000066 case '\n':
67 lines++;
68 case '\r':
69 case '\f':
70 if (linepos > length)
71 length = linepos;
72 linepos = 0;
73 goto word_separator;
74 case '\t':
75 linepos += 8 - (linepos % 8);
76 goto word_separator;
77 case ' ':
78 linepos++;
79 case '\v':
80 word_separator:
81 if (in_word) {
82 in_word = 0;
83 words++;
84 }
85 break;
86 default:
87 linepos++;
88 in_word = 1;
89 break;
Erik Andersen31638212000-01-15 22:28:50 +000090 }
91 }
92 if (linepos > length)
93 length = linepos;
94 if (in_word)
95 words++;
Erik Andersene49d5ec2000-02-08 19:58:47 +000096 print_counts(lines, words, chars, length, name);
Erik Andersen31638212000-01-15 22:28:50 +000097 total_lines += lines;
98 total_words += words;
99 total_chars += chars;
100 if (length > max_length)
101 max_length = length;
102 fclose(file);
103 fflush(stdout);
104}
105
Erik Andersene49d5ec2000-02-08 19:58:47 +0000106int wc_main(int argc, char **argv)
107{
Erik Andersen31638212000-01-15 22:28:50 +0000108 FILE *file;
Mark Whitley39505962000-07-20 00:08:10 +0000109 unsigned int num_files_counted = 0;
Eric Andersen7a86e612000-10-09 18:21:44 +0000110 int opt, status = EXIT_SUCCESS;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000111
Erik Andersen31638212000-01-15 22:28:50 +0000112 total_lines = total_words = total_chars = max_length = 0;
113 print_lines = print_words = print_chars = print_length = 0;
114
Mark Whitley39505962000-07-20 00:08:10 +0000115 while ((opt = getopt(argc, argv, "clLw")) > 0) {
116 switch (opt) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000117 case 'c':
118 print_chars = 1;
119 break;
120 case 'l':
121 print_lines = 1;
122 break;
123 case 'L':
124 print_length = 1;
125 break;
126 case 'w':
127 print_words = 1;
128 break;
129 default:
Eric Andersen67991cf2001-02-14 21:23:06 +0000130 show_usage();
Erik Andersen31638212000-01-15 22:28:50 +0000131 }
132 }
133
134 if (!print_lines && !print_words && !print_chars && !print_length)
135 print_lines = print_words = print_chars = 1;
136
Mark Whitley39505962000-07-20 00:08:10 +0000137 if (argv[optind] == NULL || strcmp(argv[optind], "-") == 0) {
Erik Andersen31638212000-01-15 22:28:50 +0000138 wc_file(stdin, "");
Matt Kraaibbaef662000-09-27 02:43:35 +0000139 return EXIT_SUCCESS;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000140 } else {
Mark Whitley39505962000-07-20 00:08:10 +0000141 while (optind < argc) {
Eric Andersen7a86e612000-10-09 18:21:44 +0000142 if ((file = wfopen(argv[optind], "r")) != NULL)
143 wc_file(file, argv[optind]);
144 else
145 status = EXIT_FAILURE;
Mark Whitley39505962000-07-20 00:08:10 +0000146 num_files_counted++;
147 optind++;
Erik Andersen31638212000-01-15 22:28:50 +0000148 }
Mark Whitley39505962000-07-20 00:08:10 +0000149 }
150
151 if (num_files_counted > 1)
Erik Andersene49d5ec2000-02-08 19:58:47 +0000152 print_counts(total_lines, total_words, total_chars,
153 max_length, "total");
Mark Whitley39505962000-07-20 00:08:10 +0000154
Eric Andersen7a86e612000-10-09 18:21:44 +0000155 return status;
Erik Andersen31638212000-01-15 22:28:50 +0000156}