/*
 * regsub
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <regexp.h>
#include "regmagic.h"

/*
 - regsub - perform substitutions after a regexp match
 */

void regsub(rp, source, dest)
const regexp *rp;
const char *source;
char *dest;
{
        regnsub(rp, source, dest, BUFSIZ);
}



/*
 - regnsub - perform bounds-checked substitutions after a regexp match
 */
void
regnsub(rp, source, dest, destlen)
const regexp *rp;
const char *source;
char *dest;
size_t destlen;
{
	register regexp * const prog = (regexp *)rp;
	register const char *src = (char *)source;
	register char *dst = dest;
	char *dstend = dest + destlen;
	char *odst;
	register char c;
	register int no;
	register size_t len;

	if (prog == NULL || source == NULL || dest == NULL) {
		regerror("NULL parameter to regsub");
		return;
	}
	if ((unsigned char)*(prog->program) != MAGIC) {
		regerror("damaged regexp");
		return;
	}

	while ((c = *src++) != '\0') {
		if (c == '&')
			no = 0;
		else if (c == '\\' && isdigit(*src))
			no = *src++ - '0';
		else
			no = -1;

		if (no < 0) {	/* Ordinary character. */
			if (c == '\\' && (*src == '\\' || *src == '&'))
				c = *src++;
			*dst++ = c;
			if (dst >= dstend) 
			{
			    	regerror("output buffer too small");
				return;
			}
		} else if (prog->startp[no] != NULL && prog->endp[no] != NULL &&
			   prog->endp[no] > prog->startp[no]) {
			len = prog->endp[no] - prog->startp[no];
			odst = dst;
			dst += len;
			if (dst >= dstend) 
			{
			    	regerror("output buffer too small");
				return;
			}
			(void) strncpy(odst, prog->startp[no], len);
			if (*(dst-1) == '\0') {	/* strncpy hit NUL. */
				regerror("damaged match string");
				return;
			}
		}
	}
	*dst++ = '\0';
}

size_t regsublen(rp, source)
const regexp *rp;
const char *source;
{
    register regexp * const prog = (regexp *)rp;
    register char *src = (char *)source;
    register char c;
    register int no;
    register int len = 0;
	
    if (prog == NULL || source == NULL) {
	regerror("NULL parameter to regsublen");
	return -1;
    }
    
    if ((unsigned char)*(prog->program) != MAGIC) {
	regerror("damaged regexp");
	return -1;
    }
    while ((c = *src++) != '\0') {
	if (c == '&')
	    no = 0;
	else if (c == '\\' && isdigit(*src))
	    no = *src++ - '0';
	else
	    no = -1;
	if (no < 0) {		/* Ordinary character. */
	    if (c == '\\' && (*src == '\\' || *src == '&'))
		src++;
	    len++;
	} else {
	    const char *s = prog->startp[no];
	    const char *e = prog->endp[no];
	    if ((s != NULL) && (e != NULL) && (e > s)) {
		len += e-s;
	    }
	}
    }
    return len+1;
}