struct subst_expr* repl_exp_parse(str subst) { struct replace_with rw[MAX_REPLACE_WITH]; int rw_no; struct subst_expr * se; int replace_all; char * p, *end, *repl, *repl_end; int max_pmatch, r; se = 0; replace_all = 0; p = subst.s; end = p + subst.len; rw_no = 0; repl = p; if((rw_no = parse_repl(rw, &p, end, &max_pmatch, WITHOUT_SEP))< 0) goto error; repl_end=p; /* construct the subst_expr structure */ se = shm_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){ LM_ERR("out of shm memory (subst_expr)\n"); goto error; } memset((void*)se, 0, sizeof(struct subst_expr)); se->replacement.len=repl_end-repl; if (!(se->replacement.s=shm_malloc(se->replacement.len * sizeof(char))) ){ LM_ERR("out of shm memory \n"); goto error; } if(!rw_no){ replace_all = 1; } /* start copying */ memcpy(se->replacement.s, repl, se->replacement.len); se->re=0; se->replace_all=replace_all; se->n_escapes=rw_no; se->max_pmatch=max_pmatch; /*replace_with is a simple structure, no shm alloc needed*/ for (r=0; r<rw_no; r++) se->replace[r]=rw[r]; return se; error: if (se) { repl_expr_free(se);} return NULL; }
/*! \brief Parse a /regular expression/replacement/flags into a subst_expr structure */ struct subst_expr* subst_parser(str* subst) { 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){ LM_ERR("expression is too short: %.*s\n", subst->len, subst->s); goto error; } p=subst->s; end=subst->s+subst->len; c=*p; if (c=='\\'){ LM_ERR("invalid separator char <%c> in %.*s\n", c, subst->len, subst->s); goto error; } p++; /* find re */ re=p; for (;p<end;p++){ /* if unescaped sep. char */ if ((*p==c) && (*(p-1)!='\\')) goto found_re; } LM_ERR("no separator found: %.*s\n", subst->len, subst->s); goto error; found_re: re_end=p; if(end< (p+2) ){ LM_ERR("string too short\n"); goto error; } repl=p+1; if((rw_no = parse_repl(rw, &p, end, &max_pmatch, WITH_SEP))< 0) goto error; 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: LM_ERR("unknown flag %c in %.*s\n", *p, subst->len, subst->s); goto error; } } /* compile the re */ if ((regex=pkg_malloc(sizeof(regex_t)))==0){ LM_ERR("out of pkg 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 */ LM_ERR("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){ LM_ERR("out of pkg 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){ LM_ERR("out of pkg 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]; LM_DBG("ok, se is %p\n", se); return se; error: if (se) { subst_expr_free(se); regex=0; } if (regex) { regfree (regex); pkg_free(regex); } return 0; }