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