|
|
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
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.
16: */
17:
18: #ifndef lint
19: char copyright[] =
20: "@(#) Copyright (c) 1980, 1987 Regents of the University of California.\n\
21: All rights reserved.\n";
22: #endif /* not lint */
23:
24: #ifndef lint
25: static char sccsid[] = "@(#)wc.c 5.4 (Berkeley) 6/29/88";
26: #endif /* not lint */
27:
28: /* wc line, word and char count */
29:
30: #include <sys/param.h>
31: #include <sys/stat.h>
32: #include <sys/file.h>
33: #include <stdio.h>
34:
35: #define DEL 0177 /* del char */
36: #define NL 012 /* newline char */
37: #define SPACE 040 /* space char */
38: #define TAB 011 /* tab char */
39:
40: static long tlinect, twordct, tcharct;
41: static int doline, doword, dochar;
42:
43: main(argc,argv)
44: int argc;
45: char **argv;
46: {
47: extern int optind;
48: register int ch;
49:
50: /*
51: * wc is unusual in that its flags are on by default, so,
52: * if you don't get any arguments, you have to turn them
53: * all on.
54: */
55: if (argc > 1 && argv[1][0] == '-' && argv[1][1]) {
56: while ((ch = getopt(argc,argv,"lwc")) != EOF)
57: switch((char)ch) {
58: case 'l':
59: doline = 1;
60: break;
61: case 'w':
62: doword = 1;
63: break;
64: case 'c':
65: dochar = 1;
66: break;
67: case '?':
68: default:
69: fputs("usage: wc [-lwc] [files]\n",stderr);
70: exit(1);
71: }
72: argv += optind;
73: argc -= optind;
74: }
75: else {
76: ++argv;
77: --argc;
78: doline = doword = dochar = 1;
79: }
80:
81: /* should print "stdin" as the file name, here */
82: if (argc <= 1) {
83: if (!*argv || !strcmp(*argv, "-")) {
84: cnt((char *)NULL);
85: putchar('\n');
86: }
87: else {
88: cnt(*argv);
89: printf(" %s\n", *argv);
90: }
91: exit(0);
92: }
93:
94: /*
95: * cat allows "-" as stdin anywhere in the arg list,
96: * might as well here, too. Again, should use "stdin"
97: * as the file name.
98: */
99: do {
100: if (!strcmp(*argv, "-")) {
101: cnt((char *)NULL);
102: putchar('\n');
103: }
104: else {
105: cnt(*argv);
106: printf(" %s\n", *argv);
107: }
108: } while(*++argv);
109:
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: exit(0);
118: }
119:
120: static
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", sbuf.st_size);
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: if (fstat(fd, &sbuf)) {
173: perror(file);
174: exit(1);
175: }
176: if (sbuf.st_mode & (S_IFREG | S_IFLNK | S_IFDIR)) {
177: printf(" %7ld", sbuf.st_size);
178: tcharct += sbuf.st_size;
179: close(fd);
180: return;
181: }
182: }
183: }
184: }
185: else
186: fd = 0;
187: /* do it the hard way... */
188: for (gotsp = 1; len = read(fd, buf, MAXBSIZE);) {
189: if (len == -1) {
190: perror(file);
191: exit(1);
192: }
193: charct += len;
194: for (C = buf; len--; ++C)
195: switch(*C) {
196: case NL:
197: ++linect;
198: case TAB:
199: case SPACE:
200: gotsp = 1;
201: continue;
202: default:
203: #ifdef notdef
204: /*
205: * This line of code implements the
206: * original V7 wc algorithm, i.e.
207: * a non-printing character doesn't
208: * toggle the "word" count, so that
209: * " ^D^F " counts as 6 spaces,
210: * while "foo^D^Fbar" counts as 8
211: * characters.
212: *
213: * test order is important -- gotsp
214: * will normally be NO, so test it
215: * first
216: */
217: if (gotsp && *C > SPACE && *C < DEL) {
218: #endif
219: /*
220: * This line implements the manual
221: * page, i.e. a word is a "maximal
222: * string of characters delimited by
223: * spaces, tabs or newlines." Notice
224: * nothing was said about a character
225: * being printing or non-printing.
226: */
227: if (gotsp) {
228: gotsp = 0;
229: ++wordct;
230: }
231: }
232: }
233: if (doline) {
234: tlinect += linect;
235: printf(" %7ld", linect);
236: }
237: if (doword) {
238: twordct += wordct;
239: printf(" %7ld", wordct);
240: }
241: if (dochar) {
242: tcharct += charct;
243: printf(" %7ld", charct);
244: }
245: close(fd);
246: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.