1 /* $NetBSD: str.c,v 1.15 2013/07/16 17:47:43 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.15 2013/07/16 17:47:43 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((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