static int cond_pcre_match(char **a, int id) { pcre *pcre_pat; const char *pcre_err; char *lhstr, *rhre; int r = 0, pcre_opts = 0, pcre_errptr, capcnt, *ov, ovsize; lhstr = cond_str(a,0,0); rhre = cond_str(a,1,0); switch(id) { case CPCRE_PLAIN: pcre_pat = pcre_compile(rhre, pcre_opts, &pcre_err, &pcre_errptr, NULL); pcre_fullinfo(pcre_pat, NULL, PCRE_INFO_CAPTURECOUNT, &capcnt); ovsize = (capcnt+1)*3; ov = zalloc(ovsize*sizeof(int)); r = pcre_exec(pcre_pat, NULL, lhstr, strlen(lhstr), 0, 0, ov, ovsize); if (r==0) return 1; else if (r==PCRE_ERROR_NOMATCH) return 0; /* no match */ else if (r>0) { zpcre_get_substrings(lhstr, ov, r, NULL); return 1; } break; } return 0; }
static int cond_psfix(char **a, int id) { if (comp_check()) { if (a[1]) return do_comp_vars(id, cond_val(a, 0), cond_str(a, 1, 1), 0, NULL, 0); else return do_comp_vars(id, -1, cond_str(a, 0, 1), 0, NULL, 0); } return 0; }
static int cond_pcre_match(char **a, int id) { pcre *pcre_pat; const char *pcre_err; char *lhstr, *rhre, *lhstr_plain, *rhre_plain, *avar=NULL; int r = 0, pcre_opts = 0, pcre_errptr, capcnt, *ov, ovsize; int return_value = 0; if (zpcre_utf8_enabled()) pcre_opts |= PCRE_UTF8; lhstr = cond_str(a,0,0); rhre = cond_str(a,1,0); lhstr_plain = ztrdup(lhstr); rhre_plain = ztrdup(rhre); unmetafy(lhstr_plain, NULL); unmetafy(rhre_plain, NULL); pcre_pat = NULL; ov = NULL; ovsize = 0; if (isset(BASHREMATCH)) avar="BASH_REMATCH"; switch(id) { case CPCRE_PLAIN: pcre_pat = pcre_compile(rhre_plain, pcre_opts, &pcre_err, &pcre_errptr, NULL); if (pcre_pat == NULL) { zwarn("failed to compile regexp /%s/: %s", rhre, pcre_err); break; } pcre_fullinfo(pcre_pat, NULL, PCRE_INFO_CAPTURECOUNT, &capcnt); ovsize = (capcnt+1)*3; ov = zalloc(ovsize*sizeof(int)); r = pcre_exec(pcre_pat, NULL, lhstr_plain, strlen(lhstr_plain), 0, 0, ov, ovsize); /* r < 0 => error; r==0 match but not enough size in ov * r > 0 => (r-1) substrings found; r==1 => no substrings */ if (r==0) { zwarn("reportable zsh problem: pcre_exec() returned 0"); return_value = 1; break; } else if (r==PCRE_ERROR_NOMATCH) { return_value = 0; /* no match */ break; } else if (r<0) { zwarn("pcre_exec() error [%d]", r); break; } else if (r>0) { zpcre_get_substrings(lhstr_plain, ov, r, NULL, avar, 0, isset(BASHREMATCH), !isset(BASHREMATCH)); return_value = 1; break; } break; } if (lhstr_plain) free(lhstr_plain); if(rhre_plain) free(rhre_plain); if (pcre_pat) pcre_free(pcre_pat); if (ov) zfree(ov, ovsize*sizeof(int)); return return_value; }
static int cond_range(char **a, int id) { return do_comp_vars(CVT_RANGEPAT, 0, cond_str(a, 0, 1), 0, (id ? cond_str(a, 1, 1) : NULL), 0); }
static int zcond_regex_match(char **a, int id) { regex_t re; regmatch_t *m, *matches = NULL; size_t matchessz = 0; char *lhstr, *lhstr_zshmeta, *rhre, *rhre_zshmeta, *s, **arr, **x; int r, n, return_value, rcflags, reflags, nelem, start; lhstr_zshmeta = cond_str(a,0,0); rhre_zshmeta = cond_str(a,1,0); rcflags = reflags = 0; return_value = 0; /* 1 => matched successfully */ lhstr = ztrdup(lhstr_zshmeta); unmetafy(lhstr, NULL); rhre = ztrdup(rhre_zshmeta); unmetafy(rhre, NULL); switch(id) { case ZREGEX_EXTENDED: rcflags |= REG_EXTENDED; if (!isset(CASEMATCH)) rcflags |= REG_ICASE; r = regcomp(&re, rhre, rcflags); if (r) { zregex_regerrwarn(r, &re, "failed to compile regex"); break; } /* re.re_nsub is number of parenthesized groups, we also need * 1 for the 0 offset, which is the entire matched portion */ if ((int)re.re_nsub < 0) { zwarn("INTERNAL ERROR: regcomp() returned " "negative subpattern count %d", (int)re.re_nsub); break; } matchessz = (re.re_nsub + 1) * sizeof(regmatch_t); matches = zalloc(matchessz); r = regexec(&re, lhstr, re.re_nsub+1, matches, reflags); if (r == REG_NOMATCH) ; /* We do nothing when we fail to match. */ else if (r == 0) { return_value = 1; if (isset(BASHREMATCH)) { start = 0; nelem = re.re_nsub + 1; } else { start = 1; nelem = re.re_nsub; } arr = NULL; /* bogus gcc warning of used uninitialised */ /* entire matched portion + re_nsub substrings + NULL */ if (nelem) { arr = x = (char **) zalloc(sizeof(char *) * (nelem + 1)); for (m = matches + start, n = start; n <= (int)re.re_nsub; ++n, ++m, ++x) { *x = metafy(lhstr + m->rm_so, m->rm_eo - m->rm_so, META_DUP); } *x = NULL; } if (isset(BASHREMATCH)) { setaparam("BASH_REMATCH", arr); } else { zlong offs; char *ptr; int clen, leftlen; m = matches; s = metafy(lhstr + m->rm_so, m->rm_eo - m->rm_so, META_DUP); setsparam("MATCH", s); /* * Count the characters before the match. */ ptr = lhstr; leftlen = m->rm_so; offs = 0; MB_CHARINIT(); while (leftlen) { offs++; clen = MB_CHARLEN(ptr, leftlen); ptr += clen; leftlen -= clen; } setiparam("MBEGIN", offs + !isset(KSHARRAYS)); /* * Add on the characters in the match. */ leftlen = m->rm_eo - m->rm_so; while (leftlen) { offs++; clen = MB_CHARLEN(ptr, leftlen); ptr += clen; leftlen -= clen; } setiparam("MEND", offs + !isset(KSHARRAYS) - 1); if (nelem) { char **mbegin, **mend, **bptr, **eptr; bptr = mbegin = (char **)zalloc(sizeof(char *)*(nelem+1)); eptr = mend = (char **)zalloc(sizeof(char *)*(nelem+1)); for (m = matches + start, n = 0; n < nelem; ++n, ++m, ++bptr, ++eptr) { char buf[DIGBUFSIZE]; if (m->rm_so < 0 || m->rm_eo < 0) { *bptr = ztrdup("-1"); *eptr = ztrdup("-1"); continue; } ptr = lhstr; leftlen = m->rm_so; offs = 0; /* Find the start offset */ MB_CHARINIT(); while (leftlen) { offs++; clen = MB_CHARLEN(ptr, leftlen); ptr += clen; leftlen -= clen; } convbase(buf, offs + !isset(KSHARRAYS), 10); *bptr = ztrdup(buf); /* Continue to the end offset */ leftlen = m->rm_eo - m->rm_so; while (leftlen ) { offs++; clen = MB_CHARLEN(ptr, leftlen); ptr += clen; leftlen -= clen; } convbase(buf, offs + !isset(KSHARRAYS) - 1, 10); *eptr = ztrdup(buf); } *bptr = *eptr = NULL; setaparam("match", arr); setaparam("mbegin", mbegin); setaparam("mend", mend); } } } else zregex_regerrwarn(r, &re, "regex matching error"); break; default: DPUTS(1, "bad regex option"); return_value = 0; goto CLEAN_BASEMETA; } if (matches) zfree(matches, matchessz); regfree(&re); CLEAN_BASEMETA: free(lhstr); free(rhre); return return_value; }