1 /* $NetBSD: str.c,v 1.16 2019/01/05 16:54:00 christos 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.16 2019/01/05 16:54:00 christos 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(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 = xmalloc((size_t)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 = xrealloc(sdst, (size_t)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 = xmalloc((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 = xmalloc((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 = xmalloc((size_t)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 = xrealloc(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 = xrealloc(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 xrealloc(sdst, (size_t)n * sizeof(*sdst)) : 428 xmalloc((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