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