|
|
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.