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