xref: /netbsd/bin/csh/str.c (revision b5b29542)
1 /* $NetBSD: str.c,v 1.13 2003/08/07 09:05:07 agc 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.13 2003/08/07 09:05:07 agc 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 = (Char **)xmalloc((size_t)((n + 1) * sizeof(Char *)));
70 
71     for (; *src != NULL; src++)
72 	*dst++ = SAVE(*src);
73     *dst = NULL;
74     return (sdst);
75 }
76 
77 char **
78 short2blk(Char **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 = (char **)xmalloc((size_t)((n + 1) * sizeof(char *)));
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 = (Char *)xmalloc((size_t)dstsize * sizeof(Char));
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 = (Char *)xrealloc((ptr_t)sdst,
118 	        (size_t)dstsize * sizeof(Char));
119 	    edst = &sdst[dstsize];
120 	    dst = &edst[-MALLOC_INCR];
121 	}
122     }
123     *dst = 0;
124     return (sdst);
125 }
126 
127 char *
128 short2str(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 = (char *)xmalloc((size_t)dstsize * sizeof(char));
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 = (char *)xrealloc((ptr_t)sdst,
148 	        (size_t)dstsize * sizeof(char));
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, 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, 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, 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(Char *str, int ch)
230 {
231     do
232 	if (*str == ch)
233 	    return (str);
234     while (*str++);
235     return (NULL);
236 }
237 
238 Char *
239 s_strrchr(Char *str, int ch)
240 {
241     Char *rstr;
242 
243     rstr = NULL;
244     do
245 	if (*str == ch)
246 	    rstr = str;
247     while (*str++);
248     return (rstr);
249 }
250 
251 size_t
252 s_strlen(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(Char *str1, 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(Char *str1, 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(Char *s)
309 {
310     Char *n, *p;
311 
312     if (s == 0)
313 	s = STRNULL;
314     for (p = s; *p++;)
315 	continue;
316     n = p = (Char *)xmalloc((size_t)((p - s) * sizeof(Char)));
317     while ((*p++ = *s++) != '\0')
318 	continue;
319     return (n);
320 }
321 
322 Char *
323 s_strspl(Char *cp, Char *dp)
324 {
325     Char *ep, *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 = (Char *)xmalloc((size_t)(((p - cp) + (q - dp) - 1) * sizeof(Char)));
336     for (p = ep, q = cp; (*p++ = *q++) != '\0';)
337 	continue;
338     for (p--, q = dp; (*p++ = *q++) != '\0';)
339 	continue;
340     return (ep);
341 }
342 
343 Char *
344 s_strend(Char *cp)
345 {
346     if (!cp)
347 	return (cp);
348     while (*cp)
349 	cp++;
350     return (cp);
351 }
352 
353 Char *
354 s_strstr(Char *s, Char *t)
355 {
356     do {
357 	Char *ss = s;
358 	Char *tt = t;
359 
360 	do
361 	    if (*tt == '\0')
362 		return (s);
363 	while (*ss++ == *tt++);
364     } while (*s++ != '\0');
365     return (NULL);
366 }
367 #endif				/* SHORT_STRINGS */
368 
369 char *
370 short2qstr(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 = (char *)xmalloc((size_t)dstsize * sizeof(char));
382     }
383     dst = sdst;
384     edst = &dst[dstsize];
385     while (*src) {
386 	if (*src & QUOTE) {
387 	    *dst++ = '\\';
388 	    if (dst == edst) {
389 		dstsize += MALLOC_INCR;
390 		sdst = (char *)xrealloc((ptr_t) sdst,
391 		    (size_t)dstsize * sizeof(char));
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 = (char *)xrealloc((ptr_t) sdst,
400 	        (size_t)dstsize * sizeof(char));
401 	    edst = &sdst[dstsize];
402 	    dst = &edst[-MALLOC_INCR];
403 	}
404     }
405     *dst = 0;
406     return (sdst);
407 }
408 
409 /*
410  * XXX: Should we worry about QUOTE'd chars?
411  */
412 char *
413 vis_str(Char *cp)
414 {
415     static char *sdst = NULL;
416     static size_t dstsize = 0;
417     Char *dp;
418     size_t n;
419 
420     if (cp == NULL)
421 	return (NULL);
422 
423     for (dp = cp; *dp++;)
424 	continue;
425     n = ((dp - cp) << 2) + 1; /* 4 times + NULL */
426     if (dstsize < n) {
427 	sdst = (char *) (dstsize ?
428 	    xrealloc(sdst, (size_t)n * sizeof(char)) :
429 	    xmalloc((size_t)n * sizeof(char)));
430 	dstsize = n;
431     }
432     /*
433      * XXX: When we are in AsciiOnly we want all characters >= 0200 to
434      * be encoded, but currently there is no way in vis to do that.
435      */
436     (void)strvis(sdst, short2str(cp), VIS_NOSLASH);
437     return (sdst);
438 }
439