1fc17b349SJuli Mallett /* $xMach: strnsubst.c,v 1.3 2002/02/23 02:10:24 jmallett Exp $ */ 2fc17b349SJuli Mallett 3fc17b349SJuli Mallett /* 4fc17b349SJuli Mallett * Copyright (c) 2002 J. Mallett. All rights reserved. 5fc17b349SJuli Mallett * You may do whatever you want with this file as long as 6fc17b349SJuli Mallett * the above copyright and this notice remain intact, along 7fc17b349SJuli Mallett * with the following statement: 8fc17b349SJuli Mallett * For the man who taught me vi, and who got too old, too young. 9fc17b349SJuli Mallett */ 10fc17b349SJuli Mallett 11fc17b349SJuli Mallett #include <sys/cdefs.h> 12fc17b349SJuli Mallett __FBSDID("$FreeBSD$"); 13fc17b349SJuli Mallett 14fc17b349SJuli Mallett #include <err.h> 15fc17b349SJuli Mallett #include <stdlib.h> 16fc17b349SJuli Mallett #include <string.h> 17fc17b349SJuli Mallett #include <unistd.h> 18fc17b349SJuli Mallett 19fc17b349SJuli Mallett void strnsubst(char **, const char *, const char *, size_t); 20fc17b349SJuli Mallett 21fc17b349SJuli Mallett /* 22fc17b349SJuli Mallett * Replaces str with a string consisting of str with match replaced with 23fc17b349SJuli Mallett * replstr as many times as can be done before the constructed string is 24fc17b349SJuli Mallett * maxsize bytes large. It does not free the string pointed to by str, it 25fc17b349SJuli Mallett * is up to the calling program to be sure that the original contents of 26fc17b349SJuli Mallett * str as well as the new contents are handled in an appropriate manner. 27986d829bSJuli Mallett * If replstr is NULL, then that internally is changed to a nil-string, so 28986d829bSJuli Mallett * that we can still pretend to do somewhat meaningful substitution. 29fc17b349SJuli Mallett * No value is returned. 30fc17b349SJuli Mallett */ 31fc17b349SJuli Mallett void 32fc17b349SJuli Mallett strnsubst(char **str, const char *match, const char *replstr, size_t maxsize) 33fc17b349SJuli Mallett { 34299ea75aSJuli Mallett char *s1, *s2, *this; 35fc17b349SJuli Mallett 36fc17b349SJuli Mallett s1 = *str; 37fc17b349SJuli Mallett if (s1 == NULL) 38fc17b349SJuli Mallett return; 39fc17b349SJuli Mallett s2 = calloc(maxsize, 1); 40fc17b349SJuli Mallett if (s2 == NULL) 41fc17b349SJuli Mallett err(1, "calloc"); 42fc17b349SJuli Mallett 43986d829bSJuli Mallett if (replstr == NULL) 44986d829bSJuli Mallett replstr = ""; 45986d829bSJuli Mallett 46299ea75aSJuli Mallett if (match == NULL || replstr == NULL || maxsize == strlen(s1)) { 470fa5e8dcSJuli Mallett strlcpy(s2, s1, maxsize); 480fa5e8dcSJuli Mallett goto done; 490fa5e8dcSJuli Mallett } 500fa5e8dcSJuli Mallett 51fc17b349SJuli Mallett for (;;) { 52fc17b349SJuli Mallett this = strstr(s1, match); 53fc17b349SJuli Mallett if (this == NULL) 54fc17b349SJuli Mallett break; 55fc17b349SJuli Mallett if ((strlen(s2) + ((uintptr_t)this - (uintptr_t)s1) + 5638dff9a4SJuli Mallett (strlen(replstr) - 1)) > maxsize && *replstr != '\0') { 57fc17b349SJuli Mallett strlcat(s2, s1, maxsize); 58fc17b349SJuli Mallett goto done; 59fc17b349SJuli Mallett } 60fc17b349SJuli Mallett strncat(s2, s1, (uintptr_t)this - (uintptr_t)s1); 61fc17b349SJuli Mallett strcat(s2, replstr); 62fc17b349SJuli Mallett s1 = this + strlen(match); 63fc17b349SJuli Mallett } 64fc17b349SJuli Mallett strcat(s2, s1); 65fc17b349SJuli Mallett done: 66fc17b349SJuli Mallett *str = s2; 67fc17b349SJuli Mallett return; 68fc17b349SJuli Mallett } 69fc17b349SJuli Mallett 70fc17b349SJuli Mallett #ifdef TEST 71fc17b349SJuli Mallett #include <stdio.h> 72fc17b349SJuli Mallett 73fc17b349SJuli Mallett int 74fc17b349SJuli Mallett main(void) 75fc17b349SJuli Mallett { 76fc17b349SJuli Mallett char *x, *y; 77fc17b349SJuli Mallett 78fc17b349SJuli Mallett y = x = "{}{}{}"; 79fc17b349SJuli Mallett strnsubst(&x, "{}", "v ybir whyv! ", 12); 80fc17b349SJuli Mallett if (strcmp(x, "v ybir whyv! ") == 0) 81fc17b349SJuli Mallett printf("strnsubst() seems to work as expected.\n"); 82fc17b349SJuli Mallett printf("x: %s\ny: %s\n", x, y); 83fc17b349SJuli Mallett free(x); 84fc17b349SJuli Mallett return 0; 85fc17b349SJuli Mallett } 86fc17b349SJuli Mallett #endif 87