static void vxp_expr_regex(struct vxp *vxp, struct vex_rhs **prhs) { const char *errptr; int erroff; /* XXX: Caseless option */ AN(prhs); AZ(*prhs); if (vxp->t->tok != VAL) { VSB_printf(vxp->sb, "Expected regular expression got '%.*s' ", PF(vxp->t)); vxp_ErrWhere(vxp, vxp->t, -1); return; } AN(vxp->t->dec); ALLOC_OBJ(*prhs, VEX_RHS_MAGIC); AN(*prhs); (*prhs)->type = VEX_REGEX; (*prhs)->val_string = strdup(vxp->t->dec); (*prhs)->val_regex = VRE_compile(vxp->t->dec, vxp->vre_options, &errptr, &erroff); if ((*prhs)->val_regex == NULL) { AN(errptr); VSB_printf(vxp->sb, "Regular expression error: %s ", errptr); vxp_ErrWhere(vxp, vxp->t, erroff); return; } vxp_NextToken(vxp); }
static void vxp_expr_not(struct vxp *vxp, struct vex **pvex) { AN(pvex); AZ(*pvex); if (vxp->t->tok == T_NOT) { *pvex = vex_alloc(vxp); AN(*pvex); (*pvex)->tok = vxp->t->tok; vxp_NextToken(vxp); vxp_expr_group(vxp, &(*pvex)->a); return; } vxp_expr_group(vxp, pvex); }
static void vxp_expr_num(struct vxp *vxp, struct vex_rhs **prhs, int vxid) { char *endptr; AN(prhs); AZ(*prhs); if (vxp->t->tok != VAL) { VSB_printf(vxp->sb, "Expected number got '%.*s' ", PF(vxp->t)); vxp_ErrWhere(vxp, vxp->t, -1); return; } AN(vxp->t->dec); ALLOC_OBJ(*prhs, VEX_RHS_MAGIC); AN(*prhs); if (strchr(vxp->t->dec, '.')) { (*prhs)->type = VEX_FLOAT; (*prhs)->val_float = VNUM(vxp->t->dec); if (isnan((*prhs)->val_float)) { VSB_printf(vxp->sb, "Floating point parse error "); vxp_ErrWhere(vxp, vxp->t, -1); return; } } else { (*prhs)->type = VEX_INT; (*prhs)->val_int = strtoll(vxp->t->dec, &endptr, 0); while (isspace(*endptr)) endptr++; if (*endptr != '\0') { VSB_printf(vxp->sb, "Integer parse error "); vxp_ErrWhere(vxp, vxp->t, -1); return; } } if (vxid && (*prhs)->type != VEX_INT) { VSB_printf(vxp->sb, "Expected integer got '%.*s' ", PF(vxp->t)); vxp_ErrWhere(vxp, vxp->t, 0); return; } vxp_NextToken(vxp); }
static void vxp_expr_str(struct vxp *vxp, struct vex_rhs **prhs) { AN(prhs); AZ(*prhs); if (vxp->t->tok != VAL) { VSB_printf(vxp->sb, "Expected string got '%.*s' ", PF(vxp->t)); vxp_ErrWhere(vxp, vxp->t, -1); return; } AN(vxp->t->dec); ALLOC_OBJ(*prhs, VEX_RHS_MAGIC); AN(*prhs); (*prhs)->type = VEX_STRING; (*prhs)->val_string = strdup(vxp->t->dec); AN((*prhs)->val_string); (*prhs)->val_stringlen = strlen((*prhs)->val_string); vxp_NextToken(vxp); }
static void vxp_expr_or(struct vxp *vxp, struct vex **pvex) { struct vex *a; AN(pvex); AZ(*pvex); vxp_expr_and(vxp, pvex); ERRCHK(vxp); while (vxp->t->tok == T_OR) { a = *pvex; *pvex = vex_alloc(vxp); AN(*pvex); (*pvex)->tok = vxp->t->tok; (*pvex)->a = a; vxp_NextToken(vxp); ERRCHK(vxp); vxp_expr_and(vxp, &(*pvex)->b); ERRCHK(vxp); } }
static void vxp_expr_lhs(struct vxp *vxp, struct vex_lhs **plhs) { char *p; int i; AN(plhs); AZ(*plhs); ALLOC_OBJ(*plhs, VEX_LHS_MAGIC); AN(*plhs); (*plhs)->tags = vbit_init(SLT__MAX); (*plhs)->level = -1; if (vxp->t->tok == '{') { /* Transaction level limits */ vxp_NextToken(vxp); if (vxp->t->tok != VAL) { VSB_printf(vxp->sb, "Expected integer got '%.*s' ", PF(vxp->t)); vxp_ErrWhere(vxp, vxp->t, -1); return; } (*plhs)->level = (int)strtol(vxp->t->dec, &p, 0); if ((*plhs)->level < 0) { VSB_printf(vxp->sb, "Expected positive integer "); vxp_ErrWhere(vxp, vxp->t, -1); return; } if (*p == '-') { (*plhs)->level_pm = -1; p++; } else if (*p == '+') { (*plhs)->level_pm = 1; p++; } if (*p) { VSB_printf(vxp->sb, "Syntax error in level limit "); vxp_ErrWhere(vxp, vxp->t, -1); return; } vxp_NextToken(vxp); ExpectErr(vxp, '}'); vxp_NextToken(vxp); } while (1) { /* The tags this expression applies to */ if (vxp->t->tok != VAL) { VSB_printf(vxp->sb, "Expected VSL tag name got '%.*s' ", PF(vxp->t)); vxp_ErrWhere(vxp, vxp->t, -1); return; } i = VSL_Glob2Tags(vxp->t->dec, -1, vsl_vbm_bitset, (*plhs)->tags); if (i == -1) { VSB_printf(vxp->sb, "Tag name matches zero tags "); vxp_ErrWhere(vxp, vxp->t, -1); return; } if (i == -2) { VSB_printf(vxp->sb, "Tag name is ambiguous "); vxp_ErrWhere(vxp, vxp->t, -1); return; } if (i == -3) { VSB_printf(vxp->sb, "Syntax error in tag name "); vxp_ErrWhere(vxp, vxp->t, -1); return; } assert(i > 0); vxp_NextToken(vxp); if (vxp->t->tok != ',') break; vxp_NextToken(vxp); } if (vxp->t->tok == ':') { /* Record prefix */ vxp_NextToken(vxp); if (vxp->t->tok != VAL) { VSB_printf(vxp->sb, "Expected string got '%.*s' ", PF(vxp->t)); vxp_ErrWhere(vxp, vxp->t, -1); return; } AN(vxp->t->dec); (*plhs)->prefix = strdup(vxp->t->dec); AN((*plhs)->prefix); (*plhs)->prefixlen = strlen((*plhs)->prefix); vxp_NextToken(vxp); } if (vxp->t->tok == '[') { /* LHS field [] */ vxp_NextToken(vxp); if (vxp->t->tok != VAL) { VSB_printf(vxp->sb, "Expected integer got '%.*s' ", PF(vxp->t)); vxp_ErrWhere(vxp, vxp->t, -1); return; } (*plhs)->field = (int)strtol(vxp->t->dec, &p, 0); if (*p || (*plhs)->field <= 0) { VSB_printf(vxp->sb, "Expected positive integer "); vxp_ErrWhere(vxp, vxp->t, -1); return; } vxp_NextToken(vxp); ExpectErr(vxp, ']'); vxp_NextToken(vxp); } }
static void vxp_expr_cmp(struct vxp *vxp, struct vex **pvex) { AN(pvex); AZ(*pvex); *pvex = vex_alloc(vxp); AN(*pvex); vxp_expr_lhs(vxp, &(*pvex)->lhs); ERRCHK(vxp); /* Test operator */ switch (vxp->t->tok) { /* Single lhs expressions don't take any more tokens */ case EOI: case T_AND: case T_OR: case ')': (*pvex)->tok = T_TRUE; return; /* Valid operators */ case T_EQ: /* == */ case '<': /* < */ case '>': /* > */ case T_GEQ: /* >= */ case T_LEQ: /* <= */ case T_NEQ: /* != */ case T_SEQ: /* eq */ case T_SNEQ: /* ne */ case '~': /* ~ */ case T_NOMATCH: /* !~ */ (*pvex)->tok = vxp->t->tok; break; /* Error */ default: VSB_printf(vxp->sb, "Expected operator got '%.*s' ", PF(vxp->t)); vxp_ErrWhere(vxp, vxp->t, -1); return; } vxp_NextToken(vxp); ERRCHK(vxp); /* Value */ switch((*pvex)->tok) { case '\0': WRONG("Missing token"); break; case T_EQ: /* == */ case '<': /* < */ case '>': /* > */ case T_GEQ: /* >= */ case T_LEQ: /* <= */ case T_NEQ: /* != */ vxp_expr_num(vxp, &(*pvex)->rhs); break; case T_SEQ: /* eq */ case T_SNEQ: /* ne */ vxp_expr_str(vxp, &(*pvex)->rhs); break; case '~': /* ~ */ case T_NOMATCH: /* !~ */ vxp_expr_regex(vxp, &(*pvex)->rhs); break; default: INCOMPL(); } }