/* Parse and evaluate match (regex) expressions */ struct val * eval5(void) { regex_t rp; regmatch_t rm[2]; char errbuf[256]; int eval; struct val *l, *r; struct val *v; l = eval6(); while (token == MATCH) { nexttoken(1); r = eval6(); /* coerce to both arguments to strings */ to_string(l); to_string(r); /* compile regular expression */ if ((eval = regcomp(&rp, r->u.s, 0)) != 0) { regerror(eval, &rp, errbuf, sizeof(errbuf)); errx(2, "%s", errbuf); } /* compare string against pattern -- remember that patterns are anchored to the beginning of the line */ if (regexec(&rp, l->u.s, 2, rm, 0) == 0 && rm[0].rm_so == 0) { if (rm[1].rm_so >= 0) { *(l->u.s + rm[1].rm_eo) = '\0'; v = make_str(l->u.s + rm[1].rm_so); } else { v = make_int((int)(rm[0].rm_eo - rm[0].rm_so)); } } else { if (rp.re_nsub == 0) { v = make_int(0); } else { v = make_str(""); } } /* free arguments and pattern buffer */ free_value(l); free_value(r); regfree(&rp); l = v; } return l; }
static VALUE *eval5(void) { VALUE *l, *r, *v; l = eval6(); while (nextarg(":")) { G.args++; r = eval6(); v = docolon(l, r); freev(l); freev(r); l = v; } return l; }
static VALUE *eval6(void) { static const char keywords[] ALIGN1 = "quote\0""length\0""match\0""index\0""substr\0"; VALUE *r, *i1, *i2; static VALUE *l = NULL; static VALUE *v = NULL; int key = *G.args ? index_in_strings(keywords, *G.args) + 1 : 0; if (key == 0) /* not a keyword */ return eval7(); G.args++; /* We have a valid token, so get the next argument. */ if (key == 1) { /* quote */ if (!*G.args) bb_error_msg_and_die("syntax error"); return str_value(*G.args++); } if (key == 2) { /* length */ r = eval6(); tostring(r); v = int_value(strlen(r->u.s)); freev(r); } else l = eval6(); if (key == 3) { /* match */ r = eval6(); v = docolon(l, r); freev(l); freev(r); } if (key == 4) { /* index */ r = eval6(); tostring(l); tostring(r); v = int_value(strcspn(l->u.s, r->u.s) + 1); if (v->u.i == (arith_t) strlen(l->u.s) + 1) v->u.i = 0; freev(l); freev(r); } if (key == 5) { /* substr */ i1 = eval6(); i2 = eval6(); tostring(l); if (!toarith(i1) || !toarith(i2) || i1->u.i > (arith_t) strlen(l->u.s) || i1->u.i <= 0 || i2->u.i <= 0) v = str_value(""); else { v = xmalloc(sizeof(VALUE)); v->type = STRING; v->u.s = xstrndup(l->u.s + i1->u.i - 1, i2->u.i); } freev(l); freev(i1); freev(i2); } return v; }