static void op_destroy(sdb_object_t *obj) { sdb_ast_op_t *op = SDB_AST_OP(obj); sdb_object_deref(SDB_OBJ(op->left)); sdb_object_deref(SDB_OBJ(op->right)); op->left = op->right = NULL; } /* op_destroy */
iter_error(sdb_strbuf_t *errbuf, sdb_ast_iter_t *iter, const char *reason, ...) { char r[1024]; va_list ap; va_start(ap, reason); vsnprintf(r, sizeof(r), reason, ap); va_end(ap); assert((iter->expr->type == SDB_AST_TYPE_OPERATOR) && (! SDB_AST_OP(iter->expr)->left)); sdb_strbuf_sprintf(errbuf, "Invalid iterator %s %s %s %s (%s)", SDB_AST_OP_TO_STRING(iter->kind), SDB_TYPE_TO_STRING(iter->iter->data_type), SDB_AST_OP_TO_STRING(SDB_AST_OP(iter->expr)->kind), SDB_TYPE_TO_STRING(SDB_AST_OP(iter->expr)->right->data_type), r); } /* iter_error */
sdb_ast_node_t * sdb_ast_op_create(int kind, sdb_ast_node_t *left, sdb_ast_node_t *right) { sdb_ast_op_t *op; op = SDB_AST_OP(sdb_object_create(SDB_AST_OP_TO_STRING(kind), op_type)); if (! op) return NULL; op->super.type = SDB_AST_TYPE_OPERATOR; op->kind = kind; op->left = left; op->right = right; return SDB_AST_NODE(op); } /* sdb_ast_op_create */
static int analyze_iter(int context, sdb_ast_iter_t *iter, sdb_strbuf_t *errbuf) { sdb_ast_const_t c = SDB_AST_CONST_INIT; int iter_context = context; int status; if (iter->iter->type == SDB_AST_TYPE_TYPED) iter_context = SDB_AST_TYPED(iter->iter)->type; if (analyze_node(iter_context, iter->iter, errbuf)) return -1; /* TODO: support other setups as well */ assert((iter->expr->type == SDB_AST_TYPE_OPERATOR) && (! SDB_AST_OP(iter->expr)->left)); /* determine the data-type for better error messages */ analyze_node(iter_context, SDB_AST_OP(iter->expr)->right, NULL); if (iter->iter->type == SDB_AST_TYPE_TYPED) { int iter_type = SDB_AST_TYPED(iter->iter)->type; c.value.type = iter->iter->data_type; if (iter_type == SDB_ATTRIBUTE) { /* attributes are always iterable */ } else if ((context != SDB_HOST) && (context != SDB_SERVICE) && (context != SDB_METRIC) && (context != UNSPEC_CONTEXT)) { iter_error(errbuf, iter, "%s not iterable in %s context", SDB_STORE_TYPE_TO_NAME(iter_type), SDB_STORE_TYPE_TO_NAME(context)); return -1; } if ((context == iter_type) || ((iter_type != SDB_SERVICE) && (iter_type != SDB_METRIC) && (iter_type != SDB_ATTRIBUTE)) || ((context == SDB_SERVICE) && (iter_type == SDB_METRIC)) || ((context == SDB_METRIC) && (iter_type == SDB_SERVICE))) { iter_error(errbuf, iter, "%s not iterable in %s context", SDB_STORE_TYPE_TO_NAME(iter_type), SDB_STORE_TYPE_TO_NAME(context)); return -1; } } else if (iter->iter->type == SDB_AST_TYPE_VALUE) { int iter_type = SDB_AST_VALUE(iter->iter)->type; c.value.type = iter->iter->data_type & 0xff; if (iter_type != SDB_FIELD_BACKEND) { iter_error(errbuf, iter, "%s not iterable in %s context", (iter_type == SDB_ATTRIBUTE) ? "attribute" : SDB_FIELD_TO_NAME(iter_type), SDB_STORE_TYPE_TO_NAME(context)); return -1; } } else if (iter->iter->type == SDB_AST_TYPE_CONST) { c.value.type = iter->iter->data_type & 0xff; if (! (SDB_AST_CONST(iter->iter)->value.type & SDB_TYPE_ARRAY)) { iter_error(errbuf, iter, "%s not iterable", SDB_TYPE_TO_STRING(SDB_AST_CONST(iter->iter)->value.type)); return -1; } } else { /* TODO: if we know the data-type of iter->iter and it's an array, * we should support an iterator for it as well */ iter_error(errbuf, iter, "%s expression not iterable", SDB_AST_TYPE_TO_STRING(iter->iter)); return -1; } SDB_AST_OP(iter->expr)->left = SDB_AST_NODE(&c); status = analyze_node(context, iter->expr, errbuf); SDB_AST_OP(iter->expr)->left = NULL; if (status) return -1; return 0; } /* analyze_iter */