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