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