/* stop_at_name = TRUE is used when we check all names anyways. */ static gboolean do_expr_name_loop_check (char const *name, GnmNamedExpr *nexpr, /* One of these */ GnmExpr const *expr, gboolean stop_at_name) { switch (GNM_EXPR_GET_OPER (expr)) { case GNM_EXPR_OP_RANGE_CTOR: case GNM_EXPR_OP_INTERSECT: case GNM_EXPR_OP_ANY_BINARY: return (do_expr_name_loop_check (name, nexpr, expr->binary.value_a, stop_at_name) || do_expr_name_loop_check (name, nexpr, expr->binary.value_b, stop_at_name)); case GNM_EXPR_OP_ANY_UNARY: return do_expr_name_loop_check (name, nexpr, expr->unary.value, stop_at_name); case GNM_EXPR_OP_NAME: { GnmNamedExpr const *nexpr2 = expr->name.name; if (name && !strcmp (nexpr2->name->str, name)) return TRUE; if (nexpr == nexpr2) return TRUE; if (!stop_at_name && nexpr2->texpr != NULL) /* look inside this name tree too */ return expr_name_check_for_loop (name, nexpr2->texpr); return FALSE; } case GNM_EXPR_OP_FUNCALL: { int i; for (i = 0; i < expr->func.argc; i++) if (do_expr_name_loop_check (name, nexpr, expr->func.argv[i], stop_at_name)) return TRUE; break; } case GNM_EXPR_OP_CONSTANT: case GNM_EXPR_OP_CELLREF: case GNM_EXPR_OP_ARRAY_CORNER: case GNM_EXPR_OP_ARRAY_ELEM: break; case GNM_EXPR_OP_SET: { int i; for (i = 0; i < expr->set.argc; i++) if (do_expr_name_loop_check (name, nexpr, expr->set.argv[i], stop_at_name)) return TRUE; break; } } return FALSE; }
/** * global_range_list_parse: * @sheet: Sheet where the range specification is relatively parsed to * @str : a range or list of ranges to parse (ex: "A1", "A1:B1,C2,Sheet2!D2:D4") * * Parses a list of ranges, relative to the @sheet and returns a list with the * results. * * Returns a GSList containing Values of type VALUE_CELLRANGE, or NULL on failure **/ GSList * global_range_list_parse (Sheet *sheet, char const *str) { GnmParsePos pp; GnmExprTop const *texpr; GSList *ranges = NULL; GnmValue *v; g_return_val_if_fail (IS_SHEET (sheet), NULL); g_return_val_if_fail (str != NULL, NULL); texpr = gnm_expr_parse_str (str, parse_pos_init_sheet (&pp, sheet), GNM_EXPR_PARSE_FORCE_EXPLICIT_SHEET_REFERENCES | GNM_EXPR_PARSE_PERMIT_MULTIPLE_EXPRESSIONS | GNM_EXPR_PARSE_UNKNOWN_NAMES_ARE_STRINGS, NULL, NULL); if (texpr != NULL) { if (GNM_EXPR_GET_OPER (texpr->expr) == GNM_EXPR_OP_SET) { GnmExpr const *expr = texpr->expr; int i; for (i = 0; i < expr->set.argc; i++) { v = gnm_expr_get_range (expr->set.argv[i]); if (v == NULL) { range_list_destroy (ranges); ranges = NULL; break; } else ranges = g_slist_prepend (ranges, v); } } else { v = gnm_expr_top_get_range (texpr); if (v != NULL) ranges = g_slist_prepend (ranges, v); } gnm_expr_top_unref (texpr); } return g_slist_reverse (ranges); }