~ubuntu-branches/ubuntu/feisty/gnumeric/feisty-security

« back to all changes in this revision

Viewing changes to src/expr.c

  • Committer: Bazaar Package Importer
  • Author(s): Gauvain Pocentek
  • Date: 2006-11-14 14:02:03 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20061114140203-iv3j2aii3vch6isl
Tags: 1.7.2-1ubuntu1
* Merge with debian experimental:
  - debian/control, debian/*-gtk-*, debian/rules,
    debian/shlibs.local: Xubuntu changes for
    gtk/gnome multibuild.
  - run intltool-update in po*
  - Build Depend on intltool

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
/*
3
3
 * expr.c : Expression evaluation in Gnumeric
4
4
 *
5
 
 * Copyright (C) 2001-2002 Jody Goldberg (jody@gnome.org)
 
5
 * Copyright (C) 2001-2006 Jody Goldberg (jody@gnome.org)
6
6
 * Copyright (C) 1998-2000 Miguel de Icaza (miguel@gnu.org)
7
7
 *
8
8
 * This program is free software; you can redistribute it and/or
20
20
 * USA
21
21
 */
22
22
#include <gnumeric-config.h>
23
 
#include <glib/gi18n.h>
 
23
#include <glib/gi18n-lib.h>
24
24
#include "gnumeric.h"
25
25
#include "expr.h"
26
26
 
851
851
        GnmValue *res;
852
852
        GnmValue const *a, *b;
853
853
        BinOpImplicitIteratorFunc       func;
 
854
 
 
855
        /* multiply by 0 in unused dimensions.
 
856
         * this is simpler than lots of conditions
 
857
         *      state->use_x.a ? x : 0
 
858
         **/
 
859
        struct {
 
860
                int a, b;
 
861
        } x, y;
854
862
        gpointer        user_data;
855
863
} BinOpImplicitIteratorState;
856
864
 
857
865
static GnmValue *
858
 
cb_implicit_iter_a_to_b (GnmValue const *v, GnmEvalPos const *ep,
 
866
cb_implicit_iter_a_and_b (GnmValue const *v, GnmEvalPos const *ep,
859
867
                         int x, int y, BinOpImplicitIteratorState const *state)
860
868
{
861
869
        state->res->v_array.vals [x][y] = (*state->func) (ep,
862
 
                v, value_area_get_x_y (state->b, x, y, ep), state->user_data);
 
870
                value_area_get_x_y (state->a, state->x.a * x, state->y.a * y, ep),
 
871
                value_area_get_x_y (state->b, state->x.b * x, state->y.b * y, ep),
 
872
                state->user_data);
863
873
        return NULL;
864
874
}
865
875
static GnmValue *
870
880
                v, state->b, state->user_data);
871
881
        return NULL;
872
882
}
 
883
 
 
884
/* This is only triggered if something returns an array or a range which can
 
885
 * only happen if we are in array eval mode. */
 
886
static GnmValue *
 
887
bin_array_iter_a (GnmEvalPos const *ep,
 
888
                  GnmValue *a, GnmValue *b,
 
889
                  BinOpImplicitIteratorFunc func,
 
890
                  GnmExpr const *expr)
 
891
{
 
892
        BinOpImplicitIteratorState iter_info;
 
893
        
 
894
        /* a must be a cellrange or array, it can not be NULL */
 
895
        iter_info.func = func;
 
896
        iter_info.user_data = (gpointer) expr;
 
897
        iter_info.a = a;
 
898
        iter_info.b = b;
 
899
 
 
900
        /* matrix to matrix
 
901
         * Use matching positions unless the dimension is singular, in which
 
902
         * case use the zero item
 
903
         * res[x][y] = f(a[singular.a.x ? 0 : x, b[singular.b.x ? 0 : x)
 
904
         *
 
905
         * If both items have non-singular sizes for
 
906
         * the same dimension use the min size (see samples/array.xls) */
 
907
        if (b != NULL &&
 
908
            (b->type == VALUE_CELLRANGE || b->type == VALUE_ARRAY)) {
 
909
                int sa, sb, w = 1, h = 1;
 
910
 
 
911
                sa = value_area_get_width  (a, ep);
 
912
                sb = value_area_get_width  (b, ep);
 
913
                if ((iter_info.x.a = (sa == 1) ? 0 : 1))
 
914
                        w = sa;
 
915
                if ((iter_info.x.b = (sb == 1) ? 0 : 1) && (w > sb || w == 1))
 
916
                        w = sb;
 
917
 
 
918
                sa = value_area_get_height  (a, ep);
 
919
                sb = value_area_get_height  (b, ep);
 
920
                if ((iter_info.y.a = (sa == 1) ? 0 : 1))
 
921
                        h = sa;
 
922
                if ((iter_info.y.b = (sb == 1) ? 0 : 1) && (h > sb || h == 1))
 
923
                        h = sb;
 
924
 
 
925
                iter_info.res = value_new_array_empty (w, h);
 
926
                value_area_foreach (iter_info.res, ep, CELL_ITER_ALL,
 
927
                        (ValueAreaFunc) cb_implicit_iter_a_and_b, &iter_info);
 
928
        } else {
 
929
                iter_info.res = value_new_array_empty (
 
930
                        value_area_get_width  (a, ep),
 
931
                        value_area_get_height (a, ep));
 
932
                value_area_foreach (a, ep, CELL_ITER_ALL,
 
933
                        (ValueAreaFunc) cb_implicit_iter_a_to_scalar_b, &iter_info);
 
934
        }
 
935
 
 
936
        value_release (a);
 
937
        if (b != NULL)
 
938
                value_release (b);
 
939
        return iter_info.res;
 
940
}
 
941
 
873
942
static GnmValue *
874
943
cb_implicit_iter_b_to_scalar_a (GnmValue const *v, GnmEvalPos const *ep,
875
944
                                int x, int y, BinOpImplicitIteratorState const *state)
878
947
                state->a, v, state->user_data);
879
948
        return NULL;
880
949
}
881
 
 
882
950
static GnmValue *
883
 
bin_array_op (GnmEvalPos const *ep, const GnmValue *sizer,
884
 
              GnmValue *a, GnmValue *b,
885
 
              BinOpImplicitIteratorFunc func, gpointer user_data)
 
951
bin_array_iter_b (GnmEvalPos const *ep,
 
952
                  GnmValue *a, GnmValue *b,
 
953
                  BinOpImplicitIteratorFunc func,
 
954
                  GnmExpr const *expr)
886
955
{
887
956
        BinOpImplicitIteratorState iter_info;
888
 
        
889
 
        if (sizer != a || b == NULL || !VALUE_IS_ERROR (b)) {
890
 
                iter_info.func = func;
891
 
                iter_info.user_data = user_data;
892
 
                iter_info.a = a;
893
 
                iter_info.b = b;
894
 
                iter_info.res = value_new_array_empty (
895
 
                        value_area_get_width  (sizer, ep),
896
 
                        value_area_get_height (sizer, ep));
897
 
                if (sizer == b)
898
 
                        value_area_foreach (b, ep, CELL_ITER_ALL,
899
 
                                (ValueAreaFunc) cb_implicit_iter_b_to_scalar_a, &iter_info);
900
 
                else if (b != NULL &&
901
 
                           (b->type == VALUE_CELLRANGE || b->type == VALUE_ARRAY))
902
 
                        value_area_foreach (a, ep, CELL_ITER_ALL,
903
 
                                (ValueAreaFunc) cb_implicit_iter_a_to_b, &iter_info);
904
 
                else
905
 
                        value_area_foreach (a, ep, CELL_ITER_ALL,
906
 
                                (ValueAreaFunc) cb_implicit_iter_a_to_scalar_b, &iter_info);
907
 
        } else
908
 
                /* you have to love the asymmetry of MS XL */
909
 
                iter_info.res = value_new_error_VALUE (ep);
 
957
 
 
958
        iter_info.func = func;
 
959
        iter_info.user_data = (gpointer) expr;
 
960
        iter_info.a = a;
 
961
        iter_info.b = b;
 
962
 
 
963
        /* b must be a cellrange or array, it can not be NULL */
 
964
        iter_info.res = value_new_array_empty (
 
965
                value_area_get_width  (b, ep),
 
966
                value_area_get_height (b, ep));
 
967
        value_area_foreach (b, ep, CELL_ITER_ALL,
 
968
                (ValueAreaFunc) cb_implicit_iter_b_to_scalar_a, &iter_info);
910
969
        if (a != NULL)
911
970
                value_release (a);
912
 
        if (b != NULL)
913
 
                value_release (b);
 
971
        value_release (b);
 
972
 
914
973
        return iter_info.res;
915
974
}
916
975
 
1052
1111
                        if (VALUE_IS_ERROR (a))
1053
1112
                                return a;
1054
1113
                        if (a->type == VALUE_CELLRANGE || a->type == VALUE_ARRAY)
1055
 
                                return bin_array_op (pos, a, a,
 
1114
                                return bin_array_iter_a (pos, a,
1056
1115
                                        gnm_expr_eval (expr->binary.value_b, pos, flags),
1057
1116
                                        (BinOpImplicitIteratorFunc) cb_bin_cmp,
1058
 
                                        (gpointer) expr);
 
1117
                                        expr);
1059
1118
                }
1060
1119
 
1061
1120
                b = gnm_expr_eval (expr->binary.value_b, pos, flags);
1066
1125
                                return b;
1067
1126
                        }
1068
1127
                        if (b->type == VALUE_CELLRANGE || b->type == VALUE_ARRAY)
1069
 
                                return bin_array_op (pos, b, a, b,
 
1128
                                return bin_array_iter_b (pos, a, b,
1070
1129
                                        (BinOpImplicitIteratorFunc) cb_bin_cmp,
1071
 
                                        (gpointer) expr);
 
1130
                                        expr);
1072
1131
                }
1073
1132
 
1074
1133
                res = bin_cmp (GNM_EXPR_GET_OPER (expr), value_compare (a, b, FALSE), pos);
1117
1176
                                value_release (b);
1118
1177
                                b = (res == NULL) ? value_new_error_VALUE (pos) : res;
1119
1178
                        }
1120
 
                        return bin_array_op (pos, a, a, b,
 
1179
                        return bin_array_iter_a (pos, a, b,
1121
1180
                                (BinOpImplicitIteratorFunc) cb_bin_arith,
1122
 
                                (gpointer) expr);
 
1181
                                expr);
1123
1182
                } else if (!VALUE_IS_NUMBER (a)) {
1124
1183
                        value_release (a);
1125
1184
                        return value_new_error_VALUE (pos);
1144
1203
                        }
1145
1204
                        b = tmp;
1146
1205
                } else if (b->type == VALUE_CELLRANGE || b->type == VALUE_ARRAY)
1147
 
                        return bin_array_op (pos, b, a, b,
 
1206
                        return bin_array_iter_b (pos, a, b,
1148
1207
                                (BinOpImplicitIteratorFunc) cb_bin_arith,
1149
 
                                (gpointer) expr);
 
1208
                                expr);
1150
1209
                else if (!VALUE_IS_NUMBER (b)) {
1151
1210
                        value_release (a);
1152
1211
                        value_release (b);
1209
1268
                        if (VALUE_IS_ERROR (a))
1210
1269
                                return a;
1211
1270
                        if (a->type == VALUE_CELLRANGE || a->type == VALUE_ARRAY)
1212
 
                                return bin_array_op (pos, a, a,
 
1271
                                return bin_array_iter_a (pos, a,
1213
1272
                                        gnm_expr_eval (expr->binary.value_b, pos, flags),
1214
1273
                                        (BinOpImplicitIteratorFunc) cb_bin_cat,
1215
 
                                        (gpointer) expr);
 
1274
                                        expr);
1216
1275
                }
1217
1276
                b = gnm_expr_eval (expr->binary.value_b, pos, flags);
1218
1277
                if (b != NULL) {
1222
1281
                                return b;
1223
1282
                        }
1224
1283
                        if (b->type == VALUE_CELLRANGE || b->type == VALUE_ARRAY)
1225
 
                                return bin_array_op (pos, b, a, b,
 
1284
                                return bin_array_iter_b (pos, a, b,
1226
1285
                                        (BinOpImplicitIteratorFunc) cb_bin_cat,
1227
 
                                        (gpointer) expr);
 
1286
                                        expr);
1228
1287
                }
1229
1288
 
1230
1289
                if (a == NULL) {
1366
1425
                return handle_empty ((a != NULL) ? value_dup (a) : NULL, flags);
1367
1426
        }
1368
1427
        case GNM_EXPR_OP_SET:
 
1428
                if (flags & GNM_EXPR_EVAL_PERMIT_NON_SCALAR) {
 
1429
                        int i;
 
1430
                        int argc = expr->set.argc;
 
1431
 
 
1432
                        res = value_new_array_non_init (1, expr->set.argc);
 
1433
                        res->v_array.vals[0] = g_new (GnmValue *, expr->set.argc);
 
1434
                        for (i = 0; i < argc; i++)
 
1435
                                res->v_array.vals[0][i] = gnm_expr_eval (
 
1436
                                        expr->set.argv[i], pos,
 
1437
                                        GNM_EXPR_EVAL_SCALAR_NON_EMPTY);
 
1438
                        return res;
 
1439
                }
1369
1440
                return value_new_error_VALUE (pos);
1370
1441
 
1371
1442
        case GNM_EXPR_OP_RANGE_CTOR:
1378
1449
 
1379
1450
static void
1380
1451
gnm_expr_list_as_string (GString *target,
1381
 
                         int argc, const GnmExprConstPtr *argv,
 
1452
                         int argc, GnmExprConstPtr const *argv,
1382
1453
                         GnmParsePos const *pp,
1383
1454
                         GnmExprConventions const *fmt);
1384
1455
 
1480
1551
        }
1481
1552
 
1482
1553
        case GNM_EXPR_OP_FUNCALL: {
1483
 
                const GnmExprFunction *func = &expr->func;
 
1554
                GnmExprFunction const *func = &expr->func;
1484
1555
                char const *name = gnm_func_get_name (func->func);
1485
1556
 
1486
1557
                g_string_append (target, name);
1575
1646
        CELLREF_RELOCATE_FROM_OUT,
1576
1647
        CELLREF_RELOCATE_ERR
1577
1648
} CellRefRelocate;
1578
 
 
1579
 
/*
1580
 
 * FIXME :
1581
 
 * C3 : =sum(a$1:b$2)
1582
 
 * Cut B2:C3
1583
 
 * Paste to the right or diagonal.
1584
 
 * range changes when it should not.
1585
 
 */
1586
1649
static CellRefRelocate
1587
 
cellref_relocate (GnmCellRef *ref, GnmExprRelocateInfo const *rinfo)
 
1650
relocate_cellref (GnmExprRelocateInfo const *rinfo, gboolean ignore_rel,
 
1651
                  GnmCellRef *ref)
 
1652
 
1588
1653
{
1589
1654
        /* For row or column refs
1590
1655
         * Ref  From    To
1612
1677
        int row = ref->row;
1613
1678
        Sheet *ref_sheet = (ref->sheet != NULL) ? ref->sheet : rinfo->pos.sheet;
1614
1679
 
1615
 
        if (ref->col_relative)
 
1680
        if (ref->col_relative) {
1616
1681
                col += rinfo->pos.eval.col;
1617
 
        if (ref->row_relative)
 
1682
        }
 
1683
        if (ref->row_relative) {
1618
1684
                row += rinfo->pos.eval.row;
 
1685
        }
1619
1686
 
1620
1687
        /* fprintf (stderr, "%s\n", cellref_as_string (ref, &rinfo->pos, FALSE)); */
1621
1688
 
1710
1777
}
1711
1778
 
1712
1779
static GnmExpr const *
1713
 
cellrange_relocate (GnmValue const *v, GnmExprRelocateInfo const *rinfo)
 
1780
relocate_cellrange (GnmExprRelocateInfo const *rinfo, gboolean ignore_rel,
 
1781
                    GnmValueRange const *v)
1714
1782
{
 
1783
        GnmCellRef ref_a = v->cell.a;
 
1784
        GnmCellRef ref_b = v->cell.b;
 
1785
        int reloc_a, reloc_b;
 
1786
 
 
1787
        if (rinfo->reloc_type == GNM_EXPR_RELOCATE_INVALIDATE_SHEET) {
 
1788
                Sheet const *sheet_a = ref_a.sheet;
 
1789
                Sheet const *sheet_b = ref_b.sheet;
 
1790
                Workbook *wb;
 
1791
                gboolean hit_a = sheet_a && sheet_a->being_invalidated;
 
1792
                gboolean hit_b = sheet_b && sheet_b->being_invalidated;
 
1793
                int dir;
 
1794
 
 
1795
                if (!hit_a && !hit_b)
 
1796
                        return NULL;
 
1797
 
 
1798
                if (sheet_a == NULL || sheet_b == NULL ||
 
1799
                    sheet_a->workbook != sheet_b->workbook)
 
1800
                        /* A 3D reference between workbooks?  */
 
1801
                        return gnm_expr_new_constant (value_new_error_REF (NULL));
 
1802
 
 
1803
                /* Narrow the sheet range.  */
 
1804
                wb = sheet_a->workbook;
 
1805
                dir = (sheet_a->index_in_wb < sheet_b->index_in_wb) ? +1 : -1;
 
1806
                while (sheet_a != sheet_b && sheet_a->being_invalidated)
 
1807
                        sheet_a = workbook_sheet_by_index (wb, sheet_a->index_in_wb + dir);
 
1808
                while (sheet_a != sheet_b && sheet_b->being_invalidated)
 
1809
                        sheet_b = workbook_sheet_by_index (wb, sheet_b->index_in_wb - dir);
 
1810
 
 
1811
                if (sheet_a->being_invalidated)
 
1812
                        return gnm_expr_new_constant (value_new_error_REF (NULL));
 
1813
 
 
1814
                ref_a.sheet = (Sheet *)sheet_a;
 
1815
                ref_b.sheet = (Sheet *)sheet_b;
 
1816
                return gnm_expr_new_constant (value_new_cellrange_unsafe (&ref_a, &ref_b));
 
1817
        }
 
1818
 
 
1819
        /* FIXME : should not be necessary.  We need to audit the code to
 
1820
         * define whether both refs need a sheet, or just ref_a for normal
 
1821
         * non-3d references */
 
1822
        if (ref_b.sheet == NULL && ref_a.sheet != NULL)
 
1823
                ref_b.sheet = ref_a.sheet;
 
1824
 
 
1825
        reloc_a = relocate_cellref (rinfo, ignore_rel, &ref_a);
 
1826
        reloc_b = relocate_cellref (rinfo, ignore_rel, &ref_b);
 
1827
 
1715
1828
        /*
1716
1829
         * If either end is an error then the whole range is an error.
1717
1830
         * If both ends need to relocate -> relocate
1721
1834
         *      in only 1 dimension, and the
1722
1835
         * otherwise remain static
1723
1836
         */
1724
 
        GnmCellRef ref_a = v->v_range.cell.a;
1725
 
        GnmCellRef ref_b = v->v_range.cell.b;
1726
 
        int needs = 0;
1727
 
 
1728
 
        /* FIXME : should not be necessary.  We need to audit the code to
1729
 
         * define whether both refs need a sheet, or just ref_a for normal
1730
 
         * non-3d references */
1731
 
        if (ref_b.sheet == NULL && ref_a.sheet != NULL)
1732
 
                ref_b.sheet = ref_a.sheet;
1733
 
 
1734
 
        switch (cellref_relocate (&ref_a, rinfo)) {
1735
 
        case CELLREF_NO_RELOCATE :      break;
1736
 
        case CELLREF_RELOCATE_FROM_IN :  needs = 0x4;   break;
1737
 
        case CELLREF_RELOCATE_FROM_OUT : needs = 0x1;   break;
1738
 
        case CELLREF_RELOCATE_ERR : return gnm_expr_new_constant (
1739
 
                value_new_error_REF (NULL));
1740
 
        }
1741
 
        switch (cellref_relocate (&ref_b, rinfo)) {
1742
 
        case CELLREF_NO_RELOCATE :      break;
1743
 
        case CELLREF_RELOCATE_FROM_IN :  needs = 0x4;   break;
1744
 
        case CELLREF_RELOCATE_FROM_OUT : needs |= 0x2;  break;
1745
 
        case CELLREF_RELOCATE_ERR :
1746
 
#if 0
1747
 
                if (needs == 0 &&
1748
 
                    (rinfo->col_offset == 0 || rinfo->row_offset == 0)) {
1749
 
                }
1750
 
#endif
1751
 
                return gnm_expr_new_constant (
1752
 
                        value_new_error_REF (NULL));
1753
 
        }
1754
 
 
1755
 
        if (needs != 0) {
 
1837
 
 
1838
        /*
 
1839
         * FIXME :
 
1840
         * C3 : =sum(a$1:b$2)
 
1841
         * Cut B2:C3
 
1842
         * Paste to the right or diagonal.
 
1843
         * range changes when it should not.
 
1844
         */
 
1845
        if (!reloc_a || !reloc_b) {
1756
1846
                GnmValue *res;
1757
1847
                Sheet const *sheet_a = ref_a.sheet;
1758
1848
                Sheet const *sheet_b = ref_b.sheet;
1766
1856
                /* Dont allow creation of 3D references */
1767
1857
                if (sheet_a == sheet_b) {
1768
1858
                        /* If just 1 end is moving do not change the reference */
1769
 
                        if ((needs == 0x1 && cellref_shift (&ref_b, rinfo)) ||
1770
 
                            (needs == 0x2 && cellref_shift (&ref_a, rinfo)))
 
1859
                        if ((reloc_a == CELLREF_RELOCATE_FROM_OUT &&
 
1860
                             cellref_shift (&ref_b, rinfo)) ||
 
1861
                            (reloc_b == CELLREF_RELOCATE_FROM_OUT &&
 
1862
                             cellref_shift (&ref_a, rinfo)))
1771
1863
                                return NULL;
1772
1864
                        res = value_new_cellrange (&ref_a, &ref_b,
1773
 
                                                   rinfo->pos.eval.col,
1774
 
                                                   rinfo->pos.eval.row);
 
1865
                                rinfo->pos.eval.col + rinfo->col_offset,
 
1866
                                rinfo->pos.eval.row + rinfo->row_offset);
1775
1867
                } else
1776
1868
                        res = value_new_error_REF (NULL);
1777
1869
 
1781
1873
        return NULL;
1782
1874
}
1783
1875
 
1784
 
/*
1785
 
 * gnm_expr_rewrite :
1786
 
 * @expr   : Expression to fixup
1787
 
 * @pos    : Location of the cell containing @expr.
1788
 
 * @rwinfo : State information required to rewrite the reference.
1789
 
 *
1790
 
 * Either:
1791
 
 *
1792
 
 * GNM_EXPR_REWRITE_INVALIDATE_SHEETS:
1793
 
 *
1794
 
 *      Find any references to sheets marked being_invalidated and
1795
 
 *      re-write them to #REF!
1796
 
 *
1797
 
 * or
1798
 
 *
1799
 
 * GNM_EXPR_REWRITE_RELOCATE:
1800
 
 *
1801
 
 *      Find any references to the specified area and adjust them by the
1802
 
 * supplied deltas.  Check for out of bounds conditions.  Return NULL if
1803
 
 * no change is required.
1804
 
 *
1805
 
 *      If the expression is within the range to be moved, its relative
1806
 
 * references to cells outside the range are adjusted to reference the
1807
 
 * same cell after the move.
1808
 
 */
1809
1876
static GnmExpr const *
1810
 
gnm_expr_rewrite (GnmExpr const *expr, GnmExprRewriteInfo const *rwinfo)
 
1877
gnm_expr_relocate (GnmExpr const *expr, GnmExprRelocateInfo const *rinfo,
 
1878
                   gboolean ignore_rel)
1811
1879
{
1812
1880
        g_return_val_if_fail (expr != NULL, NULL);
1813
1881
 
1815
1883
        case GNM_EXPR_OP_RANGE_CTOR:
1816
1884
        case GNM_EXPR_OP_INTERSECT:
1817
1885
        case GNM_EXPR_OP_ANY_BINARY: {
1818
 
                GnmExpr const *a = gnm_expr_rewrite (expr->binary.value_a, rwinfo);
1819
 
                GnmExpr const *b = gnm_expr_rewrite (expr->binary.value_b, rwinfo);
 
1886
                GnmExpr const *a = gnm_expr_relocate (expr->binary.value_a, rinfo, ignore_rel);
 
1887
                GnmExpr const *b = gnm_expr_relocate (expr->binary.value_b, rinfo, ignore_rel);
1820
1888
 
1821
1889
                if (a == NULL && b == NULL)
1822
1890
                        return NULL;
1830
1898
        }
1831
1899
 
1832
1900
        case GNM_EXPR_OP_ANY_UNARY: {
1833
 
                GnmExpr const *a = gnm_expr_rewrite (expr->unary.value, rwinfo);
 
1901
                GnmExpr const *a = gnm_expr_relocate (expr->unary.value, rinfo, ignore_rel);
1834
1902
                if (a == NULL)
1835
1903
                        return NULL;
1836
1904
                return gnm_expr_new_unary (GNM_EXPR_GET_OPER (expr), a);
1844
1912
                        argc ? g_new (GnmExprConstPtr, argc) : NULL;
1845
1913
 
1846
1914
                for (i = 0; i < argc; i++) {
1847
 
                        argv[i] = gnm_expr_rewrite (expr->func.argv[i], rwinfo);
 
1915
                        argv[i] = gnm_expr_relocate (expr->func.argv[i], rinfo, ignore_rel);
1848
1916
                        if (argv[i])
1849
1917
                                rewrite = TRUE;
1850
1918
                }
1870
1938
                        argc ? g_new (GnmExprConstPtr, argc) : NULL;
1871
1939
 
1872
1940
                for (i = 0; i < argc; i++) {
1873
 
                        argv[i] = gnm_expr_rewrite (expr->set.argv[i], rwinfo);
 
1941
                        argv[i] = gnm_expr_relocate (expr->set.argv[i], rinfo, ignore_rel);
1874
1942
                        if (argv[i])
1875
1943
                                rewrite = TRUE;
1876
1944
                }
1897
1965
                if (!nexpr->active)
1898
1966
                        return gnm_expr_new_constant (value_new_error_REF (NULL));
1899
1967
 
1900
 
                if (rwinfo->rw_type == GNM_EXPR_REWRITE_INVALIDATE_SHEETS) {
 
1968
                if (rinfo->reloc_type == GNM_EXPR_RELOCATE_INVALIDATE_SHEET) {
1901
1969
                        if (nexpr->pos.sheet && nexpr->pos.sheet->being_invalidated)
1902
1970
                                return gnm_expr_new_constant (value_new_error_REF (NULL));
1903
1971
                        else
1907
1975
                /* If the name is not officially scoped, check that it is
1908
1976
                 * available in the new scope ?  */
1909
1977
                if (expr->name.optional_scope == NULL &&
1910
 
                    rwinfo->u.relocate.target_sheet != rwinfo->u.relocate.origin_sheet) {
 
1978
                    rinfo->target_sheet != rinfo->origin_sheet) {
1911
1979
                        GnmNamedExpr *new_nexpr;
1912
1980
                        GnmParsePos pos;
1913
 
                        parse_pos_init_sheet (&pos,
1914
 
                                rwinfo->u.relocate.target_sheet);
 
1981
                        parse_pos_init_sheet (&pos, rinfo->target_sheet);
1915
1982
 
1916
1983
                        /* If the name is not available in the new scope explicitly scope it */
1917
1984
                        new_nexpr = expr_name_lookup (&pos, nexpr->name->str);
1928
1995
                }
1929
1996
 
1930
1997
                /* Do NOT rewrite the name.  Just invalidate the use of the name */
1931
 
                tmp = gnm_expr_top_rewrite (expr->name.name->texpr, rwinfo);
 
1998
                tmp = gnm_expr_top_relocate (expr->name.name->texpr, rinfo, FALSE);
1932
1999
                if (tmp != NULL) {
1933
2000
                        gnm_expr_top_unref (tmp);
1934
2001
                        return gnm_expr_new_constant (
1939
2006
        }
1940
2007
 
1941
2008
        case GNM_EXPR_OP_CELLREF:
1942
 
                switch (rwinfo->rw_type) {
1943
 
                case GNM_EXPR_REWRITE_INVALIDATE_SHEETS:
 
2009
                switch (rinfo->reloc_type) {
 
2010
                case GNM_EXPR_RELOCATE_INVALIDATE_SHEET:
1944
2011
                        if (expr->cellref.ref.sheet &&
1945
2012
                            expr->cellref.ref.sheet->being_invalidated)
1946
2013
                                return gnm_expr_new_constant (value_new_error_REF (NULL));
1947
2014
                        return NULL;
1948
2015
 
1949
 
                case GNM_EXPR_REWRITE_NAME:
1950
2016
                default : {
1951
2017
                        GnmCellRef res = expr->cellref.ref; /* Copy */
1952
2018
 
1953
 
                        switch (cellref_relocate (&res, &rwinfo->u.relocate)) {
 
2019
                        switch (relocate_cellref (rinfo, ignore_rel, &res)) {
1954
2020
                        case CELLREF_NO_RELOCATE :
1955
2021
                                return NULL;
1956
2022
                        case CELLREF_RELOCATE_FROM_IN :
1963
2029
                }
1964
2030
                return NULL;
1965
2031
 
1966
 
        case GNM_EXPR_OP_CONSTANT: {
1967
 
                GnmValue const *v = expr->constant.value;
1968
 
 
1969
 
                if (v->type == VALUE_CELLRANGE) {
1970
 
                        GnmCellRef const *ref_a = &v->v_range.cell.a;
1971
 
                        GnmCellRef const *ref_b = &v->v_range.cell.b;
1972
 
 
1973
 
                        if (rwinfo->rw_type == GNM_EXPR_REWRITE_INVALIDATE_SHEETS) {
1974
 
                                Sheet *sheet_a = ref_a->sheet;
1975
 
                                Sheet *sheet_b = ref_b->sheet;
1976
 
                                Workbook *wb;
1977
 
                                gboolean hit_a = sheet_a && sheet_a->being_invalidated;
1978
 
                                gboolean hit_b = sheet_b && sheet_b->being_invalidated;
1979
 
                                int dir_a, dir_b;
1980
 
 
1981
 
                                if (!hit_a && !hit_b)
1982
 
                                        return NULL;
1983
 
 
1984
 
                                if (sheet_a == NULL || sheet_b == NULL ||
1985
 
                                    sheet_a->workbook != sheet_b->workbook)
1986
 
                                        /* A 3D reference between workbooks?  */
1987
 
                                        return gnm_expr_new_constant (value_new_error_REF (NULL));
1988
 
 
1989
 
                                wb = sheet_a->workbook;
1990
 
                                dir_a = (sheet_a->index_in_wb < sheet_b->index_in_wb) ? +1 : -1;
1991
 
                                dir_b = -dir_a;
1992
 
                                /* Narrow the sheet range.  */
1993
 
                                while (sheet_a != sheet_b && sheet_a->being_invalidated)
1994
 
                                        sheet_a = workbook_sheet_by_index (wb, sheet_a->index_in_wb + dir_a);
1995
 
                                while (sheet_a != sheet_b && sheet_b->being_invalidated)
1996
 
                                        sheet_b = workbook_sheet_by_index (wb, sheet_b->index_in_wb + dir_b);
1997
 
 
1998
 
                                if (sheet_a->being_invalidated)
1999
 
                                        return gnm_expr_new_constant (value_new_error_REF (NULL));
2000
 
                                else {
2001
 
                                        GnmCellRef new_a = *ref_a;
2002
 
                                        GnmCellRef new_b = *ref_b;
2003
 
 
2004
 
                                        new_a.sheet = sheet_a;
2005
 
                                        new_b.sheet = sheet_b;
2006
 
                                        return gnm_expr_new_constant (value_new_cellrange_unsafe (&new_a, &new_b));
2007
 
                                }
2008
 
                        } else
2009
 
                                return cellrange_relocate (v, &rwinfo->u.relocate);
2010
 
                }
2011
 
 
 
2032
        case GNM_EXPR_OP_CONSTANT:
 
2033
                if (expr->constant.value->type == VALUE_CELLRANGE)
 
2034
                        return relocate_cellrange (rinfo, ignore_rel,
 
2035
                                &expr->constant.value->v_range);
2012
2036
                return NULL;
2013
 
        }
2014
2037
 
2015
2038
        case GNM_EXPR_OP_ARRAY_ELEM:
2016
2039
                return NULL;
2017
2040
 
2018
2041
        case GNM_EXPR_OP_ARRAY_CORNER: {
2019
 
                GnmExpr const *e =
2020
 
                        gnm_expr_rewrite (expr->array_corner.expr, rwinfo);
 
2042
                GnmExpr const *e = gnm_expr_relocate (expr->array_corner.expr, rinfo, ignore_rel);
2021
2043
                if (e)
2022
 
                        return gnm_expr_new_array_corner
2023
 
                                (expr->array_corner.cols,
2024
 
                                 expr->array_corner.rows,
2025
 
                                 e);
 
2044
                        return gnm_expr_new_array_corner (
 
2045
                                expr->array_corner.cols,
 
2046
                                expr->array_corner.rows, e);
2026
2047
                return NULL;
2027
2048
        }
2028
2049
        }
2445
2466
 
2446
2467
static void
2447
2468
gnm_expr_list_as_string (GString *target,
2448
 
                         int argc, const GnmExprConstPtr *argv,
 
2469
                         int argc, GnmExprConstPtr const *argv,
2449
2470
                         GnmParsePos const *pp,
2450
2471
                         GnmExprConventions const *conv)
2451
2472
{
2469
2490
        g_string_append_c (target, ')');
2470
2491
}
2471
2492
 
2472
 
/***************************************************************************/
2473
 
 
2474
 
/*
2475
 
 * Special hash function for expressions that assumes that equal
2476
 
 * sub-expressions are pointer-equal.  (Thus no need for recursion.)
2477
 
 */
2478
2493
static guint
2479
 
ets_hash (gconstpointer key)
 
2494
gnm_expr_hash (GnmExpr const *expr)
2480
2495
{
2481
 
        GnmExpr const *expr = (GnmExpr const *)key;
2482
2496
        guint h = (guint)(GNM_EXPR_GET_OPER (expr));
2483
2497
 
2484
2498
        switch (GNM_EXPR_GET_OPER (expr)){
2485
2499
        case GNM_EXPR_OP_INTERSECT:
2486
2500
        case GNM_EXPR_OP_RANGE_CTOR:
2487
2501
        case GNM_EXPR_OP_ANY_BINARY:
2488
 
                return ((GPOINTER_TO_UINT (expr->binary.value_a) * 7) ^
2489
 
                        (GPOINTER_TO_UINT (expr->binary.value_b) * 3) ^
 
2502
                return ((gnm_expr_hash (expr->binary.value_a) * 7) ^
 
2503
                        (gnm_expr_hash (expr->binary.value_b) * 3) ^
2490
2504
                        h);
2491
2505
 
2492
2506
        case GNM_EXPR_OP_ANY_UNARY:
2493
 
                return ((GPOINTER_TO_UINT (expr->unary.value) * 7) ^
 
2507
                return ((gnm_expr_hash (expr->unary.value) * 7) ^
2494
2508
                        h);
2495
2509
 
2496
2510
        case GNM_EXPR_OP_FUNCALL: {
2497
2511
                int i;
2498
2512
                for (i = 0; i < expr->func.argc; i++)
2499
 
                        h = (h * 3) ^ (GPOINTER_TO_UINT (expr->func.argv[i]));
 
2513
                        h = (h * 3) ^ gnm_expr_hash (expr->func.argv[i]);
2500
2514
                return h;
2501
2515
        }
2502
2516
 
2503
2517
        case GNM_EXPR_OP_SET: {
2504
2518
                int i;
2505
2519
                for (i = 0; i < expr->set.argc; i++)
2506
 
                        h = (h * 3) ^ (GPOINTER_TO_UINT (expr->set.argv[i]));
 
2520
                        h = (h * 3) ^ gnm_expr_hash (expr->set.argv[i]);
2507
2521
                return h;
2508
2522
        }
2509
2523
 
2512
2526
 
2513
2527
        case GNM_EXPR_OP_NAME:
2514
2528
                /* all we need is a somewhat unique hash, ignore int != ptr */
2515
 
                return (guint)(expr->name.name);
 
2529
                return GPOINTER_TO_UINT (expr->name.name);
2516
2530
 
2517
2531
        case GNM_EXPR_OP_CELLREF:
2518
2532
                return gnm_cellref_hash (&expr->cellref.ref);
2519
2533
 
2520
2534
        case GNM_EXPR_OP_ARRAY_CORNER:
2521
 
                return ((GPOINTER_TO_UINT (expr->array_corner.expr) * 7) ^
2522
 
                        h);
2523
 
                break;
 
2535
                return gnm_expr_hash (expr->array_corner.expr);
 
2536
 
2524
2537
        case GNM_EXPR_OP_ARRAY_ELEM:
2525
 
                return ((expr->array_elem.x * 7) ^
2526
 
                        (expr->array_elem.y * 3));
 
2538
                return ((expr->array_elem.x << 16) ^
 
2539
                        (expr->array_elem.y));
2527
2540
        }
 
2541
 
2528
2542
        return h;
2529
2543
}
2530
2544
 
2531
 
/*
2532
 
 * Special equality function for expressions that assumes that equal
2533
 
 * sub-expressions are pointer-equal.  (Thus no need for recursion.)
2534
 
 */
2535
 
static gboolean
2536
 
ets_equal (gconstpointer _a, gconstpointer _b)
2537
 
{
2538
 
        GnmExpr const *ea = _a;
2539
 
        GnmExpr const *eb = _b;
2540
 
 
2541
 
        if (GNM_EXPR_GET_OPER (ea) != GNM_EXPR_GET_OPER (eb))
2542
 
                return FALSE;
2543
 
 
2544
 
        switch (GNM_EXPR_GET_OPER (ea)) {
2545
 
        case GNM_EXPR_OP_RANGE_CTOR:
2546
 
        case GNM_EXPR_OP_INTERSECT:
2547
 
        case GNM_EXPR_OP_ANY_BINARY:
2548
 
                return (ea->binary.value_a == eb->binary.value_a &&
2549
 
                        ea->binary.value_b == eb->binary.value_b);
2550
 
        case GNM_EXPR_OP_ANY_UNARY:
2551
 
                return (ea->unary.value == eb->unary.value);
2552
 
        case GNM_EXPR_OP_FUNCALL: {
2553
 
                int i;
2554
 
 
2555
 
                if (ea->func.func != eb->func.func ||
2556
 
                    ea->func.argc != eb->func.argc)
2557
 
                        return FALSE;
2558
 
 
2559
 
                for (i = 0; i < ea->func.argc; i++)
2560
 
                        if (ea->func.argv[i] != eb->func.argv[i])
2561
 
                                return FALSE;
2562
 
                return TRUE;
2563
 
        }
2564
 
                                        
2565
 
        case GNM_EXPR_OP_SET: {
2566
 
                int i;
2567
 
 
2568
 
                if (ea->set.argc != eb->set.argc)
2569
 
                        return FALSE;
2570
 
 
2571
 
                for (i = 0; i < ea->set.argc; i++)
2572
 
                        if (ea->set.argv[i] != eb->set.argv[i])
2573
 
                                return FALSE;
2574
 
                return TRUE;
2575
 
        }
2576
 
 
2577
 
        default:
2578
 
                /* No sub-expressions.  */
2579
 
                return gnm_expr_equal (ea, eb);
2580
 
        }
2581
 
}
2582
 
 
2583
 
 
2584
 
ExprTreeSharer *
2585
 
expr_tree_sharer_new (void)
2586
 
{
2587
 
        ExprTreeSharer *es = g_new (ExprTreeSharer, 1);
2588
 
        es->nodes_in = es->nodes_stored = 0;
2589
 
        es->exprs = g_hash_table_new (ets_hash, ets_equal);
2590
 
        es->ptrs = g_hash_table_new (g_direct_hash, g_direct_equal);
 
2545
 
 
2546
/***************************************************************************/
 
2547
 
 
2548
GnmExprSharer *
 
2549
gnm_expr_sharer_new (void)
 
2550
{
 
2551
        GnmExprSharer *es = g_new (GnmExprSharer, 1);
 
2552
        es->nodes_in = 0;
 
2553
        es->nodes_stored = 0;
 
2554
        es->nodes_killed = 0;
 
2555
        es->exprs = g_hash_table_new_full
 
2556
                ((GHashFunc)gnm_expr_top_hash,
 
2557
                 (GEqualFunc)gnm_expr_top_equal,
 
2558
                 (GDestroyNotify)gnm_expr_top_unref,
 
2559
                 NULL);
2591
2560
        return es;
2592
2561
}
2593
2562
 
2594
 
static void
2595
 
cb_ets_unref_key (gpointer key, G_GNUC_UNUSED gpointer value,
2596
 
                  G_GNUC_UNUSED gpointer user_data)
2597
 
{
2598
 
        GnmExpr *e = key;
2599
 
        gnm_expr_free (e);
2600
 
}
2601
 
 
2602
 
 
2603
2563
void
2604
 
expr_tree_sharer_destroy (ExprTreeSharer *es)
 
2564
gnm_expr_sharer_destroy (GnmExprSharer *es)
2605
2565
{
2606
 
        g_hash_table_foreach (es->exprs, cb_ets_unref_key, NULL);
2607
2566
        g_hash_table_destroy (es->exprs);
2608
 
        g_hash_table_foreach (es->ptrs, cb_ets_unref_key, NULL);
2609
 
        g_hash_table_destroy (es->ptrs);
2610
2567
        g_free (es);
2611
2568
}
2612
2569
 
2613
 
GnmExpr const *
2614
 
expr_tree_sharer_share (ExprTreeSharer *es, GnmExpr const *e)
 
2570
GnmExprTop const *
 
2571
gnm_expr_sharer_share (GnmExprSharer *es, GnmExprTop const *texpr)
2615
2572
{
2616
 
        return e;
 
2573
        GnmExprTop const *shared;
 
2574
 
 
2575
        g_return_val_if_fail (es != NULL, texpr);
 
2576
        g_return_val_if_fail (texpr != NULL, NULL);
 
2577
 
 
2578
        es->nodes_in++;
 
2579
 
 
2580
        /* Corners must not get shared.  */
 
2581
        if (GNM_EXPR_GET_OPER (texpr->expr) == GNM_EXPR_OP_ARRAY_CORNER)
 
2582
                return texpr;
 
2583
 
 
2584
        shared = g_hash_table_lookup (es->exprs, texpr);
 
2585
        if (shared) {
 
2586
                gnm_expr_top_ref (shared);
 
2587
                if (texpr->refcount == 1)
 
2588
                        es->nodes_killed++;
 
2589
                gnm_expr_top_unref (texpr);
 
2590
                return shared;
 
2591
        }
 
2592
 
 
2593
        gnm_expr_top_ref (texpr);
 
2594
        g_hash_table_insert (es->exprs, (gpointer)texpr, (gpointer)texpr);
 
2595
        es->nodes_stored++;
 
2596
 
 
2597
        return texpr;
2617
2598
}
2618
2599
 
2619
2600
/***************************************************************************/
2628
2609
 
2629
2610
        res = g_new (GnmExprTop, 1);
2630
2611
        res->magic = GNM_EXPR_TOP_MAGIC;
 
2612
        res->hash = 0;
2631
2613
        res->refcount = 1;
2632
2614
        res->expr = expr;
2633
2615
        return res;
2669
2651
}
2670
2652
 
2671
2653
GnmExprTop const *
2672
 
gnm_expr_top_new_array_corner(int cols, int rows, GnmExpr const *expr)
 
2654
gnm_expr_top_new_array_corner (int cols, int rows, GnmExpr const *expr)
2673
2655
{
2674
2656
        return gnm_expr_top_new (gnm_expr_new_array_corner (cols, rows, expr));
2675
2657
}
2726
2708
        do_expr_as_string (target, texpr->expr, pp, 0, fmt);
2727
2709
}
2728
2710
 
 
2711
guint
 
2712
gnm_expr_top_hash (GnmExprTop const *texpr)
 
2713
{
 
2714
        g_return_val_if_fail (IS_GNM_EXPR_TOP (texpr), 0);
 
2715
 
 
2716
        if (texpr->hash == 0) {
 
2717
                ((GnmExprTop *)texpr)->hash = gnm_expr_hash (texpr->expr);
 
2718
                /* The following line tests the truncated value.  */
 
2719
                if (texpr->hash == 0)
 
2720
                        ((GnmExprTop *)texpr)->hash = 1;
 
2721
        }
 
2722
        return texpr->hash;
 
2723
}
 
2724
 
2729
2725
gboolean
2730
2726
gnm_expr_top_equal (GnmExprTop const *te1, GnmExprTop const *te2)
2731
2727
{
2735
2731
        g_return_val_if_fail (IS_GNM_EXPR_TOP (te1), FALSE);
2736
2732
        g_return_val_if_fail (IS_GNM_EXPR_TOP (te2), FALSE);
2737
2733
 
 
2734
        if (te1->hash && te2->hash && te1->hash != te2->hash)
 
2735
                return FALSE;
 
2736
 
2738
2737
        return gnm_expr_equal (te1->expr, te2->expr);
2739
2738
}
2740
2739
 
 
2740
/*
 
2741
 * gnm_expr_top_relocate :
 
2742
 * @expr   : #GnmExprTop to fixup
 
2743
 * @rinfo : #GnmExprRelocateInfo details of relocation
 
2744
 * @ignore_rel : Do not adjust relative refs (for internal use when
 
2745
 *                relocating named expressions.   Most callers will want FALSE.
 
2746
 *
 
2747
 * GNM_EXPR_RELOCATE_INVALIDATE_SHEET :
 
2748
 *      Convert any references to  sheets marked being_invalidated into #REF!
 
2749
 * GNM_EXPR_RELOCATE_MOVE_RANGE,
 
2750
 *      Find any references to the specified area and adjust them by the
 
2751
 *      supplied deltas.  Check for out of bounds conditions.  Return NULL if
 
2752
 *      no change is required.
 
2753
 *      If the expression is within the range to be moved, its relative
 
2754
 *      references to cells outside the range are adjusted to reference the
 
2755
 *      same cell after the move.
 
2756
 * GNM_EXPR_RELOCATE_COLS
 
2757
 * GNM_EXPR_RELOCATE_ROWS
 
2758
 *      
 
2759
 */
2741
2760
GnmExprTop const *
2742
 
gnm_expr_top_rewrite (GnmExprTop const *texpr,
2743
 
                      GnmExprRewriteInfo const *rwinfo)
 
2761
gnm_expr_top_relocate (GnmExprTop const *texpr,
 
2762
                       GnmExprRelocateInfo const *rinfo,
 
2763
                       gboolean ignore_rel)
2744
2764
{
2745
2765
        g_return_val_if_fail (IS_GNM_EXPR_TOP (texpr), NULL);
2746
2766
 
2747
 
        return gnm_expr_top_new (gnm_expr_rewrite (texpr->expr, rwinfo));
 
2767
        return gnm_expr_top_new (gnm_expr_relocate (texpr->expr, rinfo, ignore_rel));
2748
2768
}
2749
2769
 
2750
2770
gboolean
2862
2882
        return GNM_EXPR_GET_OPER (texpr->expr) == GNM_EXPR_OP_ARRAY_ELEM;
2863
2883
}
2864
2884
 
 
2885
GnmExprTop const *
 
2886
gnm_expr_top_transpose (GnmExprTop const *texpr)
 
2887
{
 
2888
        g_return_val_if_fail (IS_GNM_EXPR_TOP (texpr), NULL);
 
2889
        switch (GNM_EXPR_GET_OPER (texpr->expr)) {
 
2890
        case GNM_EXPR_OP_ARRAY_CORNER:
 
2891
                /* Transpose size  */
 
2892
                return gnm_expr_top_new_array_corner
 
2893
                        (texpr->expr->array_corner.rows,
 
2894
                         texpr->expr->array_corner.cols,
 
2895
                         gnm_expr_copy (texpr->expr));
 
2896
        case GNM_EXPR_OP_ARRAY_ELEM:
 
2897
                /* Transpose coordinates  */
 
2898
                return gnm_expr_top_new_array_elem
 
2899
                        (texpr->expr->array_elem.y,
 
2900
                         texpr->expr->array_elem.x);
 
2901
        default:
 
2902
                return NULL;
 
2903
        }
 
2904
}
 
2905
 
2865
2906
/****************************************************************************/
2866
2907
 
2867
2908
#if USE_EXPR_POOLS