xref: /minix/minix/commands/cawf/string.c (revision 433d6423)
1 /*
2  *	string.c - string support functions for cawf(1)
3  */
4 
5 /*
6  *	Copyright (c) 1991 Purdue University Research Foundation,
7  *	West Lafayette, Indiana 47907.  All rights reserved.
8  *
9  *	Written by Victor A. Abell <abe@mace.cc.purdue.edu>,  Purdue
10  *	University Computing Center.  Not derived from licensed software;
11  *	derived from awf(1) by Henry Spencer of the University of Toronto.
12  *
13  *	Permission is granted to anyone to use this software for any
14  *	purpose on any computer system, and to alter it and redistribute
15  *	it freely, subject to the following restrictions:
16  *
17  *	1. The author is not responsible for any consequences of use of
18  *	   this software, even if they arise from flaws in it.
19  *
20  *	2. The origin of this software must not be misrepresented, either
21  *	   by explicit claim or by omission.  Credits must appear in the
22  *	   documentation.
23  *
24  *	3. Altered versions must be plainly marked as such, and must not
25  *	   be misrepresented as being the original software.  Credits must
26  *	   appear in the documentation.
27  *
28  *	4. This notice may not be removed or altered.
29  */
30 
31 #include "cawf.h"
32 #include <ctype.h>
33 
34 static void Setroman();
35 
36 
37 /*
38  * Asmname(s, c) - assemble name
39  */
40 
41 Asmname(s, c)
42 	unsigned char *s;		/* pointer to name */
43 	unsigned char *c;		/* code destination (c[3]) */
44 {
45 
46 	c[1] = c[2] = '\0';
47 	while (*s && *s == ' ')
48 		s++;
49 	if ((c[0] = *s) == '\0')
50 		return(0);
51 	return(((c[1] = s[1]) == '\0') ? 1 : 2);
52 }
53 
54 
55 /*
56  * Delstr(sx) - delete string
57  */
58 
59 void
60 Delstr(sx)
61 	int sx;				/* string index */
62 {
63 	char buf[MAXLINE];		/* message buffer */
64 
65 	if (sx >= Nstr) {
66 		(void) sprintf(buf, " bad Delstr(%d) index", sx);
67 		Error(FATAL, LINE, buf, NULL);
68 	}
69 	Free(&Str[sx].str);
70 	while (sx < (Nstr - 1)) {
71 		Str[sx] = Str[sx + 1];
72 		sx++;
73 	}
74 	Nstr--;
75 }
76 
77 
78 /*
79  * Endword() - end a word
80  */
81 
82 void
83 Endword()
84 {
85 	if (Fontstat != 'R')
86 		Setroman();
87 	Word[Wordx] = '\0';
88 }
89 
90 
91 /*
92  * Findchar(nm, l, s, e) - find special character definition and
93  *			   optionally enter it
94  */
95 
96 Findchar(nm, l, s, e)
97 	unsigned char *nm;		/* character name */
98 	int l;				/* effective length */
99 	unsigned char *s;		/* value string */
100 	int e;				/* 0 = find, don't enter
101 					 * 1 = don't find, enter */
102 {
103 	int cmp, hi, low, mid;
104 	unsigned char c[3];
105 
106 	c[0] = nm[0];
107 	c[1] = (nm[1] == ' ' || nm[1] == '\t') ? '\0' : nm[1];
108 	c[2] = '\0';
109 	low = mid = 0;
110 	hi = Nsch - 1;
111 	while (low <= hi) {
112 		mid = (low + hi) / 2;
113 		if ((cmp = strncmp((char *)c, (char *)Schar[mid].nm, 2)) < 0)
114 			hi = mid - 1;
115 		else if (cmp > 0)
116 			low = mid + 1;
117 		else {
118 			if ( ! e)
119 				return(mid);
120 			Free(&Schar[mid].str);
121 			goto new_char;
122 		}
123 	}
124 	if ( ! e)
125 		return(-1);
126 	if (Nsch >= MAXSCH)
127 		Error(FATAL, LINE, " at character table limit", NULL);
128 	if (Nsch) {
129 		if (cmp > 0)
130 			mid++;
131 		for (hi = Nsch - 1; hi >= mid; hi--)
132 			Schar[hi+1] = Schar[hi];
133 	}
134 	Nsch++;
135 	Schar[mid].nm[0] = c[0];
136 	Schar[mid].nm[1] = c[1];
137 
138 new_char:
139 
140 	Schar[mid].str = Newstr(s);
141 	Schar[mid].len = l;
142 	return(mid);
143 }
144 
145 
146 /*
147  * Findhy(s, l, e) - find and optionally enter hyphen
148  */
149 
150 Findhy(s, l, e)
151 	unsigned char *s;		/* value string */
152 	int l;				/* equivalent length */
153 	int e;				/* 0 = find, don't enter
154 					 * 1 = enter, don't find */
155 {
156 	int i;
157 
158 	for (i = 0; i < Nhy; i++) {
159 		if (Font[0] == Hychar[i].font)
160 			break;
161 	}
162 	if (i >= Nhy) {
163 		if ( ! e)
164 			return(-1);
165 		if (Nhy >= MAXHYCH)
166 			Error(FATAL, LINE, " at hyphen limit for font ",
167 				(char *)Font);
168 		Hychar[i].font = Font[0];
169 		Nhy++;
170 	} else {
171 		if ( ! e)
172 			return(i);
173 		Error(WARN, LINE, " duplicate hyphen for font ", (char *)Font);
174 		Free(&Hychar[i].str);
175 	}
176 	Hychar[i].str = Newstr(s);
177 	Hychar[i].len = l;
178 	return(i);
179 }
180 
181 
182 /*
183  * Findstr(nm, s, e) - find and  optionally enter string in Str[]
184  */
185 
186 unsigned char *
187 Findstr(nm, s, e)
188 	unsigned char *nm;		/* 2 character string name */
189 	unsigned char *s;		/* string value */
190 	int e;				/* 0 = find, don't enter
191 					 * 1 = enter, don't find */
192 {
193 	unsigned char c[3];		/* character buffer */
194 	int cmp, hi, low, mid;		/* binary search controls */
195 	int i;				/* temporary indexes */
196 	unsigned char *s1, *s2;		/* temporary string pointers */
197 
198 	c[0] = nm[0];
199 	c[1] = (nm[1] == ' ' || nm[1] == '\t') ? '\0' : nm[1];
200 	c[2] = '\0';
201 	low = mid = 0;
202 	hi = Nstr - 1;
203 	Sx = -1;
204 	while (low <= hi) {
205 		mid = (low + hi) / 2;
206 		if ((cmp = strncmp((char *)c, (char *)Str[mid].nm, 2)) < 0)
207 			hi = mid - 1;
208 		else if (cmp > 0)
209 			low = mid + 1;
210 		else {
211 			Sx = mid;
212 			if ( ! e)
213 				return(Str[mid].str);
214 			Free(&Str[mid].str);
215 			goto new_string;
216 		}
217 	}
218 	if ( ! e)
219 		return((unsigned char *)"");
220 	if (Nstr >= MAXSTR)
221 		Error(FATAL, LINE, " out of space for string ", (char *)c);
222 	if (Nstr) {
223 		if (cmp > 0)
224 			mid++;
225 		for (hi = Nstr - 1; hi >= mid; hi--)
226 			Str[hi+1] = Str[hi];
227 	}
228 	Nstr++;
229 	Sx = mid;
230 	Str[mid].nm[0] = c[0];
231 	Str[mid].nm[1] = c[1];
232 
233 new_string:
234 
235 	if (s == NULL)
236 		return (Str[mid].str = Newstr((unsigned char *)""));
237 	i = (*s == '"') ? 1 : 0;
238 	s1 = Str[mid].str = Newstr(s + i);
239 	if (i) {
240 		s2 = s1 + strlen((char *)s1);
241 		if (s2 > s1 && *(s2-1) == '"')
242 			*(s2-1) = '\0';
243 	}
244 	return(s1);
245 }
246 
247 
248 /*
249  * Setroman() - set Roman font
250  */
251 
252 static void
253 Setroman()
254 {
255 	int i;
256 
257 	if ((Wordx + Fstr.rl) >= MAXLINE)
258 		Error(WARN, LINE, " word too long", NULL);
259 	else {
260 		if (Fstr.r) {
261 			for (i = 0; i < Fstr.rl; i++) {
262 				Word[Wordx++] = Fstr.r[i];
263 			}
264 	    	}
265 		Fontstat = 'R';
266 	}
267 }
268 
269 
270 /*
271  * Str2word(s, len) - copy len characters from string to Word[]
272  */
273 
274 Str2word(s, len)
275 	unsigned char *s;
276 	int len;
277 {
278 	int i;
279 
280 	for (; len > 0; len--, s++) {
281 		switch (Font[0]) {
282 		case 'B':
283 		case 'C':
284 			if (Fontctl == 0) {
285 				if ((Wordx + 5) >= MAXLINE) {
286 word_too_long:
287 					Error(WARN, LINE, " word too long",
288 						NULL);
289 					return(1);
290 				}
291 				Word[Wordx++] = Trtbl[(int)*s];
292 				Word[Wordx++] = '\b';
293 				Word[Wordx++] = Trtbl[(int)*s];
294 				Word[Wordx++] = '\b';
295 				Word[Wordx++] = Trtbl[(int)*s];
296 				break;
297 			}
298 			if (Fontstat != Font[0]) {
299 				if (Fontstat != 'R')
300 					Setroman();
301 				if ((Wordx + Fstr.bl) >= MAXLINE)
302 					goto word_too_long;
303 				if (Fstr.b) {
304 					for (i = 0; i < Fstr.bl; i++) {
305 						Word[Wordx++] = Fstr.b[i];
306 					}
307 				}
308 				Fontstat = Font[0];
309 			}
310 			if ((Wordx + 1) >= MAXLINE)
311 				goto word_too_long;
312 			Word[Wordx++] = Trtbl[(int)*s];
313 			break;
314 		case 'I':
315 			if (isalnum(*s)) {
316 				if (Fontctl == 0) {
317 					if ((Wordx + 3) >= MAXLINE)
318 						goto word_too_long;
319 					Word[Wordx++] = '_';
320 					Word[Wordx++] = '\b';
321 					Word[Wordx++] = Trtbl[(int)*s];
322 					break;
323 				}
324 				if (Fontstat != 'I') {
325 					if (Fontstat != 'R')
326 						Setroman();
327 					if ((Wordx + Fstr.itl) >= MAXLINE)
328 						goto word_too_long;
329 					if (Fstr.it) {
330 					    for (i = 0; i < Fstr.itl; i++) {
331 						Word[Wordx++] = Fstr.it[i];
332 					    }
333 					}
334 					Fontstat = 'I';
335 				}
336 				if ((Wordx + 1) >= MAXLINE)
337 					goto word_too_long;
338 				Word[Wordx++] = Trtbl[(int)*s];
339 				break;
340 			}
341 			/* else fall through */
342 		default:
343 			if (Fontstat != 'R')
344 				Setroman();
345 			if ((Wordx + 1) >= MAXLINE)
346 				goto word_too_long;
347 			Word[Wordx++] = Trtbl[(int)*s];
348 		}
349 	}
350 	return(0);
351 }
352