p++;
static char *twiddle __P((const char *));static char *getstring __P((void));static void exit_regerror __P((int, regex_t *));static void do_subst __P((const char *, regex_t *, const char *, regmatch_t *));static void do_regexpindex __P((const char *, regex_t *, regmatch_t *));static void do_regexp __P((const char *, regex_t *, const char *, regmatch_t *));static void add_sub __P((int, const char *, regex_t *, regmatch_t *));static void add_replace __P((const char *, regex_t *, const char *, regmatch_t *));static void addchars(c, n)	const char *c;	size_t n;{	if (n == 0)		return;	if (current + n > bufsize) {		if (bufsize == 0)			bufsize = 1024;		else			bufsize *= 2;		buffer = realloc(buffer, bufsize);		if (buffer == NULL)			errx(1, "out of memory");	}	memcpy(buffer+current, c, n);	current += n;}static void addchar(c)	char c;{	if (current +1 > bufsize) {		if (bufsize == 0)			bufsize = 1024;		else			bufsize *= 2;		buffer = realloc(buffer, bufsize);		if (buffer == NULL)			errx(1, "out of memory");	}	buffer[current++] = c;}static char *getstring(){	addchar('\0');	current = 0;	return buffer;}static void exit_regerror(er, re)	int er;	regex_t *re;{	size_t 	errlen;	char 	*errbuf;	errlen = regerror(er, re, NULL, 0);	errbuf = xalloc(errlen);	regerror(er, re, errbuf, errlen);	errx(1, "regular expression error: %s", errbuf);}static voidadd_sub(n, string, re, pm)	int n;	const char *string;	regex_t *re;	regmatch_t *pm;{	if (n > re->re_nsub)		warnx("No subexpression %d", n);	/* Subexpressions that did not match are	 * not an error.  */	else if (pm[n].rm_so != -1 &&	    pm[n].rm_eo != -1) {		addchars(string + pm[n].rm_so,			pm[n].rm_eo - pm[n].rm_so);	}}/* Add replacement string to the output buffer, recognizing special * constructs and replacing them with substrings of the original string. */static void add_replace(string, re, replace, pm)	const char *string;	regex_t *re;	const char *replace;	regmatch_t *pm;{	const char *p;	for (p = replace; *p != '\0'; p++) {		if (*p == '&' && !mimic_gnu) {			add_sub(0, string, re, pm);			continue;		}		if (*p == '\\') {			if (p[1] == '\\') {				addchar(p[1]);				continue;			}			if (p[1] == '&') {				if (mimic_gnu)					add_sub(0, string, re, pm);				else					addchar(p[1]);				p++;				continue;			}			if (isdigit(p[1])) {				add_sub(*(++p) - '0', string, re, pm);				continue;			}		}	    	addchar(*p);	}}static void do_subst(string, re, replace, pm)	const char *string;	regex_t *re;	const char *replace;	regmatch_t *pm;{	int error;	regoff_t last_match = -1;	while ((error = regexec(re, string, re->re_nsub+1, pm, 0)) == 0) {		/* NULL length matches are special... We use the `vi-mode' 		 * rule: don't allow a NULL-match at the last match		 * position. 		 */		if (pm[0].rm_so == pm[0].rm_eo && pm[0].rm_so == last_match) {			if (*string == '\0')				return;			addchar(*string);			string++;			continue;		}		last_match = pm[0].rm_so;		addchars(string, last_match);		add_replace(string, re, replace, pm);		string += pm[0].rm_eo;	}	if (error != REG_NOMATCH)		exit_regerror(error, re);	pbstr(string);}static void do_regexp(string, re, replace, pm)	const char *string;	regex_t *re;	const char *replace;	regmatch_t *pm;{	int error;	switch(error = regexec(re, string, re->re_nsub+1, pm, 0)) {	case 0: 		add_replace(string, re, replace, pm);		pbstr(getstring());		break;	case REG_NOMATCH:		break;	default:		exit_regerror(error, re);	}}static void do_regexpindex(string, re, pm)	const char *string;	regex_t *re;	regmatch_t *pm;{	int error;	switch(error = regexec(re, string, re->re_nsub+1, pm, 0)) {	case 0:		pbunsigned(pm[0].rm_so);		break;	case REG_NOMATCH:		pbnum(-1);		break;	default:		exit_regerror(error, re);	}}/* In Gnu m4 mode, parentheses for backmatch don't work like POSIX 1003.2 * says. So we twiddle with the regexp before passing it to regcomp. */static char *twiddle(p)	const char *p;{	/* This could use strcspn for speed... */	while (*p != '\0') {		if (*p == '\\' && (p[1] == '(' || p[1] == ')')) {			addchar(p[1]);			p+=2;			continue;		}		if (*p == '(' || *p == ')')			addchar('\\');		addchar(*p);		p++;	}	return getstring();}