]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcsh/tc.str.c
This commit was generated by cvs2svn to compensate for changes in r158795,
[FreeBSD/FreeBSD.git] / contrib / tcsh / tc.str.c
1 /* $Header: /src/pub/tcsh/tc.str.c,v 3.19 2005/01/06 16:56:26 christos Exp $ */
2 /*
3  * tc.str.c: Short string package
4  *           This has been a lesson of how to write buggy code!
5  */
6 /*-
7  * Copyright (c) 1980, 1991 The Regents of the University of California.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 #include "sh.h"
35
36 #include <limits.h>
37
38 RCSID("$Id: tc.str.c,v 3.19 2005/01/06 16:56:26 christos Exp $")
39
40 #define MALLOC_INCR     128
41 #ifdef WIDE_STRINGS
42 #define MALLOC_SURPLUS  MB_LEN_MAX /* Space for one multibyte character */
43 #else
44 #define MALLOC_SURPLUS  0
45 #endif
46
47 #ifdef WIDE_STRINGS
48 size_t
49 one_mbtowc(wchar_t *pwc, const char *s, size_t n)
50 {
51     int len;
52
53     len = rt_mbtowc(pwc, s, n);
54     if (len == -1) {
55         mbtowc(NULL, NULL, 0);
56         *pwc = (unsigned char)*s | INVALID_BYTE;
57     }
58     if (len <= 0)
59         len = 1;
60     return len;
61 }
62
63 size_t
64 one_wctomb(char *s, wchar_t wchar)
65 {
66     int len;
67
68     if (wchar & INVALID_BYTE) {
69         s[0] = wchar & 0xFF;
70         len = 1;
71     } else {
72         len = wctomb(s, wchar);
73         if (len == -1)
74             s[0] = wchar;
75         if (len <= 0)
76             len = 1;
77     }
78     return len;
79 }
80 #endif
81      
82 #ifdef SHORT_STRINGS
83 int
84 rt_mbtowc(wchar_t *pwc, const char *s, size_t n)
85 {
86     int ret;
87     char back[MB_LEN_MAX];
88
89     ret = mbtowc(pwc, s, n);
90     if (ret > 0 && (wctomb(back, *pwc) != ret || memcmp(s, back, ret) != 0))
91         ret = -1;
92     return ret;
93 }
94
95 Char  **
96 blk2short(src)
97     char **src;
98 {
99     size_t     n;
100     Char **sdst, **dst;
101
102     /*
103      * Count
104      */
105     for (n = 0; src[n] != NULL; n++)
106         continue;
107     sdst = dst = (Char **) xmalloc((size_t) ((n + 1) * sizeof(Char *)));
108
109     for (; *src != NULL; src++)
110         *dst++ = SAVE(*src);
111     *dst = NULL;
112     return (sdst);
113 }
114
115 char  **
116 short2blk(src)
117     Char **src;
118 {
119     size_t     n;
120     char **sdst, **dst;
121
122     /*
123      * Count
124      */
125     for (n = 0; src[n] != NULL; n++)
126         continue;
127     sdst = dst = (char **) xmalloc((size_t) ((n + 1) * sizeof(char *)));
128
129     for (; *src != NULL; src++)
130         *dst++ = strsave(short2str(*src));
131     *dst = NULL;
132     return (sdst);
133 }
134
135 Char   *
136 str2short(src)
137     const char *src;
138 {
139     static Char *sdst;
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
151     dst = sdst;
152     edst = &dst[dstsize];
153     while ((unsigned char) *src) {
154         src += one_mbtowc(dst, src, MB_LEN_MAX);
155         dst++;
156         if (dst == edst) {
157             dstsize += MALLOC_INCR;
158             sdst = (Char *) xrealloc((ptr_t) sdst,
159                                      (size_t) (dstsize * sizeof(Char)));
160             edst = &sdst[dstsize];
161             dst = &edst[-MALLOC_INCR];
162         }
163     }
164     *dst = 0;
165     return (sdst);
166 }
167
168 char   *
169 short2str(src)
170     const Char *src;
171 {
172     static char *sdst = NULL;
173     static size_t dstsize = 0;
174     char *dst, *edst;
175
176     if (src == NULL)
177         return (NULL);
178
179     if (sdst == NULL) {
180         dstsize = MALLOC_INCR;
181         sdst = (char *) xmalloc((size_t) ((dstsize + MALLOC_SURPLUS)
182                                           * sizeof(char)));
183     }
184     dst = sdst;
185     edst = &dst[dstsize];
186     while (*src) {
187         dst += one_wctomb(dst, *src & CHAR);
188         src++;
189         if (dst >= edst) {
190             dstsize += MALLOC_INCR;
191             sdst = (char *) xrealloc((ptr_t) sdst,
192                                      (size_t) ((dstsize + MALLOC_SURPLUS)
193                                                * sizeof(char)));
194             edst = &sdst[dstsize];
195             dst = &edst[-MALLOC_INCR];
196         }
197     }
198     *dst = 0;
199     return (sdst);
200 }
201
202 #ifndef WIDE_STRINGS
203 Char   *
204 s_strcpy(dst, src)
205     Char *dst;
206     const Char *src;
207 {
208     Char *sdst;
209
210     sdst = dst;
211     while ((*dst++ = *src++) != '\0')
212         continue;
213     return (sdst);
214 }
215
216 Char   *
217 s_strncpy(dst, src, n)
218     Char *dst;
219     const Char *src;
220     size_t n;
221 {
222     Char *sdst;
223
224     if (n == 0)
225         return(dst);
226
227     sdst = dst;
228     do 
229         if ((*dst++ = *src++) == '\0') {
230             while (--n != 0)
231                 *dst++ = '\0';
232             return(sdst);
233         }
234     while (--n != 0);
235     return (sdst);
236 }
237
238 Char   *
239 s_strcat(dst, src)
240     Char *dst;
241     const Char *src;
242 {
243     Char *sdst;
244
245     sdst = dst;
246     while (*dst++)
247         continue;
248     --dst;
249     while ((*dst++ = *src++) != '\0')
250         continue;
251     return (sdst);
252 }
253
254 #ifdef NOTUSED
255 Char   *
256 s_strncat(dst, src, n)
257     Char *dst;
258     const Char *src;
259     size_t n;
260 {
261     Char *sdst;
262
263     if (n == 0) 
264         return (dst);
265
266     sdst = dst;
267
268     while (*dst++)
269         continue;
270     --dst;
271
272     do 
273         if ((*dst++ = *src++) == '\0')
274             return(sdst);
275     while (--n != 0)
276         continue;
277
278     *dst = '\0';
279     return (sdst);
280 }
281
282 #endif
283
284 Char   *
285 s_strchr(str, ch)
286     const Char *str;
287     int ch;
288 {
289     do
290         if (*str == ch)
291             return ((Char *)(intptr_t)str);
292     while (*str++);
293     return (NULL);
294 }
295
296 Char   *
297 s_strrchr(str, ch)
298     const Char *str;
299     int ch;
300 {
301     const Char *rstr;
302
303     rstr = NULL;
304     do
305         if (*str == ch)
306             rstr = str;
307     while (*str++);
308     return ((Char *)(intptr_t)rstr);
309 }
310
311 size_t
312 s_strlen(str)
313     const Char *str;
314 {
315     size_t n;
316
317     for (n = 0; *str++; n++)
318         continue;
319     return (n);
320 }
321
322 int
323 s_strcmp(str1, str2)
324     const Char *str1, *str2;
325 {
326     for (; *str1 && *str1 == *str2; str1++, str2++)
327         continue;
328     /*
329      * The following case analysis is necessary so that characters which look
330      * negative collate low against normal characters but high against the
331      * end-of-string NUL.
332      */
333     if (*str1 == '\0' && *str2 == '\0')
334         return (0);
335     else if (*str1 == '\0')
336         return (-1);
337     else if (*str2 == '\0')
338         return (1);
339     else
340         return (*str1 - *str2);
341 }
342
343 int
344 s_strncmp(str1, str2, n)
345     const Char *str1, *str2;
346     size_t n;
347 {
348     if (n == 0)
349         return (0);
350     do {
351         if (*str1 != *str2) {
352             /*
353              * The following case analysis is necessary so that characters 
354              * which look negative collate low against normal characters
355              * but high against the end-of-string NUL.
356              */
357             if (*str1 == '\0')
358                 return (-1);
359             else if (*str2 == '\0')
360                 return (1);
361             else
362                 return (*str1 - *str2);
363         }
364         if (*str1 == '\0')
365             return(0);
366         str1++, str2++;
367     } while (--n != 0);
368     return(0);
369 }
370 #endif /* not WIDE_STRINGS */
371
372 int
373 s_strcasecmp(str1, str2)
374     const Char *str1, *str2;
375 {
376 #ifdef WIDE_STRINGS
377     wchar_t l1 = 0, l2 = 0;
378     for (; *str1 && ((*str1 == *str2 && (l1 = l2 = 0) == 0) || 
379         (l1 = towlower(*str1)) == (l2 = towlower(*str2))); str1++, str2++)
380         continue;
381     
382 #else
383     unsigned char c1, c2, l1 = 0, l2 = 0;
384     for (; *str1 && ((*str1 == *str2 && (l1 = l2 = 0) == 0) || 
385         ((c1 = (unsigned char)*str1) == *str1 &&
386          (c2 = (unsigned char)*str2) == *str2 &&
387         (l1 = tolower(c1)) == (l2 = tolower(c2)))); str1++, str2++)
388         continue;
389 #endif
390     /*
391      * The following case analysis is necessary so that characters which look
392      * negative collate low against normal characters but high against the
393      * end-of-string NUL.
394      */
395     if (*str1 == '\0' && *str2 == '\0')
396         return (0);
397     else if (*str1 == '\0')
398         return (-1);
399     else if (*str2 == '\0')
400         return (1);
401     else if (l1 == l2)  /* They are zero when they are equal */
402         return (*str1 - *str2);
403     else
404         return (l1 - l2);
405 }
406
407 Char   *
408 s_strsave(s)
409     const Char *s;
410 {
411     Char   *n;
412     Char *p;
413
414     if (s == 0)
415         s = STRNULL;
416     for (p = (Char *)(intptr_t)s; *p++;)
417         continue;
418     n = p = (Char *) xmalloc((size_t) 
419                              ((((const Char *) p) - s) * sizeof(Char)));
420     while ((*p++ = *s++) != '\0')
421         continue;
422     return (n);
423 }
424
425 Char   *
426 s_strspl(cp, dp)
427     const Char   *cp, *dp;
428 {
429     Char   *ep;
430     Char *p, *q;
431
432     if (!cp)
433         cp = STRNULL;
434     if (!dp)
435         dp = STRNULL;
436     for (p = (Char *)(intptr_t) cp; *p++;)
437         continue;
438     for (q = (Char *)(intptr_t) dp; *q++;)
439         continue;
440     ep = (Char *) xmalloc((size_t)
441                           (((((const Char *) p) - cp) + 
442                             (((const Char *) q) - dp) - 1) * sizeof(Char)));
443     for (p = ep, q = (Char*)(intptr_t) cp; (*p++ = *q++) != '\0';)
444         continue;
445     for (p--, q = (Char *)(intptr_t) dp; (*p++ = *q++) != '\0';)
446         continue;
447     return (ep);
448 }
449
450 Char   *
451 s_strend(cp)
452     const Char *cp;
453 {
454     if (!cp)
455         return ((Char *)(intptr_t) cp);
456     while (*cp)
457         cp++;
458     return ((Char *)(intptr_t) cp);
459 }
460
461 Char   *
462 s_strstr(s, t)
463     const Char *s, *t;
464 {
465     do {
466         const Char *ss = s;
467         const Char *tt = t;
468
469         do
470             if (*tt == '\0')
471                 return ((Char *)(intptr_t) s);
472         while (*ss++ == *tt++);
473     } while (*s++ != '\0');
474     return (NULL);
475 }
476
477 #endif                          /* SHORT_STRINGS */
478
479 char   *
480 short2qstr(src)
481     const Char *src;
482 {
483     static char *sdst = NULL;
484     static size_t dstsize = 0;
485     char *dst, *edst;
486
487     if (src == NULL)
488         return (NULL);
489
490     if (sdst == NULL) {
491         dstsize = MALLOC_INCR;
492         sdst = (char *) xmalloc((size_t) ((dstsize + MALLOC_SURPLUS)
493                                           * sizeof(char)));
494     }
495     dst = sdst;
496     edst = &dst[dstsize];
497     while (*src) {
498         if (*src & QUOTE) {
499             *dst++ = '\\';
500             if (dst == edst) {
501                 dstsize += MALLOC_INCR;
502                 sdst = (char *) xrealloc((ptr_t) sdst,
503                                          (size_t) ((dstsize + MALLOC_SURPLUS)
504                                                    * sizeof(char)));
505                 edst = &sdst[dstsize];
506                 dst = &edst[-MALLOC_INCR];
507             }
508         }
509         dst += one_wctomb(dst, *src & CHAR);
510         src++;
511         if (dst >= edst) {
512             dstsize += MALLOC_INCR;
513             sdst = (char *) xrealloc((ptr_t) sdst,
514                                      (size_t) ((dstsize + MALLOC_SURPLUS)
515                                                * sizeof(char)));
516             edst = &sdst[dstsize];
517             dst = &edst[-MALLOC_INCR];
518         }
519     }
520     *dst = 0;
521     return (sdst);
522 }