xref: /plan9/sys/src/cmd/freq.c (revision 82726826a7b3d40fb66339b4b0e95b60314f98b9)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 
5 uvlong	count[Runemax+1];
6 Biobuf	bout;
7 
8 void	usage(void);
9 void	freq(int, char*);
10 long	flag;
11 enum
12 {
13 	Fdec	= 1<<0,
14 	Fhex	= 1<<1,
15 	Foct	= 1<<2,
16 	Fchar	= 1<<3,
17 	Frune	= 1<<4,
18 };
19 
20 void
main(int argc,char * argv[])21 main(int argc, char *argv[])
22 {
23 	int f, i;
24 
25 	flag = 0;
26 	Binit(&bout, 1, OWRITE);
27 	ARGBEGIN{
28 	case 'd':
29 		flag |= Fdec;
30 		break;
31 	case 'x':
32 		flag |= Fhex;
33 		break;
34 	case 'o':
35 		flag |= Foct;
36 		break;
37 	case 'c':
38 		flag |= Fchar;
39 		break;
40 	case 'r':
41 		flag |= Frune;
42 		break;
43 	default:
44 		usage();
45 	}ARGEND
46 	if((flag&(Fdec|Fhex|Foct|Fchar)) == 0)
47 		flag |= Fdec | Fhex | Foct | Fchar;
48 	if(argc < 1) {
49 		freq(0, "-");
50 		exits(0);
51 	}
52 	for(i=0; i<argc; i++) {
53 		f = open(argv[i], 0);
54 		if(f < 0) {
55 			fprint(2, "open %s: %r\n", argv[i]);
56 			continue;
57 		}
58 		freq(f, argv[i]);
59 		close(f);
60 	}
61 	exits(0);
62 }
63 
64 void
usage(void)65 usage(void)
66 {
67 	fprint(2, "usage: freq [-cdorx] [file ...]\n");
68 	exits("usage");
69 }
70 
71 void
freq(int f,char * s)72 freq(int f, char *s)
73 {
74 	Biobuf bin;
75 	long c, i;
76 
77 	memset(count, 0, sizeof(count));
78 	Binit(&bin, f, OREAD);
79 	if(flag & Frune) {
80 		for(;;) {
81 			c = Bgetrune(&bin);
82 			if(c < 0)
83 				break;
84 			count[c]++;
85 		}
86 	} else {
87 		for(;;) {
88 			c = Bgetc(&bin);
89 			if(c < 0)
90 				break;
91 			count[c]++;
92 		}
93 	}
94 	Bterm(&bin);
95 	if(c != Beof)
96 		fprint(2, "freq: read error on %s\n", s);
97 
98 	for(i=0; i<nelem(count); i++) {
99 		if(count[i] == 0)
100 			continue;
101 		if(flag & Fdec)
102 			Bprint(&bout, "%3ld ", i);
103 		if(flag & Foct)
104 			Bprint(&bout, "%.3lo ", i);
105 		if(flag & Fhex)
106 			Bprint(&bout, "%.2lx ", i);
107 		if(flag & Fchar) {
108 			if(i <= 0x20 ||
109 			   i >= 0x7f && i < 0xa0 ||
110 			   i > 0xff && !(flag & Frune))
111 				Bprint(&bout, "- ");
112 			else
113 				Bprint(&bout, "%C ", (int)i);
114 		}
115 		Bprint(&bout, "%8llud\n", count[i]);
116 	}
117 	Bflush(&bout);
118 }
119