wc.c revision 1.1.1.1 1 /*
2 * Copyright (c) 1980, 1987 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #ifndef lint
35 char copyright[] =
36 "@(#) Copyright (c) 1980, 1987 Regents of the University of California.\n\
37 All rights reserved.\n";
38 #endif /* not lint */
39
40 #ifndef lint
41 static char sccsid[] = "@(#)wc.c 5.7 (Berkeley) 3/2/91";
42 #endif /* not lint */
43
44 /* wc line, word and char count */
45
46 #include <sys/param.h>
47 #include <sys/stat.h>
48 #include <sys/file.h>
49 #include <stdio.h>
50
51 #define DEL 0177 /* del char */
52 #define NL 012 /* newline char */
53 #define SPACE 040 /* space char */
54 #define TAB 011 /* tab char */
55
56 static long tlinect, twordct, tcharct;
57 static int doline, doword, dochar;
58
59 main(argc, argv)
60 int argc;
61 char **argv;
62 {
63 extern int optind;
64 register int ch;
65 int total;
66
67 /*
68 * wc is unusual in that its flags are on by default, so,
69 * if you don't get any arguments, you have to turn them
70 * all on.
71 */
72 if (argc > 1 && argv[1][0] == '-' && argv[1][1]) {
73 while ((ch = getopt(argc, argv, "lwc")) != EOF)
74 switch((char)ch) {
75 case 'l':
76 doline = 1;
77 break;
78 case 'w':
79 doword = 1;
80 break;
81 case 'c':
82 dochar = 1;
83 break;
84 case '?':
85 default:
86 fputs("usage: wc [-lwc] [files]\n", stderr);
87 exit(1);
88 }
89 argv += optind;
90 argc -= optind;
91 }
92 else {
93 ++argv;
94 --argc;
95 doline = doword = dochar = 1;
96 }
97
98 total = 0;
99 if (!*argv) {
100 cnt((char *)NULL);
101 putchar('\n');
102 }
103 else do {
104 cnt(*argv);
105 printf(" %s\n", *argv);
106 ++total;
107 } while(*++argv);
108
109 if (total > 1) {
110 if (doline)
111 printf(" %7ld", tlinect);
112 if (doword)
113 printf(" %7ld", twordct);
114 if (dochar)
115 printf(" %7ld", tcharct);
116 puts(" total");
117 }
118 exit(0);
119 }
120
121 cnt(file)
122 char *file;
123 {
124 register u_char *C;
125 register short gotsp;
126 register int len;
127 register long linect, wordct, charct;
128 struct stat sbuf;
129 int fd;
130 u_char buf[MAXBSIZE];
131
132 linect = wordct = charct = 0;
133 if (file) {
134 if ((fd = open(file, O_RDONLY, 0)) < 0) {
135 perror(file);
136 exit(1);
137 }
138 if (!doword) {
139 /*
140 * line counting is split out because it's a lot
141 * faster to get lines than to get words, since
142 * the word count requires some logic.
143 */
144 if (doline) {
145 while(len = read(fd, buf, MAXBSIZE)) {
146 if (len == -1) {
147 perror(file);
148 exit(1);
149 }
150 charct += len;
151 for (C = buf; len--; ++C)
152 if (*C == '\n')
153 ++linect;
154 }
155 tlinect += linect;
156 printf(" %7ld", linect);
157 if (dochar) {
158 tcharct += charct;
159 printf(" %7ld", charct);
160 }
161 close(fd);
162 return;
163 }
164 /*
165 * if all we need is the number of characters and
166 * it's a directory or a regular or linked file, just
167 * stat the puppy. We avoid testing for it not being
168 * a special device in case someone adds a new type
169 * of inode.
170 */
171 if (dochar) {
172 int ifmt;
173
174 if (fstat(fd, &sbuf)) {
175 perror(file);
176 exit(1);
177 }
178
179 ifmt = sbuf.st_mode & S_IFMT;
180 if (ifmt == S_IFREG || ifmt == S_IFLNK
181 || ifmt == S_IFDIR) {
182 printf(" %7ld", sbuf.st_size);
183 tcharct += sbuf.st_size;
184 close(fd);
185 return;
186 }
187 }
188 }
189 }
190 else
191 fd = 0;
192 /* do it the hard way... */
193 for (gotsp = 1; len = read(fd, buf, MAXBSIZE);) {
194 if (len == -1) {
195 perror(file);
196 exit(1);
197 }
198 charct += len;
199 for (C = buf; len--; ++C)
200 switch(*C) {
201 case NL:
202 ++linect;
203 case TAB:
204 case SPACE:
205 gotsp = 1;
206 continue;
207 default:
208 #ifdef notdef
209 /*
210 * This line of code implements the
211 * original V7 wc algorithm, i.e.
212 * a non-printing character doesn't
213 * toggle the "word" count, so that
214 * " ^D^F " counts as 6 spaces,
215 * while "foo^D^Fbar" counts as 8
216 * characters.
217 *
218 * test order is important -- gotsp
219 * will normally be NO, so test it
220 * first
221 */
222 if (gotsp && *C > SPACE && *C < DEL) {
223 #endif
224 /*
225 * This line implements the manual
226 * page, i.e. a word is a "maximal
227 * string of characters delimited by
228 * spaces, tabs or newlines." Notice
229 * nothing was said about a character
230 * being printing or non-printing.
231 */
232 if (gotsp) {
233 gotsp = 0;
234 ++wordct;
235 }
236 }
237 }
238 if (doline) {
239 tlinect += linect;
240 printf(" %7ld", linect);
241 }
242 if (doword) {
243 twordct += wordct;
244 printf(" %7ld", wordct);
245 }
246 if (dochar) {
247 tcharct += charct;
248 printf(" %7ld", charct);
249 }
250 close(fd);
251 }
252