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