str.c revision 1.11 1 /* $NetBSD: str.c,v 1.11 2001/09/14 14:04:01 wiz 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. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 #include <sys/cdefs.h>
37 #ifndef lint
38 #if 0
39 static char sccsid[] = "@(#)str.c 8.1 (Berkeley) 5/31/93";
40 #else
41 __RCSID("$NetBSD: str.c,v 1.11 2001/09/14 14:04:01 wiz Exp $");
42 #endif
43 #endif /* not lint */
44
45 #define MALLOC_INCR 128
46
47 /*
48 * tc.str.c: Short string package
49 * This has been a lesson of how to write buggy code!
50 */
51
52 #include <sys/types.h>
53
54 #include <vis.h>
55
56 #if __STDC__
57 # include <stdarg.h>
58 #else
59 # include <varargs.h>
60 #endif
61
62 #include "csh.h"
63 #include "extern.h"
64
65 #ifdef SHORT_STRINGS
66
67 Char **
68 blk2short(char **src)
69 {
70 Char **dst, **sdst;
71 size_t n;
72
73 /*
74 * Count
75 */
76 for (n = 0; src[n] != NULL; n++)
77 continue;
78 sdst = dst = (Char **)xmalloc((size_t)((n + 1) * sizeof(Char *)));
79
80 for (; *src != NULL; src++)
81 *dst++ = SAVE(*src);
82 *dst = NULL;
83 return (sdst);
84 }
85
86 char **
87 short2blk(Char **src)
88 {
89 char **dst, **sdst;
90 size_t n;
91
92 /*
93 * Count
94 */
95 for (n = 0; src[n] != NULL; n++)
96 continue;
97 sdst = dst = (char **)xmalloc((size_t)((n + 1) * sizeof(char *)));
98
99 for (; *src != NULL; src++)
100 *dst++ = strsave(short2str(*src));
101 *dst = NULL;
102 return (sdst);
103 }
104
105 Char *
106 str2short(const char *src)
107 {
108 static Char *sdst;
109 Char *dst, *edst;
110 static size_t dstsize = 0;
111
112 if (src == NULL)
113 return (NULL);
114
115 if (sdst == (NULL)) {
116 dstsize = MALLOC_INCR;
117 sdst = (Char *)xmalloc((size_t)dstsize * sizeof(Char));
118 }
119
120 dst = sdst;
121 edst = &dst[dstsize];
122 while (*src) {
123 *dst++ = (Char) ((unsigned char) *src++);
124 if (dst == edst) {
125 dstsize += MALLOC_INCR;
126 sdst = (Char *)xrealloc((ptr_t)sdst,
127 (size_t)dstsize * sizeof(Char));
128 edst = &sdst[dstsize];
129 dst = &edst[-MALLOC_INCR];
130 }
131 }
132 *dst = 0;
133 return (sdst);
134 }
135
136 char *
137 short2str(Char *src)
138 {
139 static char *sdst = NULL;
140 static size_t dstsize = 0;
141 char *dst, *edst;
142
143 if (src == NULL)
144 return (NULL);
145
146 if (sdst == NULL) {
147 dstsize = MALLOC_INCR;
148 sdst = (char *)xmalloc((size_t)dstsize * sizeof(char));
149 }
150 dst = sdst;
151 edst = &dst[dstsize];
152 while (*src) {
153 *dst++ = (char) *src++;
154 if (dst == edst) {
155 dstsize += MALLOC_INCR;
156 sdst = (char *)xrealloc((ptr_t)sdst,
157 (size_t)dstsize * sizeof(char));
158 edst = &sdst[dstsize];
159 dst = &edst[-MALLOC_INCR];
160 }
161 }
162 *dst = 0;
163 return (sdst);
164 }
165
166 Char *
167 s_strcpy(Char *dst, Char *src)
168 {
169 Char *sdst;
170
171 sdst = dst;
172 while ((*dst++ = *src++) != '\0')
173 continue;
174 return (sdst);
175 }
176
177 Char *
178 s_strncpy(Char *dst, Char *src, size_t n)
179 {
180 Char *sdst;
181
182 if (n == 0)
183 return(dst);
184
185 sdst = dst;
186 do
187 if ((*dst++ = *src++) == '\0') {
188 while (--n != 0)
189 *dst++ = '\0';
190 return(sdst);
191 }
192 while (--n != 0);
193 return (sdst);
194 }
195
196 Char *
197 s_strcat(Char *dst, Char *src)
198 {
199 short *sdst;
200
201 sdst = dst;
202 while (*dst++)
203 continue;
204 --dst;
205 while ((*dst++ = *src++) != '\0')
206 continue;
207 return (sdst);
208 }
209
210 #ifdef NOTUSED
211 Char *
212 s_strncat(Char *dst, Char *src, size_t n)
213 {
214 Char *sdst;
215
216 if (n == 0)
217 return (dst);
218
219 sdst = dst;
220
221 while (*dst++)
222 continue;
223 --dst;
224
225 do
226 if ((*dst++ = *src++) == '\0')
227 return(sdst);
228 while (--n != 0)
229 continue;
230
231 *dst = '\0';
232 return (sdst);
233 }
234
235 #endif
236
237 Char *
238 s_strchr(Char *str, int ch)
239 {
240 do
241 if (*str == ch)
242 return (str);
243 while (*str++);
244 return (NULL);
245 }
246
247 Char *
248 s_strrchr(Char *str, int ch)
249 {
250 Char *rstr;
251
252 rstr = NULL;
253 do
254 if (*str == ch)
255 rstr = str;
256 while (*str++);
257 return (rstr);
258 }
259
260 size_t
261 s_strlen(Char *str)
262 {
263 size_t n;
264
265 for (n = 0; *str++; n++)
266 continue;
267 return (n);
268 }
269
270 int
271 s_strcmp(Char *str1, Char *str2)
272 {
273 for (; *str1 && *str1 == *str2; str1++, str2++)
274 continue;
275 /*
276 * The following case analysis is necessary so that characters which look
277 * negative collate low against normal characters but high against the
278 * end-of-string NUL.
279 */
280 if (*str1 == '\0' && *str2 == '\0')
281 return (0);
282 else if (*str1 == '\0')
283 return (-1);
284 else if (*str2 == '\0')
285 return (1);
286 else
287 return (*str1 - *str2);
288 }
289
290 int
291 s_strncmp(Char *str1, Char *str2, size_t n)
292 {
293 if (n == 0)
294 return (0);
295 do {
296 if (*str1 != *str2) {
297 /*
298 * The following case analysis is necessary so that characters
299 * which look negative collate low against normal characters
300 * but high against the end-of-string NUL.
301 */
302 if (*str1 == '\0')
303 return (-1);
304 else if (*str2 == '\0')
305 return (1);
306 else
307 return (*str1 - *str2);
308 }
309 if (*str1 == '\0')
310 return(0);
311 str1++, str2++;
312 } while (--n != 0);
313 return(0);
314 }
315
316 Char *
317 s_strsave(Char *s)
318 {
319 Char *n, *p;
320
321 if (s == 0)
322 s = STRNULL;
323 for (p = s; *p++;)
324 continue;
325 n = p = (Char *)xmalloc((size_t)((p - s) * sizeof(Char)));
326 while ((*p++ = *s++) != '\0')
327 continue;
328 return (n);
329 }
330
331 Char *
332 s_strspl(Char *cp, Char *dp)
333 {
334 Char *ep, *p, *q;
335
336 if (!cp)
337 cp = STRNULL;
338 if (!dp)
339 dp = STRNULL;
340 for (p = cp; *p++;)
341 continue;
342 for (q = dp; *q++;)
343 continue;
344 ep = (Char *)xmalloc((size_t)(((p - cp) + (q - dp) - 1) * sizeof(Char)));
345 for (p = ep, q = cp; (*p++ = *q++) != '\0';)
346 continue;
347 for (p--, q = dp; (*p++ = *q++) != '\0';)
348 continue;
349 return (ep);
350 }
351
352 Char *
353 s_strend(Char *cp)
354 {
355 if (!cp)
356 return (cp);
357 while (*cp)
358 cp++;
359 return (cp);
360 }
361
362 Char *
363 s_strstr(Char *s, Char *t)
364 {
365 do {
366 Char *ss = s;
367 Char *tt = t;
368
369 do
370 if (*tt == '\0')
371 return (s);
372 while (*ss++ == *tt++);
373 } while (*s++ != '\0');
374 return (NULL);
375 }
376 #endif /* SHORT_STRINGS */
377
378 char *
379 short2qstr(Char *src)
380 {
381 static char *sdst = NULL;
382 static size_t dstsize = 0;
383 char *dst, *edst;
384
385 if (src == NULL)
386 return (NULL);
387
388 if (sdst == NULL) {
389 dstsize = MALLOC_INCR;
390 sdst = (char *)xmalloc((size_t)dstsize * sizeof(char));
391 }
392 dst = sdst;
393 edst = &dst[dstsize];
394 while (*src) {
395 if (*src & QUOTE) {
396 *dst++ = '\\';
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++ = (char) *src++;
406 if (dst == edst) {
407 dstsize += MALLOC_INCR;
408 sdst = (char *)xrealloc((ptr_t) sdst,
409 (size_t)dstsize * sizeof(char));
410 edst = &sdst[dstsize];
411 dst = &edst[-MALLOC_INCR];
412 }
413 }
414 *dst = 0;
415 return (sdst);
416 }
417
418 /*
419 * XXX: Should we worry about QUOTE'd chars?
420 */
421 char *
422 vis_str(Char *cp)
423 {
424 static char *sdst = NULL;
425 static size_t dstsize = 0;
426 Char *dp;
427 size_t n;
428
429 if (cp == NULL)
430 return (NULL);
431
432 for (dp = cp; *dp++;)
433 continue;
434 n = ((dp - cp) << 2) + 1; /* 4 times + NULL */
435 if (dstsize < n) {
436 sdst = (char *) (dstsize ?
437 xrealloc(sdst, (size_t)n * sizeof(char)) :
438 xmalloc((size_t)n * sizeof(char)));
439 dstsize = n;
440 }
441 /*
442 * XXX: When we are in AsciiOnly we want all characters >= 0200 to
443 * be encoded, but currently there is no way in vis to do that.
444 */
445 (void)strvis(sdst, short2str(cp), VIS_NOSLASH);
446 return (sdst);
447 }
448