#include <u.h>
#include <libc.h>
#include <bio.h>
long count[1<<16];
Biobuf bout;
void usage(void);
void freq(int, char*);
long flag;
enum
{
Fdec = 1<<0,
Fhex = 1<<1,
Foct = 1<<2,
Fchar = 1<<3,
Frune = 1<<4,
};
void
main(int argc, char *argv[])
{
int f, i;
flag = 0;
Binit(&bout, 1, OWRITE);
ARGBEGIN{
case 'd':
flag |= Fdec;
break;
case 'x':
flag |= Fhex;
break;
case 'o':
flag |= Foct;
break;
case 'c':
flag |= Fchar;
break;
case 'r':
flag |= Frune;
break;
default:
usage();
}ARGEND
if((flag&(Fdec|Fhex|Foct|Fchar)) == 0)
flag |= Fdec | Fhex | Foct | Fchar;
if(argc < 1) {
freq(0, "-");
exits(0);
}
for(i=0; i<argc; i++) {
f = open(argv[i], 0);
if(f < 0) {
fprint(2, "open %s: %r\n", argv[i]);
continue;
}
freq(f, argv[i]);
close(f);
}
exits(0);
}
void
usage(void)
{
fprint(2, "usage: freq [-cdorx] [file ...]\n");
exits("usage");
}
void
freq(int f, char *s)
{
Biobuf bin;
long c, i;
memset(count, 0, sizeof(count));
Binit(&bin, f, OREAD);
if(flag & Frune) {
for(;;) {
c = Bgetrune(&bin);
if(c < 0)
break;
count[c]++;
}
} else {
for(;;) {
c = Bgetc(&bin);
if(c < 0)
break;
count[c]++;
}
}
Bterm(&bin);
if(c != Beof)
fprint(2, "freq: read error on %s\n", s);
for(i=0; i<nelem(count); i++) {
if(count[i] == 0)
continue;
if(flag & Fdec)
Bprint(&bout, "%3ld ", i);
if(flag & Foct)
Bprint(&bout, "%.3lo ", i);
if(flag & Fhex)
Bprint(&bout, "%.2lx ", i);
if(flag & Fchar) {
if(i <= 0x20 ||
i >= 0x7f && i < 0xa0 ||
i > 0xff && !(flag & Frune))
Bprint(&bout, "- ");
else
Bprint(&bout, "%C ", (int)i);
}
Bprint(&bout, "%8ld\n", count[i]);
}
Bflush(&bout);
}
|