wc.c - sbase - suckless unix tools
 (HTM) git clone git://git.suckless.org/sbase
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       wc.c (1853B)
       ---
            1 /* See LICENSE file for copyright and license details. */
            2 #include <string.h>
            3 
            4 #include "utf.h"
            5 #include "util.h"
            6 
            7 static int    lflag = 0;
            8 static int    wflag = 0;
            9 static char   cmode = 0;
           10 static size_t tc = 0, tl = 0, tw = 0;
           11 
           12 static void
           13 output(const char *str, size_t nc, size_t nl, size_t nw)
           14 {
           15         int first = 1;
           16 
           17         if (lflag) {
           18                 first = 0;
           19                 printf("%zu", nl);
           20         }
           21         if (wflag) {
           22                 if (!first)
           23                         putchar(' ');
           24                 first = 0;
           25                 printf("%zu", nw);
           26         }
           27         if (cmode) {
           28                 if (!first)
           29                         putchar(' ');
           30                 printf("%zu", nc);
           31         }
           32         if (str)
           33                 printf(" %s", str);
           34         putchar('\n');
           35 }
           36 
           37 static void
           38 wc(FILE *fp, const char *str)
           39 {
           40         int word = 0, rlen;
           41         Rune c;
           42         size_t nc = 0, nl = 0, nw = 0;
           43 
           44         while ((rlen = efgetrune(&c, fp, str))) {
           45                 nc += (cmode == 'c') ? rlen : (c != Runeerror);
           46                 if (c == '\n')
           47                         nl++;
           48                 if (!isspacerune(c))
           49                         word = 1;
           50                 else if (word) {
           51                         word = 0;
           52                         nw++;
           53                 }
           54         }
           55         if (word)
           56                 nw++;
           57         tc += nc;
           58         tl += nl;
           59         tw += nw;
           60         output(str, nc, nl, nw);
           61 }
           62 
           63 static void
           64 usage(void)
           65 {
           66         eprintf("usage: %s [-c | -m] [-lw] [file ...]\n", argv0);
           67 }
           68 
           69 int
           70 main(int argc, char *argv[])
           71 {
           72         FILE *fp;
           73         int many;
           74         int ret = 0;
           75 
           76         ARGBEGIN {
           77         case 'c':
           78                 cmode = 'c';
           79                 break;
           80         case 'm':
           81                 cmode = 'm';
           82                 break;
           83         case 'l':
           84                 lflag = 1;
           85                 break;
           86         case 'w':
           87                 wflag = 1;
           88                 break;
           89         default:
           90                 usage();
           91         } ARGEND
           92 
           93         if (!lflag && !wflag && !cmode) {
           94                 cmode = 'c';
           95                 lflag = 1;
           96                 wflag = 1;
           97         }
           98 
           99         if (!argc) {
          100                 wc(stdin, NULL);
          101         } else {
          102                 for (many = (argc > 1); *argv; argc--, argv++) {
          103                         if (!strcmp(*argv, "-")) {
          104                                 *argv = "<stdin>";
          105                                 fp = stdin;
          106                         } else if (!(fp = fopen(*argv, "r"))) {
          107                                 weprintf("fopen %s:", *argv);
          108                                 ret = 1;
          109                                 continue;
          110                         }
          111                         wc(fp, *argv);
          112                         if (fp != stdin && fshut(fp, *argv))
          113                                 ret = 1;
          114                 }
          115                 if (many)
          116                         output("total", tc, tl, tw);
          117         }
          118 
          119         ret |= fshut(stdin, "<stdin>") | fshut(stdout, "<stdout>");
          120 
          121         return ret;
          122 }