xref: /openbsd/bin/csh/str.c (revision 17df1aa7)
1 /*	$OpenBSD: str.c,v 1.15 2009/10/27 23:59:21 deraadt 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 #ifdef SHORT_STRINGS
48 
49 Char  **
50 blk2short(char **src)
51 {
52     size_t     n;
53     Char **sdst, **dst;
54 
55     /*
56      * Count
57      */
58     for (n = 0; src[n] != NULL; n++)
59 	continue;
60     sdst = dst = (Char **) xmalloc((size_t) ((n + 1) * sizeof(Char *)));
61 
62     for (; *src != NULL; src++)
63 	*dst++ = SAVE(*src);
64     *dst = NULL;
65     return (sdst);
66 }
67 
68 char  **
69 short2blk(Char **src)
70 {
71     size_t     n;
72     char **sdst, **dst;
73 
74     /*
75      * Count
76      */
77     for (n = 0; src[n] != NULL; n++)
78 	continue;
79     sdst = dst = (char **) xmalloc((size_t) ((n + 1) * sizeof(char *)));
80 
81     for (; *src != NULL; src++)
82 	*dst++ = strsave(short2str(*src));
83     *dst = NULL;
84     return (sdst);
85 }
86 
87 Char   *
88 str2short(char *src)
89 {
90     static Char *sdst;
91     static size_t dstsize = 0;
92     Char *dst, *edst;
93 
94     if (src == NULL)
95 	return (NULL);
96 
97     if (sdst == (NULL)) {
98 	dstsize = MALLOC_INCR;
99 	sdst = (Char *) xmalloc((size_t) dstsize * sizeof(Char));
100     }
101 
102     dst = sdst;
103     edst = &dst[dstsize];
104     while (*src) {
105 	*dst++ = (Char) ((unsigned char) *src++);
106 	if (dst == edst) {
107 	    dstsize += MALLOC_INCR;
108 	    sdst = (Char *) xrealloc((ptr_t) sdst,
109 				     (size_t) dstsize * sizeof(Char));
110 	    edst = &sdst[dstsize];
111 	    dst = &edst[-MALLOC_INCR];
112 	}
113     }
114     *dst = 0;
115     return (sdst);
116 }
117 
118 char   *
119 short2str(Char *src)
120 {
121     static char *sdst = NULL;
122     static size_t dstsize = 0;
123     char *dst, *edst;
124 
125     if (src == NULL)
126 	return (NULL);
127 
128     if (sdst == NULL) {
129 	dstsize = MALLOC_INCR;
130 	sdst = (char *) xmalloc((size_t) dstsize * sizeof(char));
131     }
132     dst = sdst;
133     edst = &dst[dstsize];
134     while (*src) {
135 	*dst++ = (char) *src++;
136 	if (dst == edst) {
137 	    dstsize += MALLOC_INCR;
138 	    sdst = (char *) xrealloc((ptr_t) sdst,
139 				     (size_t) dstsize * sizeof(char));
140 	    edst = &sdst[dstsize];
141 	    dst = &edst[-MALLOC_INCR];
142 	}
143     }
144     *dst = 0;
145     return (sdst);
146 }
147 
148 size_t
149 s_strlcpy(Char *dst, const Char *src, size_t siz)
150 {
151         Char *d = dst;
152         const Char *s = src;
153         size_t n = siz;
154 
155         /* Copy as many bytes as will fit */
156         if (n != 0 && --n != 0) {
157                 do {
158                         if ((*d++ = *s++) == 0)
159                                 break;
160                 } while (--n != 0);
161         }
162 
163         /* Not enough room in dst, add NUL and traverse rest of src */
164         if (n == 0) {
165                 if (siz != 0)
166                         *d = '\0';              /* NUL-terminate dst */
167                 while (*s++)
168                         ;
169         }
170 
171         return(s - src - 1);    /* count does not include NUL */
172 }
173 
174 size_t
175 s_strlcat(Char *dst, const Char *src, size_t siz)
176 {
177         Char *d = dst;
178         const Char *s = src;
179         size_t n = siz;
180         size_t dlen;
181 
182         /* Find the end of dst and adjust bytes left but don't go past end */
183         while (n-- != 0 && *d != '\0')
184                 d++;
185         dlen = d - dst;
186         n = siz - dlen;
187 
188         if (n == 0)
189                 return(dlen + s_strlen((Char *)s));
190         while (*s != '\0') {
191                 if (n != 1) {
192                         *d++ = *s;
193                         n--;
194                 }
195                 s++;
196         }
197         *d = '\0';
198 
199         return(dlen + (s - src));       /* count does not include NUL */
200 }
201 
202 Char   *
203 s_strchr(Char *str, int ch)
204 {
205     do
206 	if (*str == ch)
207 	    return (str);
208     while (*str++)
209 	;
210     return (NULL);
211 }
212 
213 Char   *
214 s_strrchr(Char *str, int ch)
215 {
216     Char *rstr;
217 
218     rstr = NULL;
219     do
220 	if (*str == ch)
221 	    rstr = str;
222     while (*str++)
223 	;
224     return (rstr);
225 }
226 
227 size_t
228 s_strlen(Char *str)
229 {
230     size_t n;
231 
232     for (n = 0; *str++; n++)
233 	continue;
234     return (n);
235 }
236 
237 int
238 s_strcmp(Char *str1, Char *str2)
239 {
240     for (; *str1 && *str1 == *str2; str1++, str2++)
241 	continue;
242     /*
243      * The following case analysis is necessary so that characters which look
244      * negative collate low against normal characters but high against the
245      * end-of-string NUL.
246      */
247     if (*str1 == '\0' && *str2 == '\0')
248 	return (0);
249     else if (*str1 == '\0')
250 	return (-1);
251     else if (*str2 == '\0')
252 	return (1);
253     else
254 	return (*str1 - *str2);
255 }
256 
257 int
258 s_strncmp(Char *str1, Char *str2, size_t n)
259 {
260     if (n == 0)
261 	return (0);
262     do {
263 	if (*str1 != *str2) {
264 	    /*
265 	     * The following case analysis is necessary so that characters
266 	     * which look negative collate low against normal characters
267 	     * but high against the end-of-string NUL.
268 	     */
269 	    if (*str1 == '\0')
270 		return (-1);
271 	    else if (*str2 == '\0')
272 		return (1);
273 	    else
274 		return (*str1 - *str2);
275 	    break;
276 	}
277 	if (*str1 == '\0')
278 	    return(0);
279 	str1++, str2++;
280     } while (--n != 0);
281     return(0);
282 }
283 
284 Char   *
285 s_strsave(Char *s)
286 {
287     Char   *n;
288     Char *p;
289 
290     if (s == 0)
291 	s = STRNULL;
292     for (p = s; *p++;)
293 	continue;
294     n = p = (Char *) xmalloc((size_t) ((p - s) * sizeof(Char)));
295     while ((*p++ = *s++) != '\0')
296 	continue;
297     return (n);
298 }
299 
300 Char   *
301 s_strspl(Char *cp, Char *dp)
302 {
303     Char   *ep;
304     Char *p, *q;
305 
306     if (!cp)
307 	cp = STRNULL;
308     if (!dp)
309 	dp = STRNULL;
310     for (p = cp; *p++;)
311 	continue;
312     for (q = dp; *q++;)
313 	continue;
314     ep = (Char *) xmalloc((size_t)
315 			  (((p - cp) + (q - dp) - 1) * sizeof(Char)));
316     for (p = ep, q = cp; (*p++ = *q++) != '\0';)
317 	continue;
318     for (p--, q = dp; (*p++ = *q++) != '\0';)
319 	continue;
320     return (ep);
321 }
322 
323 Char   *
324 s_strend(Char *cp)
325 {
326     if (!cp)
327 	return (cp);
328     while (*cp)
329 	cp++;
330     return (cp);
331 }
332 
333 Char   *
334 s_strstr(Char *s, Char *t)
335 {
336     do {
337 	Char *ss = s;
338 	Char *tt = t;
339 
340 	do
341 	    if (*tt == '\0')
342 		return (s);
343 	while (*ss++ == *tt++);
344     } while (*s++ != '\0');
345     return (NULL);
346 }
347 #endif				/* SHORT_STRINGS */
348 
349 char   *
350 short2qstr(Char *src)
351 {
352     static char *sdst = NULL;
353     static size_t dstsize = 0;
354     char *dst, *edst;
355 
356     if (src == NULL)
357 	return (NULL);
358 
359     if (sdst == NULL) {
360 	dstsize = MALLOC_INCR;
361 	sdst = (char *) xmalloc((size_t) dstsize * sizeof(char));
362     }
363     dst = sdst;
364     edst = &dst[dstsize];
365     while (*src) {
366 	if (*src & QUOTE) {
367 	    *dst++ = '\\';
368 	    if (dst == edst) {
369 		dstsize += MALLOC_INCR;
370 		sdst = (char *) xrealloc((ptr_t) sdst,
371 					 (size_t) dstsize * sizeof(char));
372 		edst = &sdst[dstsize];
373 		dst = &edst[-MALLOC_INCR];
374 	    }
375 	}
376 	*dst++ = (char) *src++;
377 	if (dst == edst) {
378 	    dstsize += MALLOC_INCR;
379 	    sdst = (char *) xrealloc((ptr_t) sdst,
380 				     (size_t) dstsize * sizeof(char));
381 	    edst = &sdst[dstsize];
382 	    dst = &edst[-MALLOC_INCR];
383 	}
384     }
385     *dst = 0;
386     return (sdst);
387 }
388 
389 /*
390  * XXX: Should we worry about QUOTE'd chars?
391  */
392 char *
393 vis_str(Char *cp)
394 {
395     static char *sdst = NULL;
396     static size_t dstsize = 0;
397     size_t n;
398     Char *dp;
399 
400     if (cp == NULL)
401 	return (NULL);
402 
403     for (dp = cp; *dp++;)
404 	continue;
405     n = ((dp - cp) << 2) + 1; /* 4 times + NUL */
406     if (dstsize < n) {
407 	sdst = (char *) (dstsize ?
408 			    xrealloc(sdst, (size_t) n * sizeof(char)) :
409 			    xmalloc((size_t) n * sizeof(char)));
410 	dstsize = n;
411     }
412     /*
413      * XXX: When we are in AsciiOnly we want all characters >= 0200 to
414      * be encoded, but currently there is no way in vis to do that.
415      */
416     (void) strnvis(sdst, short2str(cp), dstsize, VIS_NOSLASH);
417     return (sdst);
418 }
419 
420