1 /* $NetBSD: str.c,v 1.12 2002/05/25 23:29:17 wiz 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. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include <sys/cdefs.h> 37 #ifndef lint 38 #if 0 39 static char sccsid[] = "@(#)str.c 8.1 (Berkeley) 5/31/93"; 40 #else 41 __RCSID("$NetBSD: str.c,v 1.12 2002/05/25 23:29:17 wiz Exp $"); 42 #endif 43 #endif /* not lint */ 44 45 #define MALLOC_INCR 128 46 47 /* 48 * tc.str.c: Short string package 49 * This has been a lesson of how to write buggy code! 50 */ 51 52 #include <sys/types.h> 53 54 #include <stdarg.h> 55 #include <vis.h> 56 57 #include "csh.h" 58 #include "extern.h" 59 60 #ifdef SHORT_STRINGS 61 62 Char ** 63 blk2short(char **src) 64 { 65 Char **dst, **sdst; 66 size_t n; 67 68 /* 69 * Count 70 */ 71 for (n = 0; src[n] != NULL; n++) 72 continue; 73 sdst = dst = (Char **)xmalloc((size_t)((n + 1) * sizeof(Char *))); 74 75 for (; *src != NULL; src++) 76 *dst++ = SAVE(*src); 77 *dst = NULL; 78 return (sdst); 79 } 80 81 char ** 82 short2blk(Char **src) 83 { 84 char **dst, **sdst; 85 size_t n; 86 87 /* 88 * Count 89 */ 90 for (n = 0; src[n] != NULL; n++) 91 continue; 92 sdst = dst = (char **)xmalloc((size_t)((n + 1) * sizeof(char *))); 93 94 for (; *src != NULL; src++) 95 *dst++ = strsave(short2str(*src)); 96 *dst = NULL; 97 return (sdst); 98 } 99 100 Char * 101 str2short(const char *src) 102 { 103 static Char *sdst; 104 Char *dst, *edst; 105 static size_t dstsize = 0; 106 107 if (src == NULL) 108 return (NULL); 109 110 if (sdst == (NULL)) { 111 dstsize = MALLOC_INCR; 112 sdst = (Char *)xmalloc((size_t)dstsize * sizeof(Char)); 113 } 114 115 dst = sdst; 116 edst = &dst[dstsize]; 117 while (*src) { 118 *dst++ = (Char) ((unsigned char) *src++); 119 if (dst == edst) { 120 dstsize += MALLOC_INCR; 121 sdst = (Char *)xrealloc((ptr_t)sdst, 122 (size_t)dstsize * sizeof(Char)); 123 edst = &sdst[dstsize]; 124 dst = &edst[-MALLOC_INCR]; 125 } 126 } 127 *dst = 0; 128 return (sdst); 129 } 130 131 char * 132 short2str(Char *src) 133 { 134 static char *sdst = NULL; 135 static size_t dstsize = 0; 136 char *dst, *edst; 137 138 if (src == NULL) 139 return (NULL); 140 141 if (sdst == NULL) { 142 dstsize = MALLOC_INCR; 143 sdst = (char *)xmalloc((size_t)dstsize * sizeof(char)); 144 } 145 dst = sdst; 146 edst = &dst[dstsize]; 147 while (*src) { 148 *dst++ = (char) *src++; 149 if (dst == edst) { 150 dstsize += MALLOC_INCR; 151 sdst = (char *)xrealloc((ptr_t)sdst, 152 (size_t)dstsize * sizeof(char)); 153 edst = &sdst[dstsize]; 154 dst = &edst[-MALLOC_INCR]; 155 } 156 } 157 *dst = 0; 158 return (sdst); 159 } 160 161 Char * 162 s_strcpy(Char *dst, Char *src) 163 { 164 Char *sdst; 165 166 sdst = dst; 167 while ((*dst++ = *src++) != '\0') 168 continue; 169 return (sdst); 170 } 171 172 Char * 173 s_strncpy(Char *dst, Char *src, size_t n) 174 { 175 Char *sdst; 176 177 if (n == 0) 178 return(dst); 179 180 sdst = dst; 181 do 182 if ((*dst++ = *src++) == '\0') { 183 while (--n != 0) 184 *dst++ = '\0'; 185 return(sdst); 186 } 187 while (--n != 0); 188 return (sdst); 189 } 190 191 Char * 192 s_strcat(Char *dst, Char *src) 193 { 194 short *sdst; 195 196 sdst = dst; 197 while (*dst++) 198 continue; 199 --dst; 200 while ((*dst++ = *src++) != '\0') 201 continue; 202 return (sdst); 203 } 204 205 #ifdef NOTUSED 206 Char * 207 s_strncat(Char *dst, Char *src, size_t n) 208 { 209 Char *sdst; 210 211 if (n == 0) 212 return (dst); 213 214 sdst = dst; 215 216 while (*dst++) 217 continue; 218 --dst; 219 220 do 221 if ((*dst++ = *src++) == '\0') 222 return(sdst); 223 while (--n != 0) 224 continue; 225 226 *dst = '\0'; 227 return (sdst); 228 } 229 230 #endif 231 232 Char * 233 s_strchr(Char *str, int ch) 234 { 235 do 236 if (*str == ch) 237 return (str); 238 while (*str++); 239 return (NULL); 240 } 241 242 Char * 243 s_strrchr(Char *str, int ch) 244 { 245 Char *rstr; 246 247 rstr = NULL; 248 do 249 if (*str == ch) 250 rstr = str; 251 while (*str++); 252 return (rstr); 253 } 254 255 size_t 256 s_strlen(Char *str) 257 { 258 size_t n; 259 260 for (n = 0; *str++; n++) 261 continue; 262 return (n); 263 } 264 265 int 266 s_strcmp(Char *str1, Char *str2) 267 { 268 for (; *str1 && *str1 == *str2; str1++, str2++) 269 continue; 270 /* 271 * The following case analysis is necessary so that characters which look 272 * negative collate low against normal characters but high against the 273 * end-of-string NUL. 274 */ 275 if (*str1 == '\0' && *str2 == '\0') 276 return (0); 277 else if (*str1 == '\0') 278 return (-1); 279 else if (*str2 == '\0') 280 return (1); 281 else 282 return (*str1 - *str2); 283 } 284 285 int 286 s_strncmp(Char *str1, Char *str2, size_t n) 287 { 288 if (n == 0) 289 return (0); 290 do { 291 if (*str1 != *str2) { 292 /* 293 * The following case analysis is necessary so that characters 294 * which look negative collate low against normal characters 295 * but high against the end-of-string NUL. 296 */ 297 if (*str1 == '\0') 298 return (-1); 299 else if (*str2 == '\0') 300 return (1); 301 else 302 return (*str1 - *str2); 303 } 304 if (*str1 == '\0') 305 return(0); 306 str1++, str2++; 307 } while (--n != 0); 308 return(0); 309 } 310 311 Char * 312 s_strsave(Char *s) 313 { 314 Char *n, *p; 315 316 if (s == 0) 317 s = STRNULL; 318 for (p = s; *p++;) 319 continue; 320 n = p = (Char *)xmalloc((size_t)((p - s) * sizeof(Char))); 321 while ((*p++ = *s++) != '\0') 322 continue; 323 return (n); 324 } 325 326 Char * 327 s_strspl(Char *cp, Char *dp) 328 { 329 Char *ep, *p, *q; 330 331 if (!cp) 332 cp = STRNULL; 333 if (!dp) 334 dp = STRNULL; 335 for (p = cp; *p++;) 336 continue; 337 for (q = dp; *q++;) 338 continue; 339 ep = (Char *)xmalloc((size_t)(((p - cp) + (q - dp) - 1) * sizeof(Char))); 340 for (p = ep, q = cp; (*p++ = *q++) != '\0';) 341 continue; 342 for (p--, q = dp; (*p++ = *q++) != '\0';) 343 continue; 344 return (ep); 345 } 346 347 Char * 348 s_strend(Char *cp) 349 { 350 if (!cp) 351 return (cp); 352 while (*cp) 353 cp++; 354 return (cp); 355 } 356 357 Char * 358 s_strstr(Char *s, Char *t) 359 { 360 do { 361 Char *ss = s; 362 Char *tt = t; 363 364 do 365 if (*tt == '\0') 366 return (s); 367 while (*ss++ == *tt++); 368 } while (*s++ != '\0'); 369 return (NULL); 370 } 371 #endif /* SHORT_STRINGS */ 372 373 char * 374 short2qstr(Char *src) 375 { 376 static char *sdst = NULL; 377 static size_t dstsize = 0; 378 char *dst, *edst; 379 380 if (src == NULL) 381 return (NULL); 382 383 if (sdst == NULL) { 384 dstsize = MALLOC_INCR; 385 sdst = (char *)xmalloc((size_t)dstsize * sizeof(char)); 386 } 387 dst = sdst; 388 edst = &dst[dstsize]; 389 while (*src) { 390 if (*src & QUOTE) { 391 *dst++ = '\\'; 392 if (dst == edst) { 393 dstsize += MALLOC_INCR; 394 sdst = (char *)xrealloc((ptr_t) sdst, 395 (size_t)dstsize * sizeof(char)); 396 edst = &sdst[dstsize]; 397 dst = &edst[-MALLOC_INCR]; 398 } 399 } 400 *dst++ = (char) *src++; 401 if (dst == edst) { 402 dstsize += MALLOC_INCR; 403 sdst = (char *)xrealloc((ptr_t) sdst, 404 (size_t)dstsize * sizeof(char)); 405 edst = &sdst[dstsize]; 406 dst = &edst[-MALLOC_INCR]; 407 } 408 } 409 *dst = 0; 410 return (sdst); 411 } 412 413 /* 414 * XXX: Should we worry about QUOTE'd chars? 415 */ 416 char * 417 vis_str(Char *cp) 418 { 419 static char *sdst = NULL; 420 static size_t dstsize = 0; 421 Char *dp; 422 size_t n; 423 424 if (cp == NULL) 425 return (NULL); 426 427 for (dp = cp; *dp++;) 428 continue; 429 n = ((dp - cp) << 2) + 1; /* 4 times + NULL */ 430 if (dstsize < n) { 431 sdst = (char *) (dstsize ? 432 xrealloc(sdst, (size_t)n * sizeof(char)) : 433 xmalloc((size_t)n * sizeof(char))); 434 dstsize = n; 435 } 436 /* 437 * XXX: When we are in AsciiOnly we want all characters >= 0200 to 438 * be encoded, but currently there is no way in vis to do that. 439 */ 440 (void)strvis(sdst, short2str(cp), VIS_NOSLASH); 441 return (sdst); 442 } 443