henesyinit from p9f47575dc5 years agoHistory
297 lines · 5.2 KB · C
RawDownload
#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);}