195080Sjmallett/* $xMach: strnsubst.c,v 1.3 2002/02/23 02:10:24 jmallett Exp $ */ 295080Sjmallett 395080Sjmallett/* 495080Sjmallett * Copyright (c) 2002 J. Mallett. All rights reserved. 595080Sjmallett * You may do whatever you want with this file as long as 695080Sjmallett * the above copyright and this notice remain intact, along 795080Sjmallett * with the following statement: 895080Sjmallett * For the man who taught me vi, and who got too old, too young. 995080Sjmallett */ 1095080Sjmallett 1195080Sjmallett#include <sys/cdefs.h> 1295080Sjmallett__FBSDID("$FreeBSD$"); 1395080Sjmallett 1495080Sjmallett#include <err.h> 1595080Sjmallett#include <stdlib.h> 1695080Sjmallett#include <string.h> 1795080Sjmallett#include <unistd.h> 1895080Sjmallett 1995080Sjmallettvoid strnsubst(char **, const char *, const char *, size_t); 2095080Sjmallett 2195080Sjmallett/* 2295080Sjmallett * Replaces str with a string consisting of str with match replaced with 2395080Sjmallett * replstr as many times as can be done before the constructed string is 2495080Sjmallett * maxsize bytes large. It does not free the string pointed to by str, it 2595080Sjmallett * is up to the calling program to be sure that the original contents of 2695080Sjmallett * str as well as the new contents are handled in an appropriate manner. 2797619Sjmallett * If replstr is NULL, then that internally is changed to a nil-string, so 2897619Sjmallett * that we can still pretend to do somewhat meaningful substitution. 2995080Sjmallett * No value is returned. 3095080Sjmallett */ 3195080Sjmallettvoid 3295080Sjmallettstrnsubst(char **str, const char *match, const char *replstr, size_t maxsize) 3395080Sjmallett{ 3495900Sjmallett char *s1, *s2, *this; 3595080Sjmallett 3695080Sjmallett s1 = *str; 3795080Sjmallett if (s1 == NULL) 3895080Sjmallett return; 39153917Sjmallett /* 40153917Sjmallett * If maxsize is 0 then set it to to the length of s1, because we have 41153917Sjmallett * to duplicate s1. XXX we maybe should double-check whether the match 42153917Sjmallett * appears in s1. If it doesn't, then we also have to set the length 43153917Sjmallett * to the length of s1, to avoid modifying the argument. It may make 44153917Sjmallett * sense to check if maxsize is <= strlen(s1), because in that case we 45153917Sjmallett * want to return the unmodified string, too. 46153917Sjmallett */ 47153917Sjmallett if (maxsize == 0) { 48153917Sjmallett match = NULL; 49153917Sjmallett maxsize = strlen(s1) + 1; 50153917Sjmallett } 51245050Sdelphij s2 = calloc(1, maxsize); 5295080Sjmallett if (s2 == NULL) 5395080Sjmallett err(1, "calloc"); 5495080Sjmallett 5597619Sjmallett if (replstr == NULL) 5697619Sjmallett replstr = ""; 5797619Sjmallett 5895900Sjmallett if (match == NULL || replstr == NULL || maxsize == strlen(s1)) { 5995898Sjmallett strlcpy(s2, s1, maxsize); 6095898Sjmallett goto done; 6195898Sjmallett } 6295898Sjmallett 6395080Sjmallett for (;;) { 6495080Sjmallett this = strstr(s1, match); 6595080Sjmallett if (this == NULL) 6695080Sjmallett break; 67136664Scperciva if ((strlen(s2) + strlen(s1) + strlen(replstr) - 68136664Scperciva strlen(match) + 1) > maxsize) { 6995080Sjmallett strlcat(s2, s1, maxsize); 7095080Sjmallett goto done; 7195080Sjmallett } 7295080Sjmallett strncat(s2, s1, (uintptr_t)this - (uintptr_t)s1); 7395080Sjmallett strcat(s2, replstr); 7495080Sjmallett s1 = this + strlen(match); 7595080Sjmallett } 7695080Sjmallett strcat(s2, s1); 7795080Sjmallettdone: 7895080Sjmallett *str = s2; 7995080Sjmallett return; 8095080Sjmallett} 8195080Sjmallett 8295080Sjmallett#ifdef TEST 8395080Sjmallett#include <stdio.h> 8495080Sjmallett 8595080Sjmallettint 8695080Sjmallettmain(void) 8795080Sjmallett{ 8898616Sjmallett char *x, *y, *z, *za; 8995080Sjmallett 9098616Sjmallett x = "{}%$"; 9198616Sjmallett strnsubst(&x, "%$", "{} enpury!", 255); 9298616Sjmallett y = x; 9398616Sjmallett strnsubst(&y, "}{}", "ybir", 255); 9498616Sjmallett z = y; 9598616Sjmallett strnsubst(&z, "{", "v ", 255); 9698616Sjmallett za = z; 9798616Sjmallett strnsubst(&z, NULL, za, 255); 9898616Sjmallett if (strcmp(z, "v ybir enpury!") == 0) 9998616Sjmallett printf("strnsubst() seems to work!\n"); 10098616Sjmallett else 10198616Sjmallett printf("strnsubst() is broken.\n"); 10298616Sjmallett printf("%s\n", z); 10395080Sjmallett free(x); 10498616Sjmallett free(y); 10598616Sjmallett free(z); 10698616Sjmallett free(za); 10795080Sjmallett return 0; 10895080Sjmallett} 10995080Sjmallett#endif 110