| #include <u.h> | 
 | #include <libc.h> | 
 | #include <bio.h> | 
 | #include "dict.h" | 
 |  | 
 | /* Possible tags */ | 
 | enum { | 
 | 	DF,		/* definition */ | 
 | 	DX,		/* definition/example */ | 
 | 	ET,		/* etymology */ | 
 | 	EX,		/* example */ | 
 | 	LA,		/* label */ | 
 | 	ME,		/* main entry */ | 
 | 	NU,		/* sense number */ | 
 | 	PR,		/* pronunciation */ | 
 | 	PS,		/* grammar part */ | 
 | 	XR,		/* cross reference */ | 
 | 	XX		/* cross reference (whole entry) */ | 
 | }; | 
 |  | 
 | /* Assoc tables must be sorted on first field */ | 
 |  | 
 | static Assoc tagtab[] = { | 
 | 	{"df",	DF}, | 
 | 	{"dx",	DX}, | 
 | 	{"et",	ET}, | 
 | 	{"ex",	EX}, | 
 | 	{"la",	LA}, | 
 | 	{"me",	ME}, | 
 | 	{"nu",	NU}, | 
 | 	{"pr",	PR}, | 
 | 	{"ps",	PS}, | 
 | 	{"xr",	XR}, | 
 | 	{"xx",	XX} | 
 | }; | 
 | static long	sget(char *, char *, char **, char **); | 
 | static void	soutpiece(char *, char *); | 
 |  | 
 | void | 
 | slangprintentry(Entry e, int cmd) | 
 | { | 
 | 	char *p, *pe, *vs, *ve; | 
 | 	long t; | 
 |  | 
 | 	p = e.start; | 
 | 	pe = e.end; | 
 | 	if(cmd == 'h') { | 
 | 		t = sget(p, pe, &vs, &ve); | 
 | 		if(t == ME) | 
 | 			soutpiece(vs, ve); | 
 | 		outnl(0); | 
 | 		return; | 
 | 	} | 
 | 	while(p < pe) { | 
 | 		switch(sget(p, pe, &vs, &ve)) { | 
 | 		case DF: | 
 | 			soutpiece(vs, ve); | 
 | 			outchars(".  "); | 
 | 			break; | 
 | 		case DX: | 
 | 			soutpiece(vs, ve); | 
 | 			outchars(".  "); | 
 | 			break; | 
 | 		case ET: | 
 | 			outchars("["); | 
 | 			soutpiece(vs, ve); | 
 | 			outchars("] "); | 
 | 			break; | 
 | 		case EX: | 
 | 			outchars("E.g., "); | 
 | 			soutpiece(vs, ve); | 
 | 			outchars(".  "); | 
 | 			break; | 
 | 		case LA: | 
 | 			outchars("("); | 
 | 			soutpiece(vs, ve); | 
 | 			outchars(") "); | 
 | 			break; | 
 | 		case ME: | 
 | 			outnl(0); | 
 | 			soutpiece(vs, ve); | 
 | 			outnl(0); | 
 | 			break; | 
 | 		case NU: | 
 | 			outnl(2); | 
 | 			soutpiece(vs, ve); | 
 | 			outchars(".  "); | 
 | 			break; | 
 | 		case PR: | 
 | 			outchars("["); | 
 | 			soutpiece(vs, ve); | 
 | 			outchars("] "); | 
 | 			break; | 
 | 		case PS: | 
 | 			outnl(1); | 
 | 			soutpiece(vs, ve); | 
 | 			outchars(". "); | 
 | 			break; | 
 | 		case XR: | 
 | 			outchars("See "); | 
 | 			soutpiece(vs, ve); | 
 | 			outchars(".  "); | 
 | 			break; | 
 | 		case XX: | 
 | 			outchars("See "); | 
 | 			soutpiece(vs, ve); | 
 | 			outchars(".  "); | 
 | 			break; | 
 | 		default: | 
 | 			ve = pe;	/* will end loop */ | 
 | 			break; | 
 | 		} | 
 | 		p = ve; | 
 | 	} | 
 | 	outnl(0); | 
 | } | 
 |  | 
 | long | 
 | slangnextoff(long fromoff) | 
 | { | 
 | 	long a; | 
 | 	char *p; | 
 |  | 
 | 	a = Bseek(bdict, fromoff, 0); | 
 | 	if(a < 0) | 
 | 		return -1; | 
 | 	for(;;) { | 
 | 		p = Brdline(bdict, '\n'); | 
 | 		if(!p) | 
 | 			break; | 
 | 		if(p[0] == 'm' && p[1] == 'e' && p[2] == ' ') | 
 | 			return (Boffset(bdict)-Blinelen(bdict)); | 
 | 	} | 
 | 	return -1; | 
 | } | 
 |  | 
 | void | 
 | slangprintkey(void) | 
 | { | 
 | 	Bprint(bout, "No key\n"); | 
 | } | 
 |  | 
 | /* | 
 |  * Starting from b, find next line beginning with a tag. | 
 |  * Don't go past e, but assume *e==0. | 
 |  * Return tag value, or -1 if no more tags before e. | 
 |  * Set pvb to beginning of value (after tag). | 
 |  * Set pve to point at newline that ends the value. | 
 |  */ | 
 | static long | 
 | sget(char *b, char *e, char **pvb, char **pve) | 
 | { | 
 | 	char *p; | 
 | 	char buf[3]; | 
 | 	long t, tans; | 
 |  | 
 | 	buf[2] = 0; | 
 | 	tans = -1; | 
 | 	for(p = b;;) { | 
 | 		if(p[2] == ' ') { | 
 | 			buf[0] = p[0]; | 
 | 			buf[1] = p[1]; | 
 | 			t = lookassoc(tagtab, asize(tagtab), buf); | 
 | 			if(t < 0) { | 
 | 				if(debug) | 
 | 					err("tag %s\n", buf); | 
 | 				p += 3; | 
 | 			} else { | 
 | 				if(tans < 0) { | 
 | 					p += 3; | 
 | 					tans = t; | 
 | 					*pvb = p; | 
 | 				} else { | 
 | 					*pve = p; | 
 | 					break; | 
 | 				} | 
 | 			} | 
 | 		} | 
 | 		p = strchr(p, '\n'); | 
 | 		if(!p || ++p >= e) { | 
 | 			if(tans >= 0) | 
 | 				*pve = e-1; | 
 | 			break; | 
 | 		} | 
 | 	} | 
 | 	return tans; | 
 | } | 
 |  | 
 | static void | 
 | soutpiece(char *b, char *e) | 
 | { | 
 | 	int c, lastc; | 
 |  | 
 | 	lastc = 0; | 
 | 	while(b < e) { | 
 | 		c = *b++; | 
 | 		if(c == '\n') | 
 | 			c = ' '; | 
 | 		if(!(c == ' ' && lastc == ' ') && c != '@') | 
 | 			outchar(c); | 
 | 		lastc = c; | 
 | 	} | 
 | } |