1 /* $Header: /src/pub/tcsh/tc.str.c,v 3.19 2005/01/06 16:56:26 christos Exp $ */ 2 /* 3 * tc.str.c: Short string package 4 * This has been a lesson of how to write buggy code! 5 */ 6 /*- 7 * Copyright (c) 1980, 1991 The Regents of the University of California. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 #include "sh.h" 35 36 #include <limits.h> 37 38 RCSID("$Id: tc.str.c,v 3.19 2005/01/06 16:56:26 christos Exp $") 39 40 #define MALLOC_INCR 128 41 #ifdef WIDE_STRINGS 42 #define MALLOC_SURPLUS MB_LEN_MAX /* Space for one multibyte character */ 43 #else 44 #define MALLOC_SURPLUS 0 45 #endif 46 47 #ifdef WIDE_STRINGS 48 size_t 49 one_mbtowc(wchar_t *pwc, const char *s, size_t n) 50 { 51 int len; 52 53 len = rt_mbtowc(pwc, s, n); 54 if (len == -1) { 55 mbtowc(NULL, NULL, 0); 56 *pwc = (unsigned char)*s | INVALID_BYTE; 57 } 58 if (len <= 0) 59 len = 1; 60 return len; 61 } 62 63 size_t 64 one_wctomb(char *s, wchar_t wchar) 65 { 66 int len; 67 68 if (wchar & INVALID_BYTE) { 69 s[0] = wchar & 0xFF; 70 len = 1; 71 } else { 72 len = wctomb(s, wchar); 73 if (len == -1) 74 s[0] = wchar; 75 if (len <= 0) 76 len = 1; 77 } 78 return len; 79 } 80 #endif 81 82 #ifdef SHORT_STRINGS 83 int 84 rt_mbtowc(wchar_t *pwc, const char *s, size_t n) 85 { 86 int ret; 87 char back[MB_LEN_MAX]; 88 89 ret = mbtowc(pwc, s, n); 90 if (ret > 0 && (wctomb(back, *pwc) != ret || memcmp(s, back, ret) != 0)) 91 ret = -1; 92 return ret; 93 } 94 95 Char ** 96 blk2short(src) 97 char **src; 98 { 99 size_t n; 100 Char **sdst, **dst; 101 102 /* 103 * Count 104 */ 105 for (n = 0; src[n] != NULL; n++) 106 continue; 107 sdst = dst = (Char **) xmalloc((size_t) ((n + 1) * sizeof(Char *))); 108 109 for (; *src != NULL; src++) 110 *dst++ = SAVE(*src); 111 *dst = NULL; 112 return (sdst); 113 } 114 115 char ** 116 short2blk(src) 117 Char **src; 118 { 119 size_t n; 120 char **sdst, **dst; 121 122 /* 123 * Count 124 */ 125 for (n = 0; src[n] != NULL; n++) 126 continue; 127 sdst = dst = (char **) xmalloc((size_t) ((n + 1) * sizeof(char *))); 128 129 for (; *src != NULL; src++) 130 *dst++ = strsave(short2str(*src)); 131 *dst = NULL; 132 return (sdst); 133 } 134 135 Char * 136 str2short(src) 137 const char *src; 138 { 139 static Char *sdst; 140 static size_t dstsize = 0; 141 Char *dst, *edst; 142 143 if (src == NULL) 144 return (NULL); 145 146 if (sdst == (NULL)) { 147 dstsize = MALLOC_INCR; 148 sdst = (Char *) xmalloc((size_t) (dstsize * sizeof(Char))); 149 } 150 151 dst = sdst; 152 edst = &dst[dstsize]; 153 while ((unsigned char) *src) { 154 src += one_mbtowc(dst, src, MB_LEN_MAX); 155 dst++; 156 if (dst == edst) { 157 dstsize += MALLOC_INCR; 158 sdst = (Char *) xrealloc((ptr_t) sdst, 159 (size_t) (dstsize * sizeof(Char))); 160 edst = &sdst[dstsize]; 161 dst = &edst[-MALLOC_INCR]; 162 } 163 } 164 *dst = 0; 165 return (sdst); 166 } 167 168 char * 169 short2str(src) 170 const Char *src; 171 { 172 static char *sdst = NULL; 173 static size_t dstsize = 0; 174 char *dst, *edst; 175 176 if (src == NULL) 177 return (NULL); 178 179 if (sdst == NULL) { 180 dstsize = MALLOC_INCR; 181 sdst = (char *) xmalloc((size_t) ((dstsize + MALLOC_SURPLUS) 182 * sizeof(char))); 183 } 184 dst = sdst; 185 edst = &dst[dstsize]; 186 while (*src) { 187 dst += one_wctomb(dst, *src & CHAR); 188 src++; 189 if (dst >= edst) { 190 dstsize += MALLOC_INCR; 191 sdst = (char *) xrealloc((ptr_t) sdst, 192 (size_t) ((dstsize + MALLOC_SURPLUS) 193 * sizeof(char))); 194 edst = &sdst[dstsize]; 195 dst = &edst[-MALLOC_INCR]; 196 } 197 } 198 *dst = 0; 199 return (sdst); 200 } 201 202 #ifndef WIDE_STRINGS 203 Char * 204 s_strcpy(dst, src) 205 Char *dst; 206 const Char *src; 207 { 208 Char *sdst; 209 210 sdst = dst; 211 while ((*dst++ = *src++) != '\0') 212 continue; 213 return (sdst); 214 } 215 216 Char * 217 s_strncpy(dst, src, n) 218 Char *dst; 219 const Char *src; 220 size_t n; 221 { 222 Char *sdst; 223 224 if (n == 0) 225 return(dst); 226 227 sdst = dst; 228 do 229 if ((*dst++ = *src++) == '\0') { 230 while (--n != 0) 231 *dst++ = '\0'; 232 return(sdst); 233 } 234 while (--n != 0); 235 return (sdst); 236 } 237 238 Char * 239 s_strcat(dst, src) 240 Char *dst; 241 const Char *src; 242 { 243 Char *sdst; 244 245 sdst = dst; 246 while (*dst++) 247 continue; 248 --dst; 249 while ((*dst++ = *src++) != '\0') 250 continue; 251 return (sdst); 252 } 253 254 #ifdef NOTUSED 255 Char * 256 s_strncat(dst, src, n) 257 Char *dst; 258 const Char *src; 259 size_t n; 260 { 261 Char *sdst; 262 263 if (n == 0) 264 return (dst); 265 266 sdst = dst; 267 268 while (*dst++) 269 continue; 270 --dst; 271 272 do 273 if ((*dst++ = *src++) == '\0') 274 return(sdst); 275 while (--n != 0) 276 continue; 277 278 *dst = '\0'; 279 return (sdst); 280 } 281 282 #endif 283 284 Char * 285 s_strchr(str, ch) 286 const Char *str; 287 int ch; 288 { 289 do 290 if (*str == ch) 291 return ((Char *)(intptr_t)str); 292 while (*str++); 293 return (NULL); 294 } 295 296 Char * 297 s_strrchr(str, ch) 298 const Char *str; 299 int ch; 300 { 301 const Char *rstr; 302 303 rstr = NULL; 304 do 305 if (*str == ch) 306 rstr = str; 307 while (*str++); 308 return ((Char *)(intptr_t)rstr); 309 } 310 311 size_t 312 s_strlen(str) 313 const Char *str; 314 { 315 size_t n; 316 317 for (n = 0; *str++; n++) 318 continue; 319 return (n); 320 } 321 322 int 323 s_strcmp(str1, str2) 324 const Char *str1, *str2; 325 { 326 for (; *str1 && *str1 == *str2; str1++, str2++) 327 continue; 328 /* 329 * The following case analysis is necessary so that characters which look 330 * negative collate low against normal characters but high against the 331 * end-of-string NUL. 332 */ 333 if (*str1 == '\0' && *str2 == '\0') 334 return (0); 335 else if (*str1 == '\0') 336 return (-1); 337 else if (*str2 == '\0') 338 return (1); 339 else 340 return (*str1 - *str2); 341 } 342 343 int 344 s_strncmp(str1, str2, n) 345 const Char *str1, *str2; 346 size_t n; 347 { 348 if (n == 0) 349 return (0); 350 do { 351 if (*str1 != *str2) { 352 /* 353 * The following case analysis is necessary so that characters 354 * which look negative collate low against normal characters 355 * but high against the end-of-string NUL. 356 */ 357 if (*str1 == '\0') 358 return (-1); 359 else if (*str2 == '\0') 360 return (1); 361 else 362 return (*str1 - *str2); 363 } 364 if (*str1 == '\0') 365 return(0); 366 str1++, str2++; 367 } while (--n != 0); 368 return(0); 369 } 370 #endif /* not WIDE_STRINGS */ 371 372 int 373 s_strcasecmp(str1, str2) 374 const Char *str1, *str2; 375 { 376 #ifdef WIDE_STRINGS 377 wchar_t l1 = 0, l2 = 0; 378 for (; *str1 && ((*str1 == *str2 && (l1 = l2 = 0) == 0) || 379 (l1 = towlower(*str1)) == (l2 = towlower(*str2))); str1++, str2++) 380 continue; 381 382 #else 383 unsigned char c1, c2, l1 = 0, l2 = 0; 384 for (; *str1 && ((*str1 == *str2 && (l1 = l2 = 0) == 0) || 385 ((c1 = (unsigned char)*str1) == *str1 && 386 (c2 = (unsigned char)*str2) == *str2 && 387 (l1 = tolower(c1)) == (l2 = tolower(c2)))); str1++, str2++) 388 continue; 389 #endif 390 /* 391 * The following case analysis is necessary so that characters which look 392 * negative collate low against normal characters but high against the 393 * end-of-string NUL. 394 */ 395 if (*str1 == '\0' && *str2 == '\0') 396 return (0); 397 else if (*str1 == '\0') 398 return (-1); 399 else if (*str2 == '\0') 400 return (1); 401 else if (l1 == l2) /* They are zero when they are equal */ 402 return (*str1 - *str2); 403 else 404 return (l1 - l2); 405 } 406 407 Char * 408 s_strsave(s) 409 const Char *s; 410 { 411 Char *n; 412 Char *p; 413 414 if (s == 0) 415 s = STRNULL; 416 for (p = (Char *)(intptr_t)s; *p++;) 417 continue; 418 n = p = (Char *) xmalloc((size_t) 419 ((((const Char *) p) - s) * sizeof(Char))); 420 while ((*p++ = *s++) != '\0') 421 continue; 422 return (n); 423 } 424 425 Char * 426 s_strspl(cp, dp) 427 const Char *cp, *dp; 428 { 429 Char *ep; 430 Char *p, *q; 431 432 if (!cp) 433 cp = STRNULL; 434 if (!dp) 435 dp = STRNULL; 436 for (p = (Char *)(intptr_t) cp; *p++;) 437 continue; 438 for (q = (Char *)(intptr_t) dp; *q++;) 439 continue; 440 ep = (Char *) xmalloc((size_t) 441 (((((const Char *) p) - cp) + 442 (((const Char *) q) - dp) - 1) * sizeof(Char))); 443 for (p = ep, q = (Char*)(intptr_t) cp; (*p++ = *q++) != '\0';) 444 continue; 445 for (p--, q = (Char *)(intptr_t) dp; (*p++ = *q++) != '\0';) 446 continue; 447 return (ep); 448 } 449 450 Char * 451 s_strend(cp) 452 const Char *cp; 453 { 454 if (!cp) 455 return ((Char *)(intptr_t) cp); 456 while (*cp) 457 cp++; 458 return ((Char *)(intptr_t) cp); 459 } 460 461 Char * 462 s_strstr(s, t) 463 const Char *s, *t; 464 { 465 do { 466 const Char *ss = s; 467 const Char *tt = t; 468 469 do 470 if (*tt == '\0') 471 return ((Char *)(intptr_t) s); 472 while (*ss++ == *tt++); 473 } while (*s++ != '\0'); 474 return (NULL); 475 } 476 477 #endif /* SHORT_STRINGS */ 478 479 char * 480 short2qstr(src) 481 const Char *src; 482 { 483 static char *sdst = NULL; 484 static size_t dstsize = 0; 485 char *dst, *edst; 486 487 if (src == NULL) 488 return (NULL); 489 490 if (sdst == NULL) { 491 dstsize = MALLOC_INCR; 492 sdst = (char *) xmalloc((size_t) ((dstsize + MALLOC_SURPLUS) 493 * sizeof(char))); 494 } 495 dst = sdst; 496 edst = &dst[dstsize]; 497 while (*src) { 498 if (*src & QUOTE) { 499 *dst++ = '\\'; 500 if (dst == edst) { 501 dstsize += MALLOC_INCR; 502 sdst = (char *) xrealloc((ptr_t) sdst, 503 (size_t) ((dstsize + MALLOC_SURPLUS) 504 * sizeof(char))); 505 edst = &sdst[dstsize]; 506 dst = &edst[-MALLOC_INCR]; 507 } 508 } 509 dst += one_wctomb(dst, *src & CHAR); 510 src++; 511 if (dst >= edst) { 512 dstsize += MALLOC_INCR; 513 sdst = (char *) xrealloc((ptr_t) sdst, 514 (size_t) ((dstsize + MALLOC_SURPLUS) 515 * sizeof(char))); 516 edst = &sdst[dstsize]; 517 dst = &edst[-MALLOC_INCR]; 518 } 519 } 520 *dst = 0; 521 return (sdst); 522 } 523