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