home *** CD-ROM | disk | FTP | other *** search
/ Borland Programmer's Resource / Borland_Programmers_Resource_CD_1995.iso / utils / source / wc / wc.c < prev    next >
C/C++ Source or Header  |  1995-05-18  |  8KB  |  325 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. #ifdef DF_POSIX     /* DF_DSC */
  35. #include <misc.h>
  36. #include <bsdlib.h>
  37. #endif
  38. #include <sys/cdefs.h>
  39.  
  40. #ifndef lint
  41. char copyright[] =
  42. "@(#) Copyright (c) 1980, 1987 Regents of the University of California.\n\
  43.  All rights reserved.\n";
  44. #endif /* not lint */
  45.  
  46. #ifndef lint
  47. static char sccsid[] = "@(#)wc.c    5.7 (Berkeley) 3/2/91";
  48. #endif /* not lint */
  49.  
  50. /* wc line, word and char count */
  51.  
  52. #ifdef DF_POSIX     /* DF_DSC */
  53. #else
  54. #include <sys/param.h>
  55. #endif
  56. #include <sys/stat.h>
  57. #ifdef _POSIX_SOURCE        /* DF_DSC */
  58. #include <fcntl.h>
  59. #include <stdlib.h>
  60. #include <unistd.h>
  61. #else
  62. #include <sys/file.h>
  63. #endif
  64. #include <stdio.h>
  65.  
  66. #define DEL    0177            /* del char */
  67. #define NL    012            /* newline char */
  68. #define SPACE    040            /* space char */
  69. #define TAB    011            /* tab char */
  70.  
  71. #if WIN_NT
  72. extern int globulate __P((int, int, char **));
  73. extern void deglobulate __P((void));
  74. extern int globulated_argc;
  75. extern char **globulated_argv;
  76. pid_t ppid;
  77. int globulation;
  78. #endif
  79.  
  80. void cnt __P((char *));
  81.  
  82. static long    tlinect, twordct, tcharct;
  83. static int    doline, doword, dochar;
  84.  
  85. int
  86. #if __STDC__
  87. main(int argc, char **argv)
  88. #else
  89. main(argc, argv)
  90.     int argc;
  91.     char **argv;
  92. #endif
  93. {
  94.     extern int optind;
  95.     register int ch;
  96.     int total;
  97.  
  98. #if WIN_NT
  99.     ppid = getppid();
  100.     if (ppid == (pid_t) 1) /* if parent is CMD.EXE */
  101.     {
  102.         globulation = globulate(1, argc, argv);
  103.         if (globulation == 0)
  104.         {
  105.             argc = globulated_argc;
  106.             argv = globulated_argv;
  107.         }
  108.     }
  109. #endif
  110.     /*
  111.      * wc is unusual in that its flags are on by default, so,
  112.      * if you don't get any arguments, you have to turn them
  113.      * all on.
  114.      */
  115.     if (argc > 1 && argv[1][0] == '-' && argv[1][1]) {
  116.         while ((ch = getopt(argc, argv, "lwc")) != EOF)
  117.             switch((char)ch) {
  118.             case 'l':
  119.                 doline = 1;
  120.                 break;
  121.             case 'w':
  122.                 doword = 1;
  123.                 break;
  124.             case 'c':
  125.                 dochar = 1;
  126.                 break;
  127.             case '?':
  128.             default:
  129.                 fputs("usage: wc [-lwc] [files]\n", stderr);
  130. #if WIN_NT
  131.                 if (ppid == (pid_t) 1 && globulation == 0)
  132.                     deglobulate();
  133. #endif
  134.                 exit(1);
  135.             }
  136.         argv += optind;
  137.         argc -= optind;
  138.     }
  139.     else {
  140.         ++argv;
  141.         --argc;
  142.         doline = doword = dochar = 1;
  143.     }
  144.  
  145.     total = 0;
  146.     if (!*argv) {
  147.         cnt((char *)NULL);
  148.         putchar('\n');
  149.     }
  150.     else do {
  151.         cnt(*argv);
  152.         printf(" %s\n", *argv);
  153.         ++total;
  154.     } while(*++argv);
  155.  
  156.     if (total > 1) {
  157.         if (doline)
  158.             printf(" %7ld", tlinect);
  159.         if (doword)
  160.             printf(" %7ld", twordct);
  161.         if (dochar)
  162.             printf(" %7ld", tcharct);
  163.         puts(" total");
  164.     }
  165.     fflush (stderr); 
  166.     fflush (stdout);
  167. #if WIN_NT
  168.     if (ppid == (pid_t) 1 && globulation == 0)
  169.         deglobulate();
  170. #endif
  171.     return 0;
  172. }
  173.  
  174. void
  175. #if __STDC__
  176. cnt(char *file)
  177. #else
  178. cnt(file)
  179.     char *file;
  180. #endif
  181. {
  182.     register u_char *C;
  183.     register short gotsp;
  184.     register int len;
  185.     register long linect, wordct, charct;
  186.     struct stat sbuf;
  187.     int fd;
  188.     u_char buf[MAXBSIZE];
  189.  
  190.     linect = wordct = charct = 0;
  191.     if (file) {
  192.         if ((fd = open(file, O_RDONLY, 0)) < 0) {
  193.             perror(file);
  194. #if WIN_NT
  195.             if (ppid == (pid_t) 1 && globulation == 0)
  196.                 deglobulate();
  197. #endif
  198.             exit(1);
  199.         }
  200.         if (!doword) {
  201.             /*
  202.              * line counting is split out because it's a lot
  203.              * faster to get lines than to get words, since
  204.              * the word count requires some logic.
  205.              */
  206.             if (doline) {
  207.                 while((len = read(fd, buf, MAXBSIZE)) != 0) {
  208.                     if (len == -1) {
  209.                         perror(file);
  210. #if WIN_NT
  211.                         if (ppid == (pid_t) 1 && globulation == 0)
  212.                             deglobulate();
  213. #endif
  214.                         exit(1);
  215.                     }
  216.                     charct += len;
  217.                     for (C = buf; len--; ++C)
  218.                         if (*C == '\n')
  219.                             ++linect;
  220.                 }
  221.                 tlinect += linect;
  222.                 printf(" %7ld", linect);
  223.                 if (dochar) {
  224.                     tcharct += charct;
  225.                     printf(" %7ld", charct);
  226.                 }
  227.                 close(fd);
  228.                 return;
  229.             }
  230.             /*
  231.              * if all we need is the number of characters and
  232.              * it's a directory or a regular or linked file, just
  233.              * stat the puppy.  We avoid testing for it not being
  234.              * a special device in case someone adds a new type
  235.              * of inode.
  236.              */
  237.             if (dochar) {
  238.                 if (fstat(fd, &sbuf)) {
  239.                     perror(file);
  240. #if WIN_NT
  241.                     if (ppid == (pid_t) 1 && globulation == 0)
  242.                         deglobulate();
  243. #endif
  244.                     exit(1);
  245.                 }
  246. #ifdef _POSIX_SOURCE
  247.                 if (sbuf.st_mode & (S_IFREG | S_IFDIR)) {
  248. #else
  249.                 if (sbuf.st_mode & (S_IFREG | S_IFLNK | S_IFDIR)) {
  250. #endif
  251.                     printf(" %7ld", sbuf.st_size);
  252.                     tcharct += sbuf.st_size;
  253.                     close(fd);
  254.                     return;
  255.                 }
  256.             }
  257.         }
  258.     }
  259.     else
  260.         fd = 0;
  261.     /* do it the hard way... */
  262.     for (gotsp = 1; (len = read(fd, buf, MAXBSIZE)) != 0;) {
  263.         if (len == -1) {
  264.             perror(file);
  265. #if WIN_NT
  266.             if (ppid == (pid_t) 1 && globulation == 0)
  267.                 deglobulate();
  268. #endif
  269.             exit(1);
  270.         }
  271.         charct += len;
  272.         for (C = buf; len--; ++C)
  273.             switch(*C) {
  274.                 case NL:
  275.                     ++linect;
  276.                 case TAB:
  277.                 case SPACE:
  278.                     gotsp = 1;
  279.                     continue;
  280.                 default:
  281. #ifdef notdef
  282.                     /*
  283.                      * This line of code implements the
  284.                      * original V7 wc algorithm, i.e.
  285.                      * a non-printing character doesn't
  286.                      * toggle the "word" count, so that
  287.                      * "  ^D^F  " counts as 6 spaces,
  288.                      * while "foo^D^Fbar" counts as 8
  289.                      * characters.
  290.                      *
  291.                      * test order is important -- gotsp
  292.                      * will normally be NO, so test it
  293.                      * first
  294.                      */
  295.                     if (gotsp && *C > SPACE && *C < DEL) {
  296. #endif
  297.                     /*
  298.                      * This line implements the manual
  299.                      * page, i.e. a word is a "maximal
  300.                      * string of characters delimited by
  301.                      * spaces, tabs or newlines."  Notice
  302.                      * nothing was said about a character
  303.                      * being printing or non-printing.
  304.                      */
  305.                     if (gotsp) {
  306.                         gotsp = 0;
  307.                         ++wordct;
  308.                     }
  309.             }
  310.     }
  311.     if (doline) {
  312.         tlinect += linect;
  313.         printf(" %7ld", linect);
  314.     }
  315.     if (doword) {
  316.         twordct += wordct;
  317.         printf(" %7ld", wordct);
  318.     }
  319.     if (dochar) {
  320.         tcharct += charct;
  321.         printf(" %7ld", charct);
  322.     }
  323.     close(fd);
  324. }
  325.