1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include "dict.h"
5 
6 /* Possible tags */
7 enum {
8 	DF,		/* definition */
9 	DX,		/* definition/example */
10 	ET,		/* etymology */
11 	EX,		/* example */
12 	LA,		/* label */
13 	ME,		/* main entry */
14 	NU,		/* sense number */
15 	PR,		/* pronunciation */
16 	PS,		/* grammar part */
17 	XR,		/* cross reference */
18 	XX		/* cross reference (whole entry) */
19 };
20 
21 /* Assoc tables must be sorted on first field */
22 
23 static Assoc tagtab[] = {
24 	{"df",	DF},
25 	{"dx",	DX},
26 	{"et",	ET},
27 	{"ex",	EX},
28 	{"la",	LA},
29 	{"me",	ME},
30 	{"nu",	NU},
31 	{"pr",	PR},
32 	{"ps",	PS},
33 	{"xr",	XR},
34 	{"xx",	XX}
35 };
36 static long	sget(char *, char *, char **, char **);
37 static void	soutpiece(char *, char *);
38 
39 void
slangprintentry(Entry e,int cmd)40 slangprintentry(Entry e, int cmd)
41 {
42 	char *p, *pe, *vs, *ve;
43 	long t;
44 
45 	p = e.start;
46 	pe = e.end;
47 	if(cmd == 'h') {
48 		t = sget(p, pe, &vs, &ve);
49 		if(t == ME)
50 			soutpiece(vs, ve);
51 		outnl(0);
52 		return;
53 	}
54 	while(p < pe) {
55 		switch(sget(p, pe, &vs, &ve)) {
56 		case DF:
57 			soutpiece(vs, ve);
58 			outchars(".  ");
59 			break;
60 		case DX:
61 			soutpiece(vs, ve);
62 			outchars(".  ");
63 			break;
64 		case ET:
65 			outchars("[");
66 			soutpiece(vs, ve);
67 			outchars("] ");
68 			break;
69 		case EX:
70 			outchars("E.g., ");
71 			soutpiece(vs, ve);
72 			outchars(".  ");
73 			break;
74 		case LA:
75 			outchars("(");
76 			soutpiece(vs, ve);
77 			outchars(") ");
78 			break;
79 		case ME:
80 			outnl(0);
81 			soutpiece(vs, ve);
82 			outnl(0);
83 			break;
84 		case NU:
85 			outnl(2);
86 			soutpiece(vs, ve);
87 			outchars(".  ");
88 			break;
89 		case PR:
90 			outchars("[");
91 			soutpiece(vs, ve);
92 			outchars("] ");
93 			break;
94 		case PS:
95 			outnl(1);
96 			soutpiece(vs, ve);
97 			outchars(". ");
98 			break;
99 		case XR:
100 			outchars("See ");
101 			soutpiece(vs, ve);
102 			outchars(".  ");
103 			break;
104 		case XX:
105 			outchars("See ");
106 			soutpiece(vs, ve);
107 			outchars(".  ");
108 			break;
109 		default:
110 			ve = pe;	/* will end loop */
111 			break;
112 		}
113 		p = ve;
114 	}
115 	outnl(0);
116 }
117 
118 long
slangnextoff(long fromoff)119 slangnextoff(long fromoff)
120 {
121 	long a;
122 	char *p;
123 
124 	a = Bseek(bdict, fromoff, 0);
125 	if(a < 0)
126 		return -1;
127 	for(;;) {
128 		p = Brdline(bdict, '\n');
129 		if(!p)
130 			break;
131 		if(p[0] == 'm' && p[1] == 'e' && p[2] == ' ')
132 			return (Boffset(bdict)-Blinelen(bdict));
133 	}
134 	return -1;
135 }
136 
137 void
slangprintkey(void)138 slangprintkey(void)
139 {
140 	Bprint(bout, "No key\n");
141 }
142 
143 /*
144  * Starting from b, find next line beginning with a tag.
145  * Don't go past e, but assume *e==0.
146  * Return tag value, or -1 if no more tags before e.
147  * Set pvb to beginning of value (after tag).
148  * Set pve to point at newline that ends the value.
149  */
150 static long
sget(char * b,char * e,char ** pvb,char ** pve)151 sget(char *b, char *e, char **pvb, char **pve)
152 {
153 	char *p;
154 	char buf[3];
155 	long t, tans;
156 
157 	buf[2] = 0;
158 	tans = -1;
159 	for(p = b;;) {
160 		if(p[2] == ' ') {
161 			buf[0] = p[0];
162 			buf[1] = p[1];
163 			t = lookassoc(tagtab, asize(tagtab), buf);
164 			if(t < 0) {
165 				if(debug)
166 					err("tag %s\n", buf);
167 				p += 3;
168 			} else {
169 				if(tans < 0) {
170 					p += 3;
171 					tans = t;
172 					*pvb = p;
173 				} else {
174 					*pve = p;
175 					break;
176 				}
177 			}
178 		}
179 		p = strchr(p, '\n');
180 		if(!p || ++p >= e) {
181 			if(tans >= 0)
182 				*pve = e-1;
183 			break;
184 		}
185 	}
186 	return tans;
187 }
188 
189 static void
soutpiece(char * b,char * e)190 soutpiece(char *b, char *e)
191 {
192 	int c, lastc;
193 
194 	lastc = 0;
195 	while(b < e) {
196 		c = *b++;
197 		if(c == '\n')
198 			c = ' ';
199 		if(!(c == ' ' && lastc == ' ') && c != '@')
200 			outchar(c);
201 		lastc = c;
202 	}
203 }
204