| #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); |
| } |