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