sbase

suckless unix tools
git clone git://git.suckless.org/sbase
Log | Files | Refs | README | 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 }