xref: /minix/minix/commands/cawf/string.c (revision 9f988b79)
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(void);
35 
36 
37 /*
38  * Asmname(s, c) - assemble name
39  */
40 
41 int Asmname(unsigned char *s, unsigned char *c) {
42 /* pointer to name s
43  * code destination (c[3])
44  */
45 	c[1] = c[2] = '\0';
46 	while (*s && *s == ' ')
47 		s++;
48 	if ((c[0] = *s) == '\0')
49 		return(0);
50 	return(((c[1] = s[1]) == '\0') ? 1 : 2);
51 }
52 
53 
54 /*
55  * Delstr(sx) - delete string
56  */
57 
58 void Delstr(int sx) {
59 /* string index sx */
60 	char buf[MAXLINE];		/* message buffer */
61 
62 	if (sx >= Nstr) {
63 		(void) sprintf(buf, " bad Delstr(%d) index", sx);
64 		Error(FATAL, LINE, buf, NULL);
65 	}
66 	Free(&Str[sx].str);
67 	while (sx < (Nstr - 1)) {
68 		Str[sx] = Str[sx + 1];
69 		sx++;
70 	}
71 	Nstr--;
72 }
73 
74 
75 /*
76  * Endword() - end a word
77  */
78 
79 void Endword(void) {
80 	if (Fontstat != 'R')
81 		Setroman();
82 	Word[Wordx] = '\0';
83 }
84 
85 
86 /*
87  * Findchar(nm, l, s, e) - find special character definition and
88  *			   optionally enter it
89  */
90 
91 int Findchar(unsigned char *nm, int l, unsigned char *s, int e) {
92 /* character name nm
93  * effective length l
94  * value string s
95  * e = 0 = find, don't enter
96  * e = 1 = don't find, enter
97  */
98 	int cmp, hi, low, mid;
99 	unsigned char c[3];
100 
101 	c[0] = nm[0];
102 	c[1] = (nm[1] == ' ' || nm[1] == '\t') ? '\0' : nm[1];
103 	c[2] = '\0';
104 	low = mid = 0;
105 	hi = Nsch - 1;
106 	while (low <= hi) {
107 		mid = (low + hi) / 2;
108 		if ((cmp = strncmp((char *)c, (char *)Schar[mid].nm, 2)) < 0)
109 			hi = mid - 1;
110 		else if (cmp > 0)
111 			low = mid + 1;
112 		else {
113 			if ( ! e)
114 				return(mid);
115 			Free(&Schar[mid].str);
116 			goto new_char;
117 		}
118 	}
119 	if ( ! e)
120 		return(-1);
121 	if (Nsch >= MAXSCH)
122 		Error(FATAL, LINE, " at character table limit", NULL);
123 	if (Nsch) {
124 		if (cmp > 0)
125 			mid++;
126 		for (hi = Nsch - 1; hi >= mid; hi--)
127 			Schar[hi+1] = Schar[hi];
128 	}
129 	Nsch++;
130 	Schar[mid].nm[0] = c[0];
131 	Schar[mid].nm[1] = c[1];
132 
133 new_char:
134 
135 	Schar[mid].str = Newstr(s);
136 	Schar[mid].len = l;
137 	return(mid);
138 }
139 
140 
141 /*
142  * Findhy(s, l, e) - find and optionally enter hyphen
143  */
144 
145 int Findhy(unsigned char *s, int l, int e) {
146 /* value string s
147  * equivalent length l
148  * e = 0 = find, don't enter
149  * e = 1 = enter, don't find
150  */
151 	int i;
152 
153 	for (i = 0; i < Nhy; i++) {
154 		if (Font[0] == Hychar[i].font)
155 			break;
156 	}
157 	if (i >= Nhy) {
158 		if ( ! e)
159 			return(-1);
160 		if (Nhy >= MAXHYCH)
161 			Error(FATAL, LINE, " at hyphen limit for font ",
162 				(char *)Font);
163 		Hychar[i].font = Font[0];
164 		Nhy++;
165 	} else {
166 		if ( ! e)
167 			return(i);
168 		Error(WARN, LINE, " duplicate hyphen for font ", (char *)Font);
169 		Free(&Hychar[i].str);
170 	}
171 	Hychar[i].str = Newstr(s);
172 	Hychar[i].len = l;
173 	return(i);
174 }
175 
176 
177 /*
178  * Findstr(nm, s, e) - find and  optionally enter string in Str[]
179  */
180 
181 unsigned char *Findstr(unsigned char *nm, unsigned char *s, int e) {
182 /* 2 character string name nm
183  * string value s
184  * e = 0 = find, don't enter
185  * e = 1 = enter, don't find
186  */
187 	unsigned char c[3];		/* character buffer */
188 	int cmp, hi, low, mid;		/* binary search controls */
189 	int i;				/* temporary indexes */
190 	unsigned char *s1, *s2;		/* temporary string pointers */
191 
192 	c[0] = nm[0];
193 	c[1] = (nm[1] == ' ' || nm[1] == '\t') ? '\0' : nm[1];
194 	c[2] = '\0';
195 	low = mid = 0;
196 	hi = Nstr - 1;
197 	Sx = -1;
198 	while (low <= hi) {
199 		mid = (low + hi) / 2;
200 		if ((cmp = strncmp((char *)c, (char *)Str[mid].nm, 2)) < 0)
201 			hi = mid - 1;
202 		else if (cmp > 0)
203 			low = mid + 1;
204 		else {
205 			Sx = mid;
206 			if ( ! e)
207 				return(Str[mid].str);
208 			Free(&Str[mid].str);
209 			goto new_string;
210 		}
211 	}
212 	if ( ! e)
213 		return((unsigned char *)"");
214 	if (Nstr >= MAXSTR)
215 		Error(FATAL, LINE, " out of space for string ", (char *)c);
216 	if (Nstr) {
217 		if (cmp > 0)
218 			mid++;
219 		for (hi = Nstr - 1; hi >= mid; hi--)
220 			Str[hi+1] = Str[hi];
221 	}
222 	Nstr++;
223 	Sx = mid;
224 	Str[mid].nm[0] = c[0];
225 	Str[mid].nm[1] = c[1];
226 
227 new_string:
228 
229 	if (s == NULL)
230 		return (Str[mid].str = Newstr((unsigned char *)""));
231 	i = (*s == '"') ? 1 : 0;
232 	s1 = Str[mid].str = Newstr(s + i);
233 	if (i) {
234 		s2 = s1 + strlen((char *)s1);
235 		if (s2 > s1 && *(s2-1) == '"')
236 			*(s2-1) = '\0';
237 	}
238 	return(s1);
239 }
240 
241 
242 /*
243  * Setroman() - set Roman font
244  */
245 
246 static void Setroman(void) {
247 	int i;
248 
249 	if ((Wordx + Fstr.rl) >= MAXLINE)
250 		Error(WARN, LINE, " word too long", NULL);
251 	else {
252 		if (Fstr.r) {
253 			for (i = 0; i < Fstr.rl; i++) {
254 				Word[Wordx++] = Fstr.r[i];
255 			}
256 	    	}
257 		Fontstat = 'R';
258 	}
259 }
260 
261 
262 /*
263  * Str2word(s, len) - copy len characters from string to Word[]
264  */
265 
266 int Str2word(unsigned char *s, int len) {
267 	int i;
268 
269 	for (; len > 0; len--, s++) {
270 		switch (Font[0]) {
271 		case 'B':
272 		case 'C':
273 			if (Fontctl == 0) {
274 				if ((Wordx + 5) >= MAXLINE) {
275 word_too_long:
276 					Error(WARN, LINE, " word too long",
277 						NULL);
278 					return(1);
279 				}
280 				Word[Wordx++] = Trtbl[(int)*s];
281 				Word[Wordx++] = '\b';
282 				Word[Wordx++] = Trtbl[(int)*s];
283 				Word[Wordx++] = '\b';
284 				Word[Wordx++] = Trtbl[(int)*s];
285 				break;
286 			}
287 			if (Fontstat != Font[0]) {
288 				if (Fontstat != 'R')
289 					Setroman();
290 				if ((Wordx + Fstr.bl) >= MAXLINE)
291 					goto word_too_long;
292 				if (Fstr.b) {
293 					for (i = 0; i < Fstr.bl; i++) {
294 						Word[Wordx++] = Fstr.b[i];
295 					}
296 				}
297 				Fontstat = Font[0];
298 			}
299 			if ((Wordx + 1) >= MAXLINE)
300 				goto word_too_long;
301 			Word[Wordx++] = Trtbl[(int)*s];
302 			break;
303 		case 'I':
304 			if (isalnum(*s)) {
305 				if (Fontctl == 0) {
306 					if ((Wordx + 3) >= MAXLINE)
307 						goto word_too_long;
308 					Word[Wordx++] = '_';
309 					Word[Wordx++] = '\b';
310 					Word[Wordx++] = Trtbl[(int)*s];
311 					break;
312 				}
313 				if (Fontstat != 'I') {
314 					if (Fontstat != 'R')
315 						Setroman();
316 					if ((Wordx + Fstr.itl) >= MAXLINE)
317 						goto word_too_long;
318 					if (Fstr.it) {
319 					    for (i = 0; i < Fstr.itl; i++) {
320 						Word[Wordx++] = Fstr.it[i];
321 					    }
322 					}
323 					Fontstat = 'I';
324 				}
325 				if ((Wordx + 1) >= MAXLINE)
326 					goto word_too_long;
327 				Word[Wordx++] = Trtbl[(int)*s];
328 				break;
329 			}
330 			/* else fall through */
331 		default:
332 			if (Fontstat != 'R')
333 				Setroman();
334 			if ((Wordx + 1) >= MAXLINE)
335 				goto word_too_long;
336 			Word[Wordx++] = Trtbl[(int)*s];
337 		}
338 	}
339 	return(0);
340 }
341