add: DBG("subst_parser: ok, se is %p\n", se);
context: struct subst_expr* subst_parser(str* subst){#define MAX_REPLACE_WITH 100	char c;	char* end;	char* p;	char* re;	char* re_end;	char* repl;	char* repl_end;	struct replace_with rw[MAX_REPLACE_WITH];	int rw_no;	int escape;	int cflags; /* regcomp flags */	int replace_all;	struct subst_expr* se;	regex_t* regex;	int max_pmatch;	int r;		/* init */	se=0;	regex=0;	cflags=REG_EXTENDED  | REG_NEWLINE; /* don't match newline */	replace_all=0;	if (subst->len<3){		LOG(L_ERR, "ERROR: subst_parser: expression is too short: %.*s\n",				subst->len, subst->s);		goto error;	}		p=subst->s;	c=*p;	if (c=='\\'){		LOG(L_ERR, "ERROR: subst_parser: invalid separator char <%c>"				" in %.*s\n", c, subst->len, subst->s);		goto error;	}	p++;	end=subst->s+subst->len;	/* find re */	re=p;	for (;p<end;p++){		/* if unescaped sep. char */		if ((*p==c) && (*(p-1)!='\\')) goto found_re;	}	LOG(L_ERR, "ERROR: subst_parser: no separator found: %.*s\n", subst->len, 			subst->s);	goto error;found_re:	re_end=p;	p++;	/* parse replacement */	repl=p;	rw_no=0;	max_pmatch=0;	escape=0;	for(;p<end; p++){		if (escape){			escape=0;			switch (*p){				/* special char escapes */				case '\\':					rw[rw_no].size=2;					rw[rw_no].offset=(p-1)-repl;					rw[rw_no].type=REPLACE_CHAR;					rw[rw_no].c='\\';					break;				case 'n':					rw[rw_no].size=2;					rw[rw_no].offset=(p-1)-repl;					rw[rw_no].type=REPLACE_CHAR;					rw[rw_no].c='\n';					break;				case 'r':					rw[rw_no].size=2;					rw[rw_no].offset=(p-1)-repl;					rw[rw_no].type=REPLACE_CHAR;					rw[rw_no].c='\r';					break;				case 't':					rw[rw_no].size=2;					rw[rw_no].offset=(p-1)-repl;					rw[rw_no].type=REPLACE_CHAR;					rw[rw_no].c='\t';					break;				/* special sip msg parts escapes */				case 'u':					rw[rw_no].size=2;					rw[rw_no].offset=(p-1)-repl;					rw[rw_no].type=REPLACE_URI;					break;				/* re matches */				case '0': /* allow 0, too, reference to the whole match */				case '1':				case '2':				case '3':				case '4':				case '5':				case '6':				case '7':				case '8':				case '9':					rw[rw_no].size=2;					rw[rw_no].offset=(p-1)-repl;					rw[rw_no].type=REPLACE_NMATCH;					rw[rw_no].nmatch=(*p)-'0'; /* 0 is the whole matched str*/					if (max_pmatch<rw[rw_no].nmatch) 						max_pmatch=rw[rw_no].nmatch;					break;				default: /* just print current char */					if (*p!=c){						LOG(L_WARN, "subst_parser: WARNING: \\%c unknown"								" escape in %.*s\n", *p, subst->len, subst->s);					}					rw[rw_no].size=2;					rw[rw_no].offset=(p-1)-repl;					rw[rw_no].type=REPLACE_CHAR;					rw[rw_no].c=*p;					break;			}			rw_no++;			if (rw_no>=MAX_REPLACE_WITH){				LOG(L_ERR, "ERROR: subst_parser: too many escapes in the"							" replace part %.*s\n", subst->len, subst->s);				goto error;			}		}else if (*p=='\\') escape=1;		else  if (*p==c) goto found_repl;	}	LOG(L_ERR, "ERROR: subst_parser: missing separator: %.*s\n", subst->len, 			subst->s);	goto error;found_repl:	repl_end=p;	p++;	/* parse flags */	for(;p<end; p++){		switch(*p){			case 'i':				cflags|=REG_ICASE;				break;			case 's':				cflags&=(~REG_NEWLINE);				break;			case 'g':				replace_all=1;				break;			default:				LOG(L_ERR, "ERROR: subst_parser: unknown flag %c in %.*s\n",						*p, subst->len, subst->s);				goto error;		}	}	/* compile the re */	if ((regex=pkg_malloc(sizeof(regex_t)))==0){		LOG(L_ERR, "ERROR: subst_parser: out of memory (re)\n");		goto error;	}	c=*re_end; /* regcomp expects null terminated strings -- save */	*re_end=0;	if (regcomp(regex, re, cflags)!=0){		pkg_free(regex);		*re_end=c; /* restore */		LOG(L_ERR, "ERROR: subst_parser: bad regular expression %.*s in "				"%.*s\n", (int)(re_end-re), re, subst->len, subst->s);		goto error;	}	*re_end=c; /* restore */	/* construct the subst_expr structure */	se=pkg_malloc(sizeof(struct subst_expr)+					((rw_no)?(rw_no-1)*sizeof(struct replace_with):0));		/* 1 replace_with structure is  already included in subst_expr */	if (se==0){		LOG(L_ERR, "ERROR: subst_parser: out of memory (subst_expr)\n");		goto error;	}	memset((void*)se, 0, sizeof(struct subst_expr));	se->replacement.len=repl_end-repl;	if ((se->replacement.s=pkg_malloc(se->replacement.len))==0){		LOG(L_ERR, "ERROR: subst_parser: out of memory (replacement)\n");		goto error;	}	/* start copying */	memcpy(se->replacement.s, repl, se->replacement.len);	se->re=regex;	se->replace_all=replace_all;	se->n_escapes=rw_no;	se->max_pmatch=max_pmatch;	for (r=0; r<rw_no; r++) se->replace[r]=rw[r];	return se;	error:	if (se) { subst_expr_free(se); regex=0; }	if (regex) { regfree (regex); pkg_free(regex); }	return 0;}