Update to NetBSD version --- makes it POSIX.2 compliant, although
authorJ.T. Conklin <jtc@FreeBSD.org>
Thu, 4 Nov 1993 19:41:29 +0000 (19:41 +0000)
committerJ.T. Conklin <jtc@FreeBSD.org>
Thu, 4 Nov 1993 19:41:29 +0000 (19:41 +0000)
multibyte character support isn't in yet.

usr.bin/wc/wc.1
usr.bin/wc/wc.c

index 56c592a..17cf574 100644 (file)
@@ -32,7 +32,8 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\"     @(#)wc.1       6.4 (Berkeley) 6/27/91
+.\"     from: @(#)wc.1 6.4 (Berkeley) 6/27/91
+.\"    $Id: wc.1,v 1.4 1993/08/19 17:16:49 jtc Exp $
 .\"
 .Dd June 27, 1991
 .Dt WC 1
 .\"
 .Dd June 27, 1991
 .Dt WC 1
@@ -42,7 +43,8 @@
 .Nd Word, line, and byte count.
 .Sh SYNOPSIS
 .Nm wc
 .Nd Word, line, and byte count.
 .Sh SYNOPSIS
 .Nm wc
-.Op Fl clw
+.Op Fl c | Fl m
+.Op Fl lw
 .Op Ar file ...
 .Sh DESCRIPTION
 The
 .Op Ar file ...
 .Sh DESCRIPTION
 The
@@ -66,6 +68,9 @@ is written to the standard output.
 .It Fl l
 The number of lines in each input file
 is written to the standard output.
 .It Fl l
 The number of lines in each input file
 is written to the standard output.
+.It Fl m
+The number of characters in each input file
+is written to the standard output.
 .It Fl w
 The number of words in each input file
 is written to the standard output.
 .It Fl w
 The number of words in each input file
 is written to the standard output.
@@ -101,8 +106,6 @@ lines        words  bytes   file_name
 .Pp
 The counts for lines, words and bytes are integers separated
 by spaces.
 .Pp
 The counts for lines, words and bytes are integers separated
 by spaces.
-The ordering of the display of the number of lines, words,
-and/or bytes is the order in which the options were specified.
 .Pp
 The
 .Nm wc
 .Pp
 The
 .Nm wc
@@ -110,5 +113,5 @@ utility exits 0 on success, and >0 if an error occurs.
 .Sh STANDARDS
 The
 .Nm wc
 .Sh STANDARDS
 The
 .Nm wc
-function conforms to
-.St -p1003.2 .
+utility conforms to
+.St -p1003.2-92 .
index 65df315..91c8b90 100644 (file)
@@ -38,86 +38,88 @@ char copyright[] =
 #endif /* not lint */
 
 #ifndef lint
 #endif /* not lint */
 
 #ifndef lint
-static char sccsid[] = "@(#)wc.c       5.7 (Berkeley) 3/2/91";
+/*static char sccsid[] = "from: @(#)wc.c       5.7 (Berkeley) 3/2/91";*/
+static char rcsid[] = "$Id: wc.c,v 1.8 1993/11/04 05:43:30 jtc Exp $";
 #endif /* not lint */
 
 /* wc line, word and char count */
 
 #endif /* not lint */
 
 /* wc line, word and char count */
 
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+#include <ctype.h>
+#include <errno.h>
 #include <sys/param.h>
 #include <sys/stat.h>
 #include <sys/file.h>
 #include <sys/param.h>
 #include <sys/stat.h>
 #include <sys/file.h>
-#include <stdio.h>
-
-#define DEL    0177                    /* del char */
-#define NL     012                     /* newline char */
-#define SPACE  040                     /* space char */
-#define TAB    011                     /* tab char */
+#include <unistd.h>
+#include <err.h>
 
 
+static void    print_counts();
+static void    cnt();
 static long    tlinect, twordct, tcharct;
 static int     doline, doword, dochar;
 static long    tlinect, twordct, tcharct;
 static int     doline, doword, dochar;
+static int     rval = 0;
 
 
+int
 main(argc, argv)
        int argc;
        char **argv;
 {
        extern int optind;
        register int ch;
 main(argc, argv)
        int argc;
        char **argv;
 {
        extern int optind;
        register int ch;
-       int total;
+
+       setlocale(LC_ALL, "");
+
+       while ((ch = getopt(argc, argv, "lwcm")) != -1)
+               switch((char)ch) {
+               case 'l':
+                       doline = 1;
+                       break;
+               case 'w':
+                       doword = 1;
+                       break;
+               case 'c':
+               case 'm':
+                       dochar = 1;
+                       break;
+               case '?':
+               default:
+                       fprintf(stderr, "usage: wc [-c | -m] [-lw] [file ...]\n");
+                       exit(1);
+               }
+       argv += optind;
+       argc -= optind;
 
        /*
         * wc is unusual in that its flags are on by default, so,
         * if you don't get any arguments, you have to turn them
         * all on.
         */
 
        /*
         * wc is unusual in that its flags are on by default, so,
         * if you don't get any arguments, you have to turn them
         * all on.
         */
-       if (argc > 1 && argv[1][0] == '-' && argv[1][1]) {
-               while ((ch = getopt(argc, argv, "lwc")) != EOF)
-                       switch((char)ch) {
-                       case 'l':
-                               doline = 1;
-                               break;
-                       case 'w':
-                               doword = 1;
-                               break;
-                       case 'c':
-                               dochar = 1;
-                               break;
-                       case '?':
-                       default:
-                               fputs("usage: wc [-lwc] [files]\n", stderr);
-                               exit(1);
-                       }
-               argv += optind;
-               argc -= optind;
-       }
-       else {
-               ++argv;
-               --argc;
+       if (!doline && !doword && !dochar) {
                doline = doword = dochar = 1;
        }
 
                doline = doword = dochar = 1;
        }
 
-       total = 0;
        if (!*argv) {
                cnt((char *)NULL);
        if (!*argv) {
                cnt((char *)NULL);
-               putchar('\n');
-       }
-       else do {
-               cnt(*argv);
-               printf(" %s\n", *argv);
-               ++total;
-       } while(*++argv);
-
-       if (total > 1) {
-               if (doline)
-                       printf(" %7ld", tlinect);
-               if (doword)
-                       printf(" %7ld", twordct);
-               if (dochar)
-                       printf(" %7ld", tcharct);
-               puts(" total");
+       } else {
+               int dototal = (argc > 1);
+
+               do {
+                       cnt(*argv);
+               } while(*++argv);
+
+               if (dototal) {
+                       print_counts (tlinect, twordct, tcharct, "total"); 
+               }
        }
        }
-       exit(0);
+
+       exit(rval);
 }
 
 }
 
+
+static void
 cnt(file)
        char *file;
 {
 cnt(file)
        char *file;
 {
@@ -132,120 +134,118 @@ cnt(file)
        linect = wordct = charct = 0;
        if (file) {
                if ((fd = open(file, O_RDONLY, 0)) < 0) {
        linect = wordct = charct = 0;
        if (file) {
                if ((fd = open(file, O_RDONLY, 0)) < 0) {
-                       perror(file);
-                       exit(1);
+                       warn ("%s", file);
+                       rval = 1;
+                       return;
                }
                }
-               if (!doword) {
-                       /*
-                        * line counting is split out because it's a lot
-                        * faster to get lines than to get words, since
-                        * the word count requires some logic.
-                        */
-                       if (doline) {
-                               while(len = read(fd, buf, MAXBSIZE)) {
-                                       if (len == -1) {
-                                               perror(file);
-                                               exit(1);
-                                       }
-                                       charct += len;
-                                       for (C = buf; len--; ++C)
-                                               if (*C == '\n')
-                                                       ++linect;
-                               }
-                               tlinect += linect;
-                               printf(" %7ld", linect);
-                               if (dochar) {
-                                       tcharct += charct;
-                                       printf(" %7ld", charct);
-                               }
-                               close(fd);
-                               return;
+       } else  {
+               fd = STDIN_FILENO;
+       }
+       
+       if (!doword) {
+               /*
+                * line counting is split out because it's a lot
+                * faster to get lines than to get words, since
+                * the word count requires some logic.
+                */
+               if (doline) {
+                       while((len = read(fd, buf, MAXBSIZE)) > 0) {
+                               charct += len;
+                               for (C = buf; len--; ++C)
+                                       if (*C == '\n')
+                                               ++linect;
                        }
                        }
-                       /*
-                        * if all we need is the number of characters and
-                        * it's a directory or a regular or linked file, just
-                        * stat the puppy.  We avoid testing for it not being
-                        * a special device in case someone adds a new type
-                        * of inode.
-                        */
-                       if (dochar) {
-                               int ifmt;
-
-                               if (fstat(fd, &sbuf)) {
-                                       perror(file);
-                                       exit(1);
-                               }
+                       if (len == -1) {
+                               warn ("%s", file);
+                               rval = 1;
+                       }
+               }
 
 
+               /*
+                * if all we need is the number of characters and
+                * it's a directory or a regular or linked file, just
+                * stat the puppy.  We avoid testing for it not being
+                * a special device in case someone adds a new type
+                * of inode.
+                */
+               else if (dochar) {
+                       int ifmt;
+
+                       if (fstat(fd, &sbuf)) {
+                               warn ("%s", file);
+                               rval = 1;
+                       } else {
                                ifmt = sbuf.st_mode & S_IFMT;
                                if (ifmt == S_IFREG || ifmt == S_IFLNK
                                        || ifmt == S_IFDIR) {
                                ifmt = sbuf.st_mode & S_IFMT;
                                if (ifmt == S_IFREG || ifmt == S_IFLNK
                                        || ifmt == S_IFDIR) {
-                                       printf(" %7ld", sbuf.st_size);
-                                       tcharct += sbuf.st_size;
-                                       close(fd);
-                                       return;
+                                       charct = sbuf.st_size;
                                }
                        }
                }
        }
        else
                                }
                        }
                }
        }
        else
-               fd = 0;
-       /* do it the hard way... */
-       for (gotsp = 1; len = read(fd, buf, MAXBSIZE);) {
-               if (len == -1) {
-                       perror(file);
-                       exit(1);
-               }
-               charct += len;
-               for (C = buf; len--; ++C)
-                       switch(*C) {
-                               case NL:
-                                       ++linect;
-                               case TAB:
-                               case SPACE:
+       {
+               /* do it the hard way... */
+               gotsp = 1;
+               while ((len = read(fd, buf, MAXBSIZE)) > 0) {
+                       charct += len;
+                       for (C = buf; len--; ++C) {
+                               if (isspace (*C)) {
                                        gotsp = 1;
                                        gotsp = 1;
-                                       continue;
-                               default:
-#ifdef notdef
-                                       /*
-                                        * This line of code implements the
-                                        * original V7 wc algorithm, i.e.
-                                        * a non-printing character doesn't
-                                        * toggle the "word" count, so that
-                                        * "  ^D^F  " counts as 6 spaces,
-                                        * while "foo^D^Fbar" counts as 8
-                                        * characters.
-                                        *
-                                        * test order is important -- gotsp
-                                        * will normally be NO, so test it
-                                        * first
-                                        */
-                                       if (gotsp && *C > SPACE && *C < DEL) {
-#endif
+                                       if (*C == '\n') {
+                                               ++linect;
+                                       }
+                               } else {
                                        /*
                                        /*
-                                        * This line implements the manual
-                                        * page, i.e. a word is a "maximal
+                                        * This line implements the POSIX
+                                        * spec, i.e. a word is a "maximal
                                         * string of characters delimited by
                                         * string of characters delimited by
-                                        * spaces, tabs or newlines."  Notice
-                                        * nothing was said about a character
-                                        * being printing or non-printing.
+                                        * whitespace."  Notice nothing was
+                                        * said about a character being
+                                        * printing or non-printing.
                                         */
                                        if (gotsp) {
                                                gotsp = 0;
                                                ++wordct;
                                        }
                                         */
                                        if (gotsp) {
                                                gotsp = 0;
                                                ++wordct;
                                        }
+                               }
                        }
                        }
+               }
+               if (len == -1) {
+                       warn ("%s", file);
+                       rval = 1;
+               }
        }
        }
-       if (doline) {
-               tlinect += linect;
-               printf(" %7ld", linect);
-       }
-       if (doword) {
-               twordct += wordct;
-               printf(" %7ld", wordct);
-       }
-       if (dochar) {
-               tcharct += charct;
-               printf(" %7ld", charct);
+
+       print_counts (linect, wordct, charct, file ? file : "");
+
+       /* don't bother checkint doline, doword, or dochar --- speeds
+           up the common case */
+       tlinect += linect;
+       twordct += wordct;
+       tcharct += charct;
+
+       if (close(fd)) {
+               warn ("%s", file);
+               rval = 1;
        }
        }
-       close(fd);
+}
+
+
+void
+print_counts (lines, words, chars, name)
+       long lines;
+       long words;
+       long chars;
+       char *name;
+{
+
+       if (doline)
+               printf(" %7ld", lines);
+       if (doword)
+               printf(" %7ld", words);
+       if (dochar)
+               printf(" %7ld", chars);
+
+       printf (" %s\n", name);
 }
 }