Home | History | Annotate | Line # | Download | only in csh
      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 **
     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 **
     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 *
     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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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
    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
    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
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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