home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / wc / wc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-26  |  5.9 KB  |  247 lines

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