sbase

suckless unix tools
git clone git://git.2f30.org/sbase
Log | Files | Refs | README | LICENSE

wc.c (1948B)


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