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