xref: /freebsd/contrib/tcsh/tc.str.c (revision 7bd6fde3)
1 /* $Header: /src/pub/tcsh/tc.str.c,v 3.19 2005/01/06 16:56:26 christos Exp $ */
2 /*
3  * tc.str.c: Short string package
4  * 	     This has been a lesson of how to write buggy code!
5  */
6 /*-
7  * Copyright (c) 1980, 1991 The Regents of the University of California.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 #include "sh.h"
35 
36 #include <limits.h>
37 
38 RCSID("$Id: tc.str.c,v 3.19 2005/01/06 16:56:26 christos Exp $")
39 
40 #define MALLOC_INCR	128
41 #ifdef WIDE_STRINGS
42 #define MALLOC_SURPLUS	MB_LEN_MAX /* Space for one multibyte character */
43 #else
44 #define MALLOC_SURPLUS	0
45 #endif
46 
47 #ifdef WIDE_STRINGS
48 size_t
49 one_mbtowc(wchar_t *pwc, const char *s, size_t n)
50 {
51     int len;
52 
53     len = rt_mbtowc(pwc, s, n);
54     if (len == -1) {
55         mbtowc(NULL, NULL, 0);
56 	*pwc = (unsigned char)*s | INVALID_BYTE;
57     }
58     if (len <= 0)
59 	len = 1;
60     return len;
61 }
62 
63 size_t
64 one_wctomb(char *s, wchar_t wchar)
65 {
66     int len;
67 
68     if (wchar & INVALID_BYTE) {
69 	s[0] = wchar & 0xFF;
70 	len = 1;
71     } else {
72 	len = wctomb(s, wchar);
73 	if (len == -1)
74 	    s[0] = wchar;
75 	if (len <= 0)
76 	    len = 1;
77     }
78     return len;
79 }
80 #endif
81 
82 #ifdef SHORT_STRINGS
83 int
84 rt_mbtowc(wchar_t *pwc, const char *s, size_t n)
85 {
86     int ret;
87     char back[MB_LEN_MAX];
88 
89     ret = mbtowc(pwc, s, n);
90     if (ret > 0 && (wctomb(back, *pwc) != ret || memcmp(s, back, ret) != 0))
91 	ret = -1;
92     return ret;
93 }
94 
95 Char  **
96 blk2short(src)
97     char **src;
98 {
99     size_t     n;
100     Char **sdst, **dst;
101 
102     /*
103      * Count
104      */
105     for (n = 0; src[n] != NULL; n++)
106 	continue;
107     sdst = dst = (Char **) xmalloc((size_t) ((n + 1) * sizeof(Char *)));
108 
109     for (; *src != NULL; src++)
110 	*dst++ = SAVE(*src);
111     *dst = NULL;
112     return (sdst);
113 }
114 
115 char  **
116 short2blk(src)
117     Char **src;
118 {
119     size_t     n;
120     char **sdst, **dst;
121 
122     /*
123      * Count
124      */
125     for (n = 0; src[n] != NULL; n++)
126 	continue;
127     sdst = dst = (char **) xmalloc((size_t) ((n + 1) * sizeof(char *)));
128 
129     for (; *src != NULL; src++)
130 	*dst++ = strsave(short2str(*src));
131     *dst = NULL;
132     return (sdst);
133 }
134 
135 Char   *
136 str2short(src)
137     const char *src;
138 {
139     static Char *sdst;
140     static size_t dstsize = 0;
141     Char *dst, *edst;
142 
143     if (src == NULL)
144 	return (NULL);
145 
146     if (sdst == (NULL)) {
147 	dstsize = MALLOC_INCR;
148 	sdst = (Char *) xmalloc((size_t) (dstsize * sizeof(Char)));
149     }
150 
151     dst = sdst;
152     edst = &dst[dstsize];
153     while ((unsigned char) *src) {
154 	src += one_mbtowc(dst, src, MB_LEN_MAX);
155 	dst++;
156 	if (dst == edst) {
157 	    dstsize += MALLOC_INCR;
158 	    sdst = (Char *) xrealloc((ptr_t) sdst,
159 				     (size_t) (dstsize * sizeof(Char)));
160 	    edst = &sdst[dstsize];
161 	    dst = &edst[-MALLOC_INCR];
162 	}
163     }
164     *dst = 0;
165     return (sdst);
166 }
167 
168 char   *
169 short2str(src)
170     const Char *src;
171 {
172     static char *sdst = NULL;
173     static size_t dstsize = 0;
174     char *dst, *edst;
175 
176     if (src == NULL)
177 	return (NULL);
178 
179     if (sdst == NULL) {
180 	dstsize = MALLOC_INCR;
181 	sdst = (char *) xmalloc((size_t) ((dstsize + MALLOC_SURPLUS)
182 					  * sizeof(char)));
183     }
184     dst = sdst;
185     edst = &dst[dstsize];
186     while (*src) {
187 	dst += one_wctomb(dst, *src & CHAR);
188 	src++;
189 	if (dst >= edst) {
190 	    dstsize += MALLOC_INCR;
191 	    sdst = (char *) xrealloc((ptr_t) sdst,
192 				     (size_t) ((dstsize + MALLOC_SURPLUS)
193 					       * sizeof(char)));
194 	    edst = &sdst[dstsize];
195 	    dst = &edst[-MALLOC_INCR];
196 	}
197     }
198     *dst = 0;
199     return (sdst);
200 }
201 
202 #ifndef WIDE_STRINGS
203 Char   *
204 s_strcpy(dst, src)
205     Char *dst;
206     const Char *src;
207 {
208     Char *sdst;
209 
210     sdst = dst;
211     while ((*dst++ = *src++) != '\0')
212 	continue;
213     return (sdst);
214 }
215 
216 Char   *
217 s_strncpy(dst, src, n)
218     Char *dst;
219     const Char *src;
220     size_t n;
221 {
222     Char *sdst;
223 
224     if (n == 0)
225 	return(dst);
226 
227     sdst = dst;
228     do
229 	if ((*dst++ = *src++) == '\0') {
230 	    while (--n != 0)
231 		*dst++ = '\0';
232 	    return(sdst);
233 	}
234     while (--n != 0);
235     return (sdst);
236 }
237 
238 Char   *
239 s_strcat(dst, src)
240     Char *dst;
241     const Char *src;
242 {
243     Char *sdst;
244 
245     sdst = dst;
246     while (*dst++)
247 	continue;
248     --dst;
249     while ((*dst++ = *src++) != '\0')
250 	continue;
251     return (sdst);
252 }
253 
254 #ifdef NOTUSED
255 Char   *
256 s_strncat(dst, src, n)
257     Char *dst;
258     const Char *src;
259     size_t n;
260 {
261     Char *sdst;
262 
263     if (n == 0)
264 	return (dst);
265 
266     sdst = dst;
267 
268     while (*dst++)
269 	continue;
270     --dst;
271 
272     do
273 	if ((*dst++ = *src++) == '\0')
274 	    return(sdst);
275     while (--n != 0)
276 	continue;
277 
278     *dst = '\0';
279     return (sdst);
280 }
281 
282 #endif
283 
284 Char   *
285 s_strchr(str, ch)
286     const Char *str;
287     int ch;
288 {
289     do
290 	if (*str == ch)
291 	    return ((Char *)(intptr_t)str);
292     while (*str++);
293     return (NULL);
294 }
295 
296 Char   *
297 s_strrchr(str, ch)
298     const Char *str;
299     int ch;
300 {
301     const Char *rstr;
302 
303     rstr = NULL;
304     do
305 	if (*str == ch)
306 	    rstr = str;
307     while (*str++);
308     return ((Char *)(intptr_t)rstr);
309 }
310 
311 size_t
312 s_strlen(str)
313     const Char *str;
314 {
315     size_t n;
316 
317     for (n = 0; *str++; n++)
318 	continue;
319     return (n);
320 }
321 
322 int
323 s_strcmp(str1, str2)
324     const Char *str1, *str2;
325 {
326     for (; *str1 && *str1 == *str2; str1++, str2++)
327 	continue;
328     /*
329      * The following case analysis is necessary so that characters which look
330      * negative collate low against normal characters but high against the
331      * end-of-string NUL.
332      */
333     if (*str1 == '\0' && *str2 == '\0')
334 	return (0);
335     else if (*str1 == '\0')
336 	return (-1);
337     else if (*str2 == '\0')
338 	return (1);
339     else
340 	return (*str1 - *str2);
341 }
342 
343 int
344 s_strncmp(str1, str2, n)
345     const Char *str1, *str2;
346     size_t n;
347 {
348     if (n == 0)
349 	return (0);
350     do {
351 	if (*str1 != *str2) {
352 	    /*
353 	     * The following case analysis is necessary so that characters
354 	     * which look negative collate low against normal characters
355 	     * but high against the end-of-string NUL.
356 	     */
357 	    if (*str1 == '\0')
358 		return (-1);
359 	    else if (*str2 == '\0')
360 		return (1);
361 	    else
362 		return (*str1 - *str2);
363 	}
364         if (*str1 == '\0')
365 	    return(0);
366 	str1++, str2++;
367     } while (--n != 0);
368     return(0);
369 }
370 #endif /* not WIDE_STRINGS */
371 
372 int
373 s_strcasecmp(str1, str2)
374     const Char *str1, *str2;
375 {
376 #ifdef WIDE_STRINGS
377     wchar_t l1 = 0, l2 = 0;
378     for (; *str1 && ((*str1 == *str2 && (l1 = l2 = 0) == 0) ||
379 	(l1 = towlower(*str1)) == (l2 = towlower(*str2))); str1++, str2++)
380 	continue;
381 
382 #else
383     unsigned char c1, c2, l1 = 0, l2 = 0;
384     for (; *str1 && ((*str1 == *str2 && (l1 = l2 = 0) == 0) ||
385 	((c1 = (unsigned char)*str1) == *str1 &&
386 	 (c2 = (unsigned char)*str2) == *str2 &&
387 	(l1 = tolower(c1)) == (l2 = tolower(c2)))); str1++, str2++)
388 	continue;
389 #endif
390     /*
391      * The following case analysis is necessary so that characters which look
392      * negative collate low against normal characters but high against the
393      * end-of-string NUL.
394      */
395     if (*str1 == '\0' && *str2 == '\0')
396 	return (0);
397     else if (*str1 == '\0')
398 	return (-1);
399     else if (*str2 == '\0')
400 	return (1);
401     else if (l1 == l2)	/* They are zero when they are equal */
402 	return (*str1 - *str2);
403     else
404 	return (l1 - l2);
405 }
406 
407 Char   *
408 s_strsave(s)
409     const Char *s;
410 {
411     Char   *n;
412     Char *p;
413 
414     if (s == 0)
415 	s = STRNULL;
416     for (p = (Char *)(intptr_t)s; *p++;)
417 	continue;
418     n = p = (Char *) xmalloc((size_t)
419 			     ((((const Char *) p) - s) * sizeof(Char)));
420     while ((*p++ = *s++) != '\0')
421 	continue;
422     return (n);
423 }
424 
425 Char   *
426 s_strspl(cp, dp)
427     const Char   *cp, *dp;
428 {
429     Char   *ep;
430     Char *p, *q;
431 
432     if (!cp)
433 	cp = STRNULL;
434     if (!dp)
435 	dp = STRNULL;
436     for (p = (Char *)(intptr_t) cp; *p++;)
437 	continue;
438     for (q = (Char *)(intptr_t) dp; *q++;)
439 	continue;
440     ep = (Char *) xmalloc((size_t)
441 			  (((((const Char *) p) - cp) +
442 			    (((const Char *) q) - dp) - 1) * sizeof(Char)));
443     for (p = ep, q = (Char*)(intptr_t) cp; (*p++ = *q++) != '\0';)
444 	continue;
445     for (p--, q = (Char *)(intptr_t) dp; (*p++ = *q++) != '\0';)
446 	continue;
447     return (ep);
448 }
449 
450 Char   *
451 s_strend(cp)
452     const Char *cp;
453 {
454     if (!cp)
455 	return ((Char *)(intptr_t) cp);
456     while (*cp)
457 	cp++;
458     return ((Char *)(intptr_t) cp);
459 }
460 
461 Char   *
462 s_strstr(s, t)
463     const Char *s, *t;
464 {
465     do {
466 	const Char *ss = s;
467 	const Char *tt = t;
468 
469 	do
470 	    if (*tt == '\0')
471 		return ((Char *)(intptr_t) s);
472 	while (*ss++ == *tt++);
473     } while (*s++ != '\0');
474     return (NULL);
475 }
476 
477 #endif				/* SHORT_STRINGS */
478 
479 char   *
480 short2qstr(src)
481     const Char *src;
482 {
483     static char *sdst = NULL;
484     static size_t dstsize = 0;
485     char *dst, *edst;
486 
487     if (src == NULL)
488 	return (NULL);
489 
490     if (sdst == NULL) {
491 	dstsize = MALLOC_INCR;
492 	sdst = (char *) xmalloc((size_t) ((dstsize + MALLOC_SURPLUS)
493 					  * sizeof(char)));
494     }
495     dst = sdst;
496     edst = &dst[dstsize];
497     while (*src) {
498 	if (*src & QUOTE) {
499 	    *dst++ = '\\';
500 	    if (dst == edst) {
501 		dstsize += MALLOC_INCR;
502 		sdst = (char *) xrealloc((ptr_t) sdst,
503 					 (size_t) ((dstsize + MALLOC_SURPLUS)
504 						   * sizeof(char)));
505 		edst = &sdst[dstsize];
506 		dst = &edst[-MALLOC_INCR];
507 	    }
508 	}
509 	dst += one_wctomb(dst, *src & CHAR);
510 	src++;
511 	if (dst >= edst) {
512 	    dstsize += MALLOC_INCR;
513 	    sdst = (char *) xrealloc((ptr_t) sdst,
514 				     (size_t) ((dstsize + MALLOC_SURPLUS)
515 					       * sizeof(char)));
516 	    edst = &sdst[dstsize];
517 	    dst = &edst[-MALLOC_INCR];
518 	}
519     }
520     *dst = 0;
521     return (sdst);
522 }
523