remove BSD ifdefs
[unix-history] / usr / src / usr.bin / wc / wc.c
CommitLineData
f42904bc 1/*
2d5da4ef
KB
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 are permitted
5e8b0e60
KB
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
f42904bc
DF
16 */
17
18#ifndef lint
19char copyright[] =
2d5da4ef 20"@(#) Copyright (c) 1980, 1987 Regents of the University of California.\n\
f42904bc 21 All rights reserved.\n";
2d5da4ef 22#endif /* not lint */
f42904bc
DF
23
24#ifndef lint
e4e131e4 25static char sccsid[] = "@(#)wc.c 5.5 (Berkeley) %G%";
2d5da4ef 26#endif /* not lint */
f42904bc 27
93b63814 28/* wc line, word and char count */
66690d0f 29
93b63814
KB
30#include <sys/param.h>
31#include <sys/stat.h>
32#include <sys/file.h>
66690d0f 33#include <stdio.h>
66690d0f 34
93b63814 35#define DEL 0177 /* del char */
93b63814 36#define NL 012 /* newline char */
93b63814
KB
37#define SPACE 040 /* space char */
38#define TAB 011 /* tab char */
93b63814 39
2d5da4ef 40static long tlinect, twordct, tcharct;
e4e131e4 41static int doline, doword, dochar;
93b63814 42
e4e131e4 43main(argc, argv)
2d5da4ef
KB
44 int argc;
45 char **argv;
66690d0f 46{
2d5da4ef
KB
47 extern int optind;
48 register int ch;
e4e131e4 49 int total;
66690d0f 50
93b63814
KB
51 /*
52 * wc is unusual in that its flags are on by default, so,
53 * if you don't get any arguments, you have to turn them
54 * all on.
55 */
56 if (argc > 1 && argv[1][0] == '-' && argv[1][1]) {
e4e131e4 57 while ((ch = getopt(argc, argv, "lwc")) != EOF)
93b63814 58 switch((char)ch) {
2d5da4ef
KB
59 case 'l':
60 doline = 1;
61 break;
62 case 'w':
63 doword = 1;
64 break;
65 case 'c':
66 dochar = 1;
67 break;
68 case '?':
69 default:
e4e131e4 70 fputs("usage: wc [-lwc] [files]\n", stderr);
2d5da4ef 71 exit(1);
93b63814
KB
72 }
73 argv += optind;
74 argc -= optind;
75 }
76 else {
77 ++argv;
78 --argc;
2d5da4ef 79 doline = doword = dochar = 1;
93b63814
KB
80 }
81
e4e131e4
KB
82 total = 0;
83 if (!*argv) {
84 cnt((char *)NULL);
85 putchar('\n');
66690d0f 86 }
e4e131e4
KB
87 else do {
88 cnt(*argv);
89 printf(" %s\n", *argv);
90 ++total;
93b63814
KB
91 } while(*++argv);
92
e4e131e4
KB
93 if (total > 1) {
94 if (doline)
95 printf(" %7ld", tlinect);
96 if (doword)
97 printf(" %7ld", twordct);
98 if (dochar)
99 printf(" %7ld", tcharct);
100 puts(" total");
101 }
2d5da4ef 102 exit(0);
93b63814
KB
103}
104
105static
106cnt(file)
2d5da4ef 107 char *file;
93b63814 108{
2d5da4ef
KB
109 register u_char *C;
110 register short gotsp;
111 register int len;
e4e131e4 112 register long linect, wordct, charct;
2d5da4ef
KB
113 struct stat sbuf;
114 int fd;
115 u_char buf[MAXBSIZE];
93b63814
KB
116
117 linect = wordct = charct = 0;
118 if (file) {
2d5da4ef 119 if ((fd = open(file, O_RDONLY, 0)) < 0) {
93b63814 120 perror(file);
2d5da4ef 121 exit(1);
93b63814
KB
122 }
123 if (!doword) {
124 /*
125 * line counting is split out because it's a lot
126 * faster to get lines than to get words, since
127 * the word count requires some logic.
128 */
129 if (doline) {
2d5da4ef 130 while(len = read(fd, buf, MAXBSIZE)) {
93b63814
KB
131 if (len == -1) {
132 perror(file);
2d5da4ef 133 exit(1);
93b63814
KB
134 }
135 charct += len;
2d5da4ef 136 for (C = buf; len--; ++C)
93b63814
KB
137 if (*C == '\n')
138 ++linect;
139 }
140 tlinect += linect;
2d5da4ef 141 printf(" %7ld", linect);
93b63814
KB
142 if (dochar) {
143 tcharct += charct;
e4e131e4 144 printf(" %7ld", charct);
66690d0f 145 }
93b63814
KB
146 close(fd);
147 return;
66690d0f 148 }
93b63814
KB
149 /*
150 * if all we need is the number of characters and
151 * it's a directory or a regular or linked file, just
152 * stat the puppy. We avoid testing for it not being
153 * a special device in case someone adds a new type
154 * of inode.
155 */
156 if (dochar) {
2d5da4ef 157 if (fstat(fd, &sbuf)) {
93b63814 158 perror(file);
2d5da4ef 159 exit(1);
93b63814
KB
160 }
161 if (sbuf.st_mode & (S_IFREG | S_IFLNK | S_IFDIR)) {
2d5da4ef 162 printf(" %7ld", sbuf.st_size);
93b63814
KB
163 tcharct += sbuf.st_size;
164 close(fd);
165 return;
166 }
66690d0f 167 }
66690d0f 168 }
93b63814
KB
169 }
170 else
171 fd = 0;
172 /* do it the hard way... */
2d5da4ef 173 for (gotsp = 1; len = read(fd, buf, MAXBSIZE);) {
93b63814
KB
174 if (len == -1) {
175 perror(file);
2d5da4ef 176 exit(1);
93b63814
KB
177 }
178 charct += len;
2d5da4ef 179 for (C = buf; len--; ++C)
93b63814
KB
180 switch(*C) {
181 case NL:
182 ++linect;
183 case TAB:
184 case SPACE:
2d5da4ef 185 gotsp = 1;
93b63814
KB
186 continue;
187 default:
2d5da4ef 188#ifdef notdef
93b63814
KB
189 /*
190 * This line of code implements the
191 * original V7 wc algorithm, i.e.
192 * a non-printing character doesn't
193 * toggle the "word" count, so that
194 * " ^D^F " counts as 6 spaces,
195 * while "foo^D^Fbar" counts as 8
196 * characters.
197 *
198 * test order is important -- gotsp
199 * will normally be NO, so test it
200 * first
201 */
202 if (gotsp && *C > SPACE && *C < DEL) {
2d5da4ef 203#endif
93b63814
KB
204 /*
205 * This line implements the manual
206 * page, i.e. a word is a "maximal
207 * string of characters delimited by
208 * spaces, tabs or newlines." Notice
209 * nothing was said about a character
210 * being printing or non-printing.
211 */
212 if (gotsp) {
2d5da4ef 213 gotsp = 0;
93b63814
KB
214 ++wordct;
215 }
216 }
217 }
218 if (doline) {
66690d0f 219 tlinect += linect;
2d5da4ef 220 printf(" %7ld", linect);
93b63814
KB
221 }
222 if (doword) {
66690d0f 223 twordct += wordct;
2d5da4ef 224 printf(" %7ld", wordct);
66690d0f 225 }
93b63814
KB
226 if (dochar) {
227 tcharct += charct;
2d5da4ef 228 printf(" %7ld", charct);
66690d0f 229 }
93b63814 230 close(fd);
66690d0f 231}