xref: /netbsd/bin/csh/str.c (revision 7405c8c3)
1 /* $NetBSD: str.c,v 1.16 2019/01/05 16:54:00 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.16 2019/01/05 16:54:00 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 **
blk2short(char ** src)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 **
short2blk(Char * const * src)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 *
str2short(const char * src)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(sdst, (size_t)dstsize * sizeof(*sdst));
118 	    edst = &sdst[dstsize];
119 	    dst = &edst[-MALLOC_INCR];
120 	}
121     }
122     *dst = 0;
123     return (sdst);
124 }
125 
126 char *
short2str(const Char * src)127 short2str(const Char *src)
128 {
129     static char *sdst = NULL;
130     static size_t dstsize = 0;
131     char *dst, *edst;
132 
133     if (src == NULL)
134 	return (NULL);
135 
136     if (sdst == NULL) {
137 	dstsize = MALLOC_INCR;
138 	sdst = xmalloc((size_t)dstsize * sizeof(*sdst));
139     }
140     dst = sdst;
141     edst = &dst[dstsize];
142     while (*src) {
143 	*dst++ = (char) *src++;
144 	if (dst == edst) {
145 	    dstsize += MALLOC_INCR;
146 	    sdst = xrealloc(sdst, (size_t)dstsize * sizeof(*sdst));
147 	    edst = &sdst[dstsize];
148 	    dst = &edst[-MALLOC_INCR];
149 	}
150     }
151     *dst = 0;
152     return (sdst);
153 }
154 
155 Char *
s_strcpy(Char * dst,const Char * src)156 s_strcpy(Char *dst, const Char *src)
157 {
158     Char *sdst;
159 
160     sdst = dst;
161     while ((*dst++ = *src++) != '\0')
162 	continue;
163     return (sdst);
164 }
165 
166 Char *
s_strncpy(Char * dst,const Char * src,size_t n)167 s_strncpy(Char *dst, const Char *src, size_t n)
168 {
169     Char *sdst;
170 
171     if (n == 0)
172 	return(dst);
173 
174     sdst = dst;
175     do
176 	if ((*dst++ = *src++) == '\0') {
177 	    while (--n != 0)
178 		*dst++ = '\0';
179 	    return(sdst);
180 	}
181     while (--n != 0);
182     return (sdst);
183 }
184 
185 Char *
s_strcat(Char * dst,const Char * src)186 s_strcat(Char *dst, const Char *src)
187 {
188     short *sdst;
189 
190     sdst = dst;
191     while (*dst++)
192 	continue;
193     --dst;
194     while ((*dst++ = *src++) != '\0')
195 	continue;
196     return (sdst);
197 }
198 
199 #ifdef NOTUSED
200 Char *
s_strncat(Char * dst,Char * src,size_t n)201 s_strncat(Char *dst, Char *src, size_t n)
202 {
203     Char *sdst;
204 
205     if (n == 0)
206 	return (dst);
207 
208     sdst = dst;
209 
210     while (*dst++)
211 	continue;
212     --dst;
213 
214     do
215 	if ((*dst++ = *src++) == '\0')
216 	    return(sdst);
217     while (--n != 0)
218 	continue;
219 
220     *dst = '\0';
221     return (sdst);
222 }
223 
224 #endif
225 
226 Char *
s_strchr(const Char * str,int ch)227 s_strchr(const Char *str, int ch)
228 {
229     do
230 	if (*str == ch)
231 	    return __UNCONST(str);
232     while (*str++);
233     return (NULL);
234 }
235 
236 Char *
s_strrchr(const Char * str,int ch)237 s_strrchr(const Char *str, int ch)
238 {
239     const Char *rstr;
240 
241     rstr = NULL;
242     do
243 	if (*str == ch)
244 	    rstr = str;
245     while (*str++);
246     return __UNCONST(rstr);
247 }
248 
249 size_t
s_strlen(const Char * str)250 s_strlen(const Char *str)
251 {
252     size_t n;
253 
254     for (n = 0; *str++; n++)
255 	continue;
256     return (n);
257 }
258 
259 int
s_strcmp(const Char * str1,const Char * str2)260 s_strcmp(const Char *str1, const Char *str2)
261 {
262     for (; *str1 && *str1 == *str2; str1++, str2++)
263 	continue;
264     /*
265      * The following case analysis is necessary so that characters which look
266      * negative collate low against normal characters but high against the
267      * end-of-string NUL.
268      */
269     if (*str1 == '\0' && *str2 == '\0')
270 	return (0);
271     else if (*str1 == '\0')
272 	return (-1);
273     else if (*str2 == '\0')
274 	return (1);
275     else
276 	return (*str1 - *str2);
277 }
278 
279 int
s_strncmp(const Char * str1,const Char * str2,size_t n)280 s_strncmp(const Char *str1, const Char *str2, size_t n)
281 {
282     if (n == 0)
283 	return (0);
284     do {
285 	if (*str1 != *str2) {
286 	    /*
287 	     * The following case analysis is necessary so that characters
288 	     * which look negative collate low against normal characters
289 	     * but high against the end-of-string NUL.
290 	     */
291 	    if (*str1 == '\0')
292 		return (-1);
293 	    else if (*str2 == '\0')
294 		return (1);
295 	    else
296 		return (*str1 - *str2);
297 	}
298         if (*str1 == '\0')
299 	    return(0);
300 	str1++, str2++;
301     } while (--n != 0);
302     return(0);
303 }
304 
305 Char *
s_strsave(const Char * s)306 s_strsave(const Char *s)
307 {
308     const Char *p;
309     Char *n;
310 
311     if (s == 0)
312 	s = STRNULL;
313     for (p = s; *p++;)
314 	continue;
315     p = n = xmalloc((size_t)(p - s) * sizeof(*n));
316     while ((*n++ = *s++) != '\0')
317 	continue;
318     return __UNCONST(p);
319 }
320 
321 Char *
s_strspl(const Char * cp,const Char * dp)322 s_strspl(const Char *cp, const Char *dp)
323 {
324     Char *ep, *d;
325     const Char *p, *q;
326 
327     if (!cp)
328 	cp = STRNULL;
329     if (!dp)
330 	dp = STRNULL;
331     for (p = cp; *p++;)
332 	continue;
333     for (q = dp; *q++;)
334 	continue;
335     ep = xmalloc((size_t)((p - cp) + (q - dp) - 1) * sizeof(*ep));
336     for (d = ep, q = cp; (*d++ = *q++) != '\0';)
337 	continue;
338     for (d--, q = dp; (*d++ = *q++) != '\0';)
339 	continue;
340     return (ep);
341 }
342 
343 Char *
s_strend(const Char * cp)344 s_strend(const Char *cp)
345 {
346     if (!cp)
347 	return __UNCONST(cp);
348     while (*cp)
349 	cp++;
350     return __UNCONST(cp);
351 }
352 
353 Char *
s_strstr(const Char * s,const Char * t)354 s_strstr(const Char *s, const Char *t)
355 {
356     do {
357 	const Char *ss = s;
358 	const Char *tt = t;
359 
360 	do
361 	    if (*tt == '\0')
362 		return __UNCONST(s);
363 	while (*ss++ == *tt++);
364     } while (*s++ != '\0');
365     return (NULL);
366 }
367 #endif				/* SHORT_STRINGS */
368 
369 char *
short2qstr(const Char * src)370 short2qstr(const Char *src)
371 {
372     static char *sdst = NULL;
373     static size_t dstsize = 0;
374     char *dst, *edst;
375 
376     if (src == NULL)
377 	return (NULL);
378 
379     if (sdst == NULL) {
380 	dstsize = MALLOC_INCR;
381 	sdst = xmalloc((size_t)dstsize * sizeof(*sdst));
382     }
383     dst = sdst;
384     edst = &dst[dstsize];
385     while (*src) {
386 
387 	if (*src & QUOTE) {
388 	    *dst++ = '\\';
389 	    if (dst == edst) {
390 		dstsize += MALLOC_INCR;
391 		sdst = xrealloc(sdst, (size_t)dstsize * sizeof(*sdst));
392 		edst = &sdst[dstsize];
393 		dst = &edst[-MALLOC_INCR];
394 	    }
395 	}
396 	*dst++ = (char) *src++;
397 	if (dst == edst) {
398 	    dstsize += MALLOC_INCR;
399 	    sdst = xrealloc(sdst, (size_t)dstsize * sizeof(*sdst));
400 	    edst = &sdst[dstsize];
401 	    dst = &edst[-MALLOC_INCR];
402 	}
403     }
404     *dst = 0;
405     return (sdst);
406 }
407 
408 /*
409  * XXX: Should we worry about QUOTE'd chars?
410  */
411 char *
vis_str(const Char * cp)412 vis_str(const Char *cp)
413 {
414     static char *sdst = NULL;
415     static size_t dstsize = 0;
416     const Char *dp;
417     size_t n;
418 
419     if (cp == NULL)
420 	return (NULL);
421 
422     for (dp = cp; *dp++;)
423 	continue;
424     n = ((size_t)(dp - cp) << 2) + 1; /* 4 times + NULL */
425     if (dstsize < n) {
426 	sdst = (dstsize ?
427 	    xrealloc(sdst, (size_t)n * sizeof(*sdst)) :
428 	    xmalloc((size_t)n * sizeof(*sdst)));
429 	dstsize = n;
430     }
431     /*
432      * XXX: When we are in AsciiOnly we want all characters >= 0200 to
433      * be encoded, but currently there is no way in vis to do that.
434      */
435     (void)strvis(sdst, short2str(cp), VIS_NOSLASH);
436     return (sdst);
437 }
438