#include <u.h>#include <libc.h>#include <bio.h> typedef struct PCB /* Control block controlling specification parse */{ char *base; /* start of specification */ char *current; /* current parse point */ long last; /* last Rune returned */ long final; /* final Rune in a span */} Pcb; uchar bits[] = { 1, 2, 4, 8, 16, 32, 64, 128 }; #define SETBIT(a, c) ((a)[(c)/8] |= bits[(c)&07])#define CLEARBIT(a,c) ((a)[(c)/8] &= ~bits[(c)&07])#define BITSET(a,c) ((a)[(c)/8] & bits[(c)&07]) #define MAXRUNE 0xFFFF uchar f[(MAXRUNE+1)/8];uchar t[(MAXRUNE+1)/8]; Biobuf fin;Biobuf fout; Pcb pfrom, pto; int cflag;int dflag;int sflag; void complement(void);void delete(void);void squeeze(void);void translit(void);void error(char*);long canon(Pcb*);char *getrune(char*, Rune*);void Pinit(Pcb*, char*);void Prewind(Pcb *p); voidmain(int argc, char **argv){ ARGBEGIN{ case 's': sflag++; break; case 'd': dflag++; break; case 'c': cflag++; break; default: error("bad option"); }ARGEND Binit(&fin, 0, OREAD); Binit(&fout, 1, OWRITE); if(argc>0) Pinit(&pfrom, argv[0]); if(argc>1) Pinit(&pto, argv[1]); if(argc>2) error("arg count"); if(dflag) { if (sflag && argc != 2) error("arg count"); delete(); } else { if (argc != 2) error("arg count"); if (cflag) complement(); else translit(); } exits(0);} voiddelete(void){ long c, last; if (cflag) { memset((char *) f, 0xff, sizeof f); while ((c = canon(&pfrom)) >= 0) CLEARBIT(f, c); } else { while ((c = canon(&pfrom)) >= 0) SETBIT(f, c); } if (sflag) { while ((c = canon(&pto)) >= 0) SETBIT(t, c); } last = 0x10000; while ((c = Bgetrune(&fin)) >= 0) { if(!BITSET(f, c) && (c != last || !BITSET(t,c))) { last = c; if (Bputrune(&fout, c) < 0) error("write error"); } }} voidcomplement(void){ Rune *p; int i; long from, to, lastc, high; lastc = 0; high = 0; while ((from = canon(&pfrom)) >= 0) { if (from > high) high = from; SETBIT(f, from); } while ((to = canon(&pto)) > 0) { if (to > high) high = to; SETBIT(t,to); } Prewind(&pto); if ((p = (Rune *) malloc((high+1)*sizeof(Rune))) == 0) error("can't allocate memory"); for (i = 0; i <= high; i++){ if (!BITSET(f,i)) { if ((to = canon(&pto)) < 0) to = lastc; else lastc = to; p[i] = to; } else p[i] = i; } if (sflag){ lastc = 0x10000; while ((from = Bgetrune(&fin)) >= 0) { if (from > high) from = to; else from = p[from]; if (from != lastc || !BITSET(t,from)) { lastc = from; if (Bputrune(&fout, from) < 0) error("write error"); } } } else { while ((from = Bgetrune(&fin)) >= 0){ if (from > high) from = to; else from = p[from]; if (Bputrune(&fout, from) < 0) error("write error"); } }} voidtranslit(void){ Rune *p; int i; long from, to, lastc, high; lastc = 0; high = 0; while ((from = canon(&pfrom)) >= 0) if (from > high) high = from; Prewind(&pfrom); if ((p = (Rune *) malloc((high+1)*sizeof(Rune))) == 0) error("can't allocate memory"); for (i = 0; i <= high; i++) p[i] = i; while ((from = canon(&pfrom)) >= 0) { if ((to = canon(&pto)) < 0) to = lastc; else lastc = to; if (BITSET(f,from) && p[from] != to) error("ambiguous translation"); SETBIT(f,from); p[from] = to; SETBIT(t,to); } while ((to = canon(&pto)) >= 0) { SETBIT(t,to); } if (sflag){ lastc = 0x10000; while ((from = Bgetrune(&fin)) >= 0) { if (from <= high) from = p[from]; if (from != lastc || !BITSET(t,from)) { lastc = from; if (Bputrune(&fout, from) < 0) error("write error"); } } } else { while ((from = Bgetrune(&fin)) >= 0){ if (from <= high) from = p[from]; if (Bputrune(&fout, from) < 0) error("write error"); } }} char *getrune(char *s, Rune *rp){ Rune r; char *save; int i, n; s += chartorune(rp, s); if((r = *rp) == '\\' && *s){ n = 0; if (*s == 'x') { s++; for (i = 0; i < 4; i++) { save = s; s += chartorune(&r, s); if ('0' <= r && r <= '9') n = 16*n + r - '0'; else if ('a' <= r && r <= 'f') n = 16*n + r - 'a' + 10; else if ('A' <= r && r <= 'F') n = 16*n + r - 'A' + 10; else { if (i == 0) *rp = 'x'; else *rp = n; return save; } } } else { for(i = 0; i < 3; i++) { save = s; s += chartorune(&r, s); if('0' <= r && r <= '7') n = 8*n + r - '0'; else { if (i == 0) { *rp = r; return s; } *rp = n; return save; } } if(n > 0377) error("char>0377"); } *rp = n; } return s;} longcanon(Pcb *p){ Rune r; if (p->final >= 0) { if (p->last < p->final) return ++p->last; p->final = -1; } if (*p->current == '\0') return -1; if(*p->current == '-' && p->last >= 0 && p->current[1]){ p->current = getrune(p->current+1, &r); if (r < p->last) error ("Invalid range specification"); if (r > p->last) { p->final = r; return ++p->last; } } p->current = getrune(p->current, &r); p->last = r; return p->last;} voidPinit(Pcb *p, char *cp){ p->current = p->base = cp; p->last = p->final = -1;}voidPrewind(Pcb *p){ p->current = p->base; p->last = p->final = -1;}voiderror(char *s){ fprint(2, "%s: %s\n", argv0, s); exits(s);}
#include <u.h>
#include <libc.h>
#include <bio.h>
typedef struct PCB /* Control block controlling specification parse */
{
char *base; /* start of specification */
char *current; /* current parse point */
long last; /* last Rune returned */
long final; /* final Rune in a span */
} Pcb;
uchar bits[] = { 1, 2, 4, 8, 16, 32, 64, 128 };
#define SETBIT(a, c) ((a)[(c)/8] |= bits[(c)&07])
#define CLEARBIT(a,c) ((a)[(c)/8] &= ~bits[(c)&07])
#define BITSET(a,c) ((a)[(c)/8] & bits[(c)&07])
#define MAXRUNE 0xFFFF
uchar f[(MAXRUNE+1)/8];
uchar t[(MAXRUNE+1)/8];
Biobuf fin;
Biobuf fout;
Pcb pfrom, pto;
int cflag;
int dflag;
int sflag;
void complement(void);
void delete(void);
void squeeze(void);
void translit(void);
void error(char*);
long canon(Pcb*);
char *getrune(char*, Rune*);
void Pinit(Pcb*, char*);
void Prewind(Pcb *p);
void
main(int argc, char **argv)
{
ARGBEGIN{
case 's': sflag++; break;
case 'd': dflag++; break;
case 'c': cflag++; break;
default: error("bad option");
}ARGEND
Binit(&fin, 0, OREAD);
Binit(&fout, 1, OWRITE);
if(argc>0)
Pinit(&pfrom, argv[0]);
if(argc>1)
Pinit(&pto, argv[1]);
if(argc>2)
error("arg count");
if(dflag) {
if (sflag && argc != 2)
error("arg count");
delete();
} else {
if (argc != 2)
error("arg count");
if (cflag)
complement();
else translit();
}
exits(0);
}
void
delete(void)
{
long c, last;
if (cflag) {
memset((char *) f, 0xff, sizeof f);
while ((c = canon(&pfrom)) >= 0)
CLEARBIT(f, c);
} else {
while ((c = canon(&pfrom)) >= 0)
SETBIT(f, c);
}
if (sflag) {
while ((c = canon(&pto)) >= 0)
SETBIT(t, c);
}
last = 0x10000;
while ((c = Bgetrune(&fin)) >= 0) {
if(!BITSET(f, c) && (c != last || !BITSET(t,c))) {
last = c;
if (Bputrune(&fout, c) < 0)
error("write error");
}
}
}
void
complement(void)
{
Rune *p;
int i;
long from, to, lastc, high;
lastc = 0;
high = 0;
while ((from = canon(&pfrom)) >= 0) {
if (from > high) high = from;
SETBIT(f, from);
}
while ((to = canon(&pto)) > 0) {
if (to > high) high = to;
SETBIT(t,to);
}
Prewind(&pto);
if ((p = (Rune *) malloc((high+1)*sizeof(Rune))) == 0)
error("can't allocate memory");
for (i = 0; i <= high; i++){
if (!BITSET(f,i)) {
if ((to = canon(&pto)) < 0)
to = lastc;
else lastc = to;
p[i] = to;
}
else p[i] = i;
}
if (sflag){
lastc = 0x10000;
while ((from = Bgetrune(&fin)) >= 0) {
if (from > high) from = to;
else from = p[from];
if (from != lastc || !BITSET(t,from)) {
lastc = from;
if (Bputrune(&fout, from) < 0)
error("write error");
}
}
} else {
while ((from = Bgetrune(&fin)) >= 0){
if (from > high) from = to;
else from = p[from];
if (Bputrune(&fout, from) < 0)
error("write error");
}
}
}
void
translit(void)
{
Rune *p;
int i;
long from, to, lastc, high;
lastc = 0;
high = 0;
while ((from = canon(&pfrom)) >= 0)
if (from > high) high = from;
Prewind(&pfrom);
if ((p = (Rune *) malloc((high+1)*sizeof(Rune))) == 0)
error("can't allocate memory");
for (i = 0; i <= high; i++)
p[i] = i;
while ((from = canon(&pfrom)) >= 0) {
if ((to = canon(&pto)) < 0)
to = lastc;
else lastc = to;
if (BITSET(f,from) && p[from] != to)
error("ambiguous translation");
SETBIT(f,from);
p[from] = to;
SETBIT(t,to);
}
while ((to = canon(&pto)) >= 0) {
SETBIT(t,to);
}
if (sflag){
lastc = 0x10000;
while ((from = Bgetrune(&fin)) >= 0) {
if (from <= high) from = p[from];
if (from != lastc || !BITSET(t,from)) {
lastc = from;
if (Bputrune(&fout, from) < 0)
error("write error");
}
}
} else {
while ((from = Bgetrune(&fin)) >= 0){
if (from <= high) from = p[from];
if (Bputrune(&fout, from) < 0)
error("write error");
}
}
}
char *
getrune(char *s, Rune *rp)
{
Rune r;
char *save;
int i, n;
s += chartorune(rp, s);
if((r = *rp) == '\\' && *s){
n = 0;
if (*s == 'x') {
s++;
for (i = 0; i < 4; i++) {
save = s;
s += chartorune(&r, s);
if ('0' <= r && r <= '9')
n = 16*n + r - '0';
else if ('a' <= r && r <= 'f')
n = 16*n + r - 'a' + 10;
else if ('A' <= r && r <= 'F')
n = 16*n + r - 'A' + 10;
else {
if (i == 0)
*rp = 'x';
else *rp = n;
return save;
}
}
} else {
for(i = 0; i < 3; i++) {
save = s;
s += chartorune(&r, s);
if('0' <= r && r <= '7')
n = 8*n + r - '0';
else {
if (i == 0)
{
*rp = r;
return s;
}
*rp = n;
return save;
}
}
if(n > 0377)
error("char>0377");
}
*rp = n;
}
return s;
}
long
canon(Pcb *p)
{
Rune r;
if (p->final >= 0) {
if (p->last < p->final)
return ++p->last;
p->final = -1;
}
if (*p->current == '\0')
return -1;
if(*p->current == '-' && p->last >= 0 && p->current[1]){
p->current = getrune(p->current+1, &r);
if (r < p->last)
error ("Invalid range specification");
if (r > p->last) {
p->final = r;
return ++p->last;
}
}
p->current = getrune(p->current, &r);
p->last = r;
return p->last;
}
void
Pinit(Pcb *p, char *cp)
{
p->current = p->base = cp;
p->last = p->final = -1;
}
void
Prewind(Pcb *p)
{
p->current = p->base;
p->last = p->final = -1;
}
void
error(char *s)
{
fprint(2, "%s: %s\n", argv0, s);
exits(s);
}