strnsubst.c revision 95898
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: head/usr.bin/xargs/strnsubst.c 95898 2002-05-02 02:06:03Z jmallett $");
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.
2795080Sjmallett * No value is returned.
2895080Sjmallett */
2995080Sjmallettvoid
3095080Sjmallettstrnsubst(char **str, const char *match, const char *replstr, size_t maxsize)
3195080Sjmallett{
3295080Sjmallett	char *s1, *s2;
3395080Sjmallett
3495080Sjmallett	s1 = *str;
3595080Sjmallett	if (s1 == NULL)
3695080Sjmallett		return;
3795080Sjmallett	s2 = calloc(maxsize, 1);
3895080Sjmallett	if (s2 == NULL)
3995080Sjmallett		err(1, "calloc");
4095080Sjmallett
4195898Sjmallett	if (match == NULL || replstr == NULL || maxsize == strlen(*str)) {
4295898Sjmallett		strlcpy(s2, s1, maxsize);
4395898Sjmallett		goto done;
4495898Sjmallett	}
4595898Sjmallett
4695080Sjmallett	for (;;) {
4795080Sjmallett		char *this;
4895080Sjmallett
4995080Sjmallett		this = strstr(s1, match);
5095080Sjmallett		if (this == NULL)
5195080Sjmallett			break;
5295080Sjmallett		if ((strlen(s2) + ((uintptr_t)this - (uintptr_t)s1) +
5395080Sjmallett		    (strlen(replstr) - 1)) > maxsize) {
5495080Sjmallett			strlcat(s2, s1, maxsize);
5595080Sjmallett			goto done;
5695080Sjmallett		}
5795080Sjmallett		strncat(s2, s1, (uintptr_t)this - (uintptr_t)s1);
5895080Sjmallett		strcat(s2, replstr);
5995080Sjmallett		s1 = this + strlen(match);
6095080Sjmallett	}
6195080Sjmallett	strcat(s2, s1);
6295080Sjmallettdone:
6395080Sjmallett	*str = s2;
6495080Sjmallett	return;
6595080Sjmallett}
6695080Sjmallett
6795080Sjmallett#ifdef TEST
6895080Sjmallett#include <stdio.h>
6995080Sjmallett
7095080Sjmallettint
7195080Sjmallettmain(void)
7295080Sjmallett{
7395080Sjmallett	char *x, *y;
7495080Sjmallett
7595080Sjmallett	y = x = "{}{}{}";
7695080Sjmallett	strnsubst(&x, "{}", "v ybir whyv! ", 12);
7795080Sjmallett	if (strcmp(x, "v ybir whyv! ") == 0)
7895080Sjmallett		printf("strnsubst() seems to work as expected.\n");
7995080Sjmallett	printf("x: %s\ny: %s\n", x, y);
8095080Sjmallett	free(x);
8195080Sjmallett	return 0;
8295080Sjmallett}
8395080Sjmallett#endif
84