1 /* $OpenBSD: str.c,v 1.19 2015/10/26 16:31:09 naddy 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 Char ** 48 blk2short(char **src) 49 { 50 size_t n; 51 Char **sdst, **dst; 52 53 /* 54 * Count 55 */ 56 for (n = 0; src[n] != NULL; n++) 57 continue; 58 sdst = dst = xreallocarray(NULL, n + 1, sizeof(Char *)); 59 60 for (; *src != NULL; src++) 61 *dst++ = SAVE(*src); 62 *dst = NULL; 63 return (sdst); 64 } 65 66 char ** 67 short2blk(Char **src) 68 { 69 size_t n; 70 char **sdst, **dst; 71 72 /* 73 * Count 74 */ 75 for (n = 0; src[n] != NULL; n++) 76 continue; 77 sdst = dst = xreallocarray(NULL, n + 1, sizeof(char *)); 78 79 for (; *src != NULL; src++) 80 *dst++ = strsave(short2str(*src)); 81 *dst = NULL; 82 return (sdst); 83 } 84 85 Char * 86 str2short(char *src) 87 { 88 static Char *sdst; 89 static size_t dstsize = 0; 90 Char *dst, *edst; 91 92 if (src == NULL) 93 return (NULL); 94 95 if (sdst == (NULL)) { 96 dstsize = MALLOC_INCR; 97 sdst = xreallocarray(NULL, dstsize, sizeof(Char)); 98 } 99 100 dst = sdst; 101 edst = &dst[dstsize]; 102 while (*src) { 103 *dst++ = (Char) ((unsigned char) *src++); 104 if (dst == edst) { 105 dstsize += MALLOC_INCR; 106 sdst = xreallocarray(sdst, dstsize, sizeof(Char)); 107 edst = &sdst[dstsize]; 108 dst = &edst[-MALLOC_INCR]; 109 } 110 } 111 *dst = 0; 112 return (sdst); 113 } 114 115 char * 116 short2str(Char *src) 117 { 118 static char *sdst = NULL; 119 static size_t dstsize = 0; 120 char *dst, *edst; 121 122 if (src == NULL) 123 return (NULL); 124 125 if (sdst == NULL) { 126 dstsize = MALLOC_INCR; 127 sdst = xreallocarray(NULL, dstsize, sizeof(char)); 128 } 129 dst = sdst; 130 edst = &dst[dstsize]; 131 while (*src) { 132 *dst++ = (char) *src++; 133 if (dst == edst) { 134 dstsize += MALLOC_INCR; 135 sdst = xreallocarray(sdst, dstsize, sizeof(char)); 136 edst = &sdst[dstsize]; 137 dst = &edst[-MALLOC_INCR]; 138 } 139 } 140 *dst = 0; 141 return (sdst); 142 } 143 144 size_t 145 Strlcpy(Char *dst, const Char *src, size_t siz) 146 { 147 Char *d = dst; 148 const Char *s = src; 149 size_t n = siz; 150 151 /* Copy as many bytes as will fit */ 152 if (n != 0 && --n != 0) { 153 do { 154 if ((*d++ = *s++) == 0) 155 break; 156 } while (--n != 0); 157 } 158 159 /* Not enough room in dst, add NUL and traverse rest of src */ 160 if (n == 0) { 161 if (siz != 0) 162 *d = '\0'; /* NUL-terminate dst */ 163 while (*s++) 164 ; 165 } 166 167 return(s - src - 1); /* count does not include NUL */ 168 } 169 170 size_t 171 Strlcat(Char *dst, const Char *src, size_t siz) 172 { 173 Char *d = dst; 174 const Char *s = src; 175 size_t n = siz; 176 size_t dlen; 177 178 /* Find the end of dst and adjust bytes left but don't go past end */ 179 while (n-- != 0 && *d != '\0') 180 d++; 181 dlen = d - dst; 182 n = siz - dlen; 183 184 if (n == 0) 185 return(dlen + Strlen((Char *)s)); 186 while (*s != '\0') { 187 if (n != 1) { 188 *d++ = *s; 189 n--; 190 } 191 s++; 192 } 193 *d = '\0'; 194 195 return(dlen + (s - src)); /* count does not include NUL */ 196 } 197 198 Char * 199 Strchr(Char *str, int ch) 200 { 201 do 202 if (*str == ch) 203 return (str); 204 while (*str++) 205 ; 206 return (NULL); 207 } 208 209 Char * 210 Strrchr(Char *str, int ch) 211 { 212 Char *rstr; 213 214 rstr = NULL; 215 do 216 if (*str == ch) 217 rstr = str; 218 while (*str++) 219 ; 220 return (rstr); 221 } 222 223 size_t 224 Strlen(Char *str) 225 { 226 size_t n; 227 228 for (n = 0; *str++; n++) 229 continue; 230 return (n); 231 } 232 233 int 234 Strcmp(Char *str1, Char *str2) 235 { 236 for (; *str1 && *str1 == *str2; str1++, str2++) 237 continue; 238 /* 239 * The following case analysis is necessary so that characters which look 240 * negative collate low against normal characters but high against the 241 * end-of-string NUL. 242 */ 243 if (*str1 == '\0' && *str2 == '\0') 244 return (0); 245 else if (*str1 == '\0') 246 return (-1); 247 else if (*str2 == '\0') 248 return (1); 249 else 250 return (*str1 - *str2); 251 } 252 253 int 254 Strncmp(Char *str1, Char *str2, size_t n) 255 { 256 if (n == 0) 257 return (0); 258 do { 259 if (*str1 != *str2) { 260 /* 261 * The following case analysis is necessary so that characters 262 * which look negative collate low against normal characters 263 * but high against the end-of-string NUL. 264 */ 265 if (*str1 == '\0') 266 return (-1); 267 else if (*str2 == '\0') 268 return (1); 269 else 270 return (*str1 - *str2); 271 break; 272 } 273 if (*str1 == '\0') 274 return(0); 275 str1++, str2++; 276 } while (--n != 0); 277 return(0); 278 } 279 280 Char * 281 Strsave(Char *s) 282 { 283 Char *n; 284 Char *p; 285 286 if (s == 0) 287 s = STRNULL; 288 for (p = s; *p++;) 289 continue; 290 n = p = xreallocarray(NULL, p - s, sizeof(Char)); 291 while ((*p++ = *s++) != '\0') 292 continue; 293 return (n); 294 } 295 296 Char * 297 Strspl(Char *cp, Char *dp) 298 { 299 Char *ep; 300 Char *p, *q; 301 302 if (!cp) 303 cp = STRNULL; 304 if (!dp) 305 dp = STRNULL; 306 for (p = cp; *p++;) 307 continue; 308 for (q = dp; *q++;) 309 continue; 310 ep = xreallocarray(NULL, ((p - cp) + (q - dp) - 1), sizeof(Char)); 311 for (p = ep, q = cp; (*p++ = *q++) != '\0';) 312 continue; 313 for (p--, q = dp; (*p++ = *q++) != '\0';) 314 continue; 315 return (ep); 316 } 317 318 Char * 319 Strend(Char *cp) 320 { 321 if (!cp) 322 return (cp); 323 while (*cp) 324 cp++; 325 return (cp); 326 } 327 328 Char * 329 Strstr(Char *s, Char *t) 330 { 331 do { 332 Char *ss = s; 333 Char *tt = t; 334 335 do 336 if (*tt == '\0') 337 return (s); 338 while (*ss++ == *tt++); 339 } while (*s++ != '\0'); 340 return (NULL); 341 } 342 343 char * 344 short2qstr(Char *src) 345 { 346 static char *sdst = NULL; 347 static size_t dstsize = 0; 348 char *dst, *edst; 349 350 if (src == NULL) 351 return (NULL); 352 353 if (sdst == NULL) { 354 dstsize = MALLOC_INCR; 355 sdst = xreallocarray(NULL, dstsize, sizeof(char)); 356 } 357 dst = sdst; 358 edst = &dst[dstsize]; 359 while (*src) { 360 if (*src & QUOTE) { 361 *dst++ = '\\'; 362 if (dst == edst) { 363 dstsize += MALLOC_INCR; 364 sdst = xreallocarray(sdst, dstsize, sizeof(char)); 365 edst = &sdst[dstsize]; 366 dst = &edst[-MALLOC_INCR]; 367 } 368 } 369 *dst++ = (char) *src++; 370 if (dst == edst) { 371 dstsize += MALLOC_INCR; 372 sdst = xreallocarray(sdst, dstsize, sizeof(char)); 373 edst = &sdst[dstsize]; 374 dst = &edst[-MALLOC_INCR]; 375 } 376 } 377 *dst = 0; 378 return (sdst); 379 } 380 381 /* 382 * XXX: Should we worry about QUOTE'd chars? 383 */ 384 char * 385 vis_str(Char *cp) 386 { 387 static char *sdst = NULL; 388 static size_t dstsize = 0; 389 size_t n; 390 Char *dp; 391 392 if (cp == NULL) 393 return (NULL); 394 395 for (dp = cp; *dp++;) 396 continue; 397 n = ((dp - cp) << 2) + 1; /* 4 times + NUL */ 398 if (dstsize < n) { 399 sdst = xreallocarray(sdst, n, sizeof(char)); 400 dstsize = n; 401 } 402 (void) strnvis(sdst, short2str(cp), dstsize, VIS_NOSLASH); 403 return (sdst); 404 } 405 406