blob: daba277fd434ede1346ab23350e2151fa56d8fc3 [file] [log] [blame]
#include <u.h>
#include <libc.h>
#include <bio.h>
uvlong count[Runemax+1];
Biobuf bout;
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{
default:
fprint(2, "freq: unknown option %c\n", ARGC());
exits("usage");
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;
}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, "cannot open %s\n", argv[i]);
continue;
}
freq(f, argv[i]);
close(f);
}
exits(0);
}
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, "%8llud\n", count[i]);
}
Bflush(&bout);
}