1 /* $NetBSD: str.c,v 1.17 2024/04/24 15:49:03 nia 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.17 2024/04/24 15:49:03 nia 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 = xreallocarray(NULL, 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 = xreallocarray(NULL, 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 = xreallocarray(NULL, (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 = xreallocarray(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 = xreallocarray(NULL, 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 = xreallocarray(sdst, 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 = xreallocarray(NULL, (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 = xreallocarray(NULL, (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 = xreallocarray(NULL, 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 = xreallocarray(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 = xreallocarray(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               xreallocarray(sdst, (size_t)n, sizeof(*sdst)) :
428               xreallocarray(NULL, (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