static void vcc_expr_string_add(struct vcc *tl, struct expr **e) { struct expr *e2; enum var_type f2; f2 = (*e)->fmt; while (tl->t->tok == '+') { vcc_NextToken(tl); vcc_expr_mul(tl, &e2, STRING); ERRCHK(tl); if (e2->fmt != STRING && e2->fmt != STRING_LIST) { vcc_expr_tostring(tl, &e2, f2); ERRCHK(tl); } ERRCHK(tl); assert(e2->fmt == STRING || e2->fmt == STRING_LIST); if (vcc_isconst(*e) && vcc_isconst(e2)) { assert((*e)->fmt == STRING); assert(e2->fmt == STRING); *e = vcc_expr_edit(STRING, "\v1\n\v2", *e, e2); (*e)->constant = EXPR_CONST; } else if (((*e)->constant & EXPR_STR_CONST) && vcc_isconst(e2)) { assert((*e)->fmt == STRING_LIST); assert(e2->fmt == STRING); *e = vcc_expr_edit(STRING_LIST, "\v1\n\v2", *e, e2); (*e)->constant = EXPR_VAR | EXPR_STR_CONST; } else if (e2->fmt == STRING && vcc_isconst(e2)) { *e = vcc_expr_edit(STRING_LIST, "\v1,\n\v2", *e, e2); (*e)->constant = EXPR_VAR | EXPR_STR_CONST; } else { *e = vcc_expr_edit(STRING_LIST, "\v1,\n\v2", *e, e2); (*e)->constant = EXPR_VAR; } } }
static void vcc_expr_add(struct vcc *tl, struct expr **e, enum var_type fmt) { struct expr *e2; enum var_type f2; struct token *tk; *e = NULL; vcc_expr_mul(tl, e, fmt); ERRCHK(tl); f2 = (*e)->fmt; if ((f2 == STRING_LIST || f2 == STRING) && tl->t->tok == '+') { while (tl->t->tok == '+') { vcc_NextToken(tl); vcc_expr_mul(tl, &e2, STRING); ERRCHK(tl); if (e2->fmt != STRING && e2->fmt != STRING_LIST) vcc_expr_tostring(&e2, f2); ERRCHK(tl); assert(e2->fmt == STRING || e2->fmt == STRING_LIST); if ((*e)->constant && e2->constant) { assert((*e)->fmt == STRING); assert(e2->fmt == STRING); *e = vcc_expr_edit(STRING, "\v1\n\v2", *e, e2); } else { *e = vcc_expr_edit(STRING_LIST, "\v1,\n\v2", *e, e2); } } } if (fmt != STRING_LIST && (*e)->fmt == STRING_LIST) *e = vcc_expr_edit(STRING, "\v+VRT_WrkString(sp,\n\v1,\nvrt_magic_string_end)", *e, NULL); if (fmt == STRING_LIST && (*e)->fmt == STRING) (*e)->fmt = STRING_LIST; switch(f2) { case INT: break; case TIME: break; case DURATION: break; case BYTES: break; default: if (tl->t->tok != '+' && tl->t->tok != '-') return; VSB_printf(tl->sb, "Operator %.*s not possible on type %s.\n", PF(tl->t), vcc_Type(f2)); vcc_ErrWhere(tl, tl->t); return; } while (tl->t->tok == '+' || tl->t->tok == '-') { if (f2 == TIME) f2 = DURATION; tk = tl->t; vcc_NextToken(tl); vcc_expr_mul(tl, &e2, f2); ERRCHK(tl); if (tk->tok == '-' && (*e)->fmt == TIME && e2->fmt == TIME) { /* OK */ } else if (tk->tok == '-' && (*e)->fmt == BYTES && e2->fmt == BYTES) { /* OK */ } else if (e2->fmt != f2) { VSB_printf(tl->sb, "%s %.*s %s not possible.\n", vcc_Type((*e)->fmt), PF(tk), vcc_Type(e2->fmt)); vcc_ErrWhere2(tl, tk, tl->t); return; } if (tk->tok == '+') *e = vcc_expr_edit(f2, "(\v1+\v2)", *e, e2); else if (f2 == TIME && e2->fmt == TIME) *e = vcc_expr_edit(DURATION, "(\v1-\v2)", *e, e2); else *e = vcc_expr_edit(f2, "(\v1-\v2)", *e, e2); } }
static void vcc_expr_add(struct vcc *tl, struct expr **e, enum var_type fmt) { struct expr *e2; enum var_type f2; struct token *tk; *e = NULL; vcc_expr_mul(tl, e, fmt); ERRCHK(tl); f2 = (*e)->fmt; /* Unless we specifically ask for a HEADER, fold them to string here */ if (fmt != HEADER && f2 == HEADER) { vcc_expr_tostring(tl, e, STRING); ERRCHK(tl); f2 = (*e)->fmt; assert(f2 == STRING); } if (tl->t->tok != '+' && tl->t->tok != '-') return; switch(f2) { case STRING: case STRING_LIST: vcc_expr_string_add(tl, e); return; case INT: break; case TIME: break; case DURATION: break; case BYTES: break; default: VSB_printf(tl->sb, "Operator %.*s not possible on type %s.\n", PF(tl->t), vcc_Type(f2)); vcc_ErrWhere(tl, tl->t); return; } while (tl->t->tok == '+' || tl->t->tok == '-') { if (f2 == TIME) f2 = DURATION; tk = tl->t; vcc_NextToken(tl); vcc_expr_mul(tl, &e2, f2); ERRCHK(tl); if (tk->tok == '-' && (*e)->fmt == TIME && e2->fmt == TIME) { /* OK */ } else if ((*e)->fmt == TIME && e2->fmt == DURATION) { f2 = TIME; /* OK */ } else if (tk->tok == '-' && (*e)->fmt == BYTES && e2->fmt == BYTES) { /* OK */ } else if (e2->fmt != f2) { VSB_printf(tl->sb, "%s %.*s %s not possible.\n", vcc_Type((*e)->fmt), PF(tk), vcc_Type(e2->fmt)); vcc_ErrWhere2(tl, tk, tl->t); return; } if (tk->tok == '+') *e = vcc_expr_edit(f2, "(\v1+\v2)", *e, e2); else if (f2 == TIME && e2->fmt == TIME) *e = vcc_expr_edit(DURATION, "(\v1-\v2)", *e, e2); else *e = vcc_expr_edit(f2, "(\v1-\v2)", *e, e2); } }