~ubuntu-branches/ubuntu/quantal/gnumeric/quantal

« back to all changes in this revision

Viewing changes to src/dependent.c

  • Committer: Bazaar Package Importer
  • Author(s): Gauvain Pocentek
  • Date: 2009-06-07 11:10:47 UTC
  • mfrom: (1.1.19 upstream) (2.1.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090607111047-l3rtbzfjxvmi1kx0
Tags: 1.9.8-1ubuntu1
* Merge from debian unstable, remaining changes:
  - Promoted gnumeric-doc to Recommends in gnumeric package for help to be
    installed automatically
  - gnumeric-gtk is a transitional package
  - gnumeric conflicts with gnumeric-gtk << 1.8.3-3ubuntu1
  - call initltool-update in po*
  - remove psiconv support (psiconv is in universe):
    o debian/control: remove B-D on libpsiconv-dev
    o debian/rules: don't pass --with-psiconv to ./configure

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
/*
3
3
 * dependent.c:  Manage calculation dependencies between objects
4
4
 *
5
 
 * Copyright (C) 2000-2006
6
 
 *  Jody Goldberg   (jody@gnome.org)
7
 
 *  Morten Welinder (terra@gnome.org)
 
5
 * Copyright (C) 2000-2006 Jody Goldberg (jody@gnome.org)
 
6
 * Copyright (C) 2006-2009 Morten Welinder (terra@gnome.org)
8
7
 *
9
8
 * This program is free software; you can redistribute it and/or modify it
10
9
 * under the terms of version 2 of the GNU General Public License as published
90
89
 
91
90
#define BUCKET_SIZE     128
92
91
#define BUCKET_OF_ROW(row) ((row) / BUCKET_SIZE)
93
 
#define BUCKET_LAST (BUCKET_OF_ROW (gnm_sheet_get_max_rows (sheet) - 1))
94
92
#define BUCKET_START_ROW(b) ((b) * BUCKET_SIZE)
95
93
#define BUCKET_END_ROW(b) ((b) * BUCKET_SIZE + (BUCKET_SIZE - 1))
96
94
 
511
509
{
512
510
        g_return_if_fail (dep != NULL);
513
511
 
 
512
#ifdef DEBUG_EVALUATION
 
513
        g_printerr ("/* QUEUE (%s) */\n", cell_name (GNM_DEP_TO_CELL (dep)));
 
514
#endif
514
515
        if (!dependent_needs_recalc (dep)) {
515
516
                GSList listrec;
516
517
                listrec.next = NULL;
596
597
                        }
597
598
                }
598
599
 
599
 
                g_print ("resize %p: %d [%d %.1f %.0f%%]\n",
600
 
                         hash_table,
601
 
                         new_nbuckets,
602
 
                         hash_table->num_elements,
603
 
                         (double)totlen / nonzero,
604
 
                         100.0 * totlen / capacity);
 
600
                g_printerr ("resize %p: %d [%d %.1f %.0f%%]\n",
 
601
                            hash_table,
 
602
                            new_nbuckets,
 
603
                            hash_table->num_elements,
 
604
                            (double)totlen / nonzero,
 
605
                            100.0 * totlen / capacity);
605
606
        }
606
607
#endif
607
608
}
846
847
        DependencySingle *single;
847
848
        GnmDepContainer *deps;
848
849
        DependentFlags flag = DEPENDENT_NO_FLAG;
849
 
 
850
 
        if (ref->sheet != NULL) {
851
 
                if (ref->sheet != dep->sheet)
852
 
                        flag = (ref->sheet->workbook != dep->sheet->workbook)
853
 
                                ? DEPENDENT_GOES_INTERBOOK : DEPENDENT_GOES_INTERSHEET;
854
 
                deps = ref->sheet->deps;
855
 
        } else
856
 
                deps = dep->sheet->deps;
 
850
        Sheet const *sheet = eval_sheet (ref->sheet, dep->sheet);
 
851
 
 
852
        if (sheet != dep->sheet)
 
853
                flag = (sheet->workbook != dep->sheet->workbook)
 
854
                        ? DEPENDENT_GOES_INTERBOOK
 
855
                        : DEPENDENT_GOES_INTERSHEET;
 
856
 
 
857
        deps = sheet->deps;
857
858
 
858
859
        /* Inserts if it is not already there */
859
 
        gnm_cellpos_init_cellref (&lookup.pos, ref, pos);
 
860
        gnm_cellpos_init_cellref (&lookup.pos, ref, pos, sheet);
860
861
        single = g_hash_table_lookup (deps->single_hash, &lookup);
861
862
        if (single == NULL) {
862
863
                single = go_mem_chunk_alloc (deps->single_pool);
874
875
{
875
876
        DependencySingle lookup;
876
877
        DependencySingle *single;
877
 
        GnmDepContainer *deps = eval_sheet (a->sheet, dep->sheet)->deps;
 
878
        Sheet const *sheet = eval_sheet (a->sheet, dep->sheet);
 
879
        GnmDepContainer *deps = sheet->deps;
878
880
 
879
881
        if (!deps)
880
882
                return;
881
883
 
882
 
        gnm_cellpos_init_cellref (&lookup.pos, a, pos);
 
884
        gnm_cellpos_init_cellref (&lookup.pos, a, pos, sheet);
883
885
        single = g_hash_table_lookup (deps->single_hash, &lookup);
884
886
        if (single != NULL) {
885
887
                micro_hash_remove (&single->deps, dep);
897
899
{
898
900
        int i = BUCKET_OF_ROW (r->range.start.row);
899
901
        int const end = BUCKET_OF_ROW (r->range.end.row);
 
902
        DependencyRange r2 = *r;
900
903
 
901
904
        for ( ; i <= end; i++) {
902
 
                /* Look it up */
903
905
                DependencyRange *result;
904
906
 
 
907
                /* Restrict range to bucket.  */
 
908
                r2.range.start.row = MAX (r->range.start.row, BUCKET_START_ROW (i));
 
909
                r2.range.end.row = MIN (r->range.end.row, BUCKET_END_ROW (i));
 
910
 
905
911
                if (deps->range_hash[i] == NULL)
906
912
                        deps->range_hash[i] = g_hash_table_new (
907
913
                                (GHashFunc)  deprange_hash,
908
914
                                (GEqualFunc) deprange_equal);
909
915
                else {
910
 
                        result = g_hash_table_lookup (deps->range_hash[i], r);
 
916
                        result = g_hash_table_lookup (deps->range_hash[i], &r2);
911
917
                        if (result) {
912
918
                                /* Inserts if it is not already there */
913
919
                                micro_hash_insert (&result->deps, dep);
917
923
 
918
924
                /* Create a new DependencyRange structure */
919
925
                result = go_mem_chunk_alloc (deps->range_pool);
920
 
                *result = *r;
 
926
                *result = r2;
921
927
                micro_hash_init (&result->deps, dep);
922
928
                g_hash_table_insert (deps->range_hash[i], result, result);
923
929
        }
929
935
{
930
936
        int i = BUCKET_OF_ROW (r->range.start.row);
931
937
        int const end = BUCKET_OF_ROW (r->range.end.row);
 
938
        DependencyRange r2 = *r;
932
939
 
933
940
        if (!deps)
934
941
                return;
935
942
 
936
943
        for ( ; i <= end; i++) {
937
 
                DependencyRange *result =
938
 
                        g_hash_table_lookup (deps->range_hash[i], r);
 
944
                DependencyRange *result;
 
945
 
 
946
                /* Restrict range to bucket.  */
 
947
                r2.range.start.row = MAX (r->range.start.row, BUCKET_START_ROW (i));
 
948
                r2.range.end.row = MIN (r->range.end.row, BUCKET_END_ROW (i));
 
949
 
 
950
                result = g_hash_table_lookup (deps->range_hash[i], &r2);
939
951
                if (result) {
940
952
                        micro_hash_remove (&result->deps, dep);
941
953
                        if (micro_hash_is_empty (&result->deps)) {
954
966
        DependencyRange range;
955
967
        DependentFlags flag = DEPENDENT_NO_FLAG;
956
968
 
957
 
        gnm_cellpos_init_cellref (&range.range.start, a, pos);
958
 
        gnm_cellpos_init_cellref (&range.range.end, b, pos);
 
969
        gnm_cellpos_init_cellref (&range.range.start, a, pos, dep->sheet);
 
970
        gnm_cellpos_init_cellref (&range.range.end, b, pos, dep->sheet);
959
971
        range_normalize (&range.range);
960
972
 
961
973
        if (a->sheet != NULL) {
991
1003
{
992
1004
        DependencyRange range;
993
1005
 
994
 
        gnm_cellpos_init_cellref (&range.range.start, a, pos);
995
 
        gnm_cellpos_init_cellref (&range.range.end, b, pos);
 
1006
        gnm_cellpos_init_cellref (&range.range.start, a, pos, dep->sheet);
 
1007
        gnm_cellpos_init_cellref (&range.range.end, b, pos, dep->sheet);
996
1008
        range_normalize (&range.range);
997
1009
 
998
1010
        if (a->sheet != NULL) {
1024
1036
        case GNM_EXPR_OP_RANGE_CTOR:  /* See #562363 */
1025
1037
        case GNM_EXPR_OP_INTERSECT:
1026
1038
        case GNM_EXPR_OP_ANY_BINARY:
1027
 
                return  link_expr_dep (ep, tree->binary.value_a) |
1028
 
                        link_expr_dep (ep, tree->binary.value_b);
 
1039
                return link_expr_dep (ep, tree->binary.value_a) |
 
1040
                       link_expr_dep (ep, tree->binary.value_b);
1029
1041
        case GNM_EXPR_OP_ANY_UNARY:
1030
1042
                return link_expr_dep (ep, tree->unary.value);
1031
1043
        case GNM_EXPR_OP_CELLREF:
1097
1109
                        res |= link_expr_dep (ep, tree->set.argv[i]);
1098
1110
                return res;
1099
1111
        }
1100
 
 
1101
1112
#ifndef DEBUG_SWITCH_ENUM
1102
1113
        default:
1103
1114
                g_assert_not_reached ();
1230
1241
static void
1231
1242
name_dep_debug_name (GnmDependent const *dep, GString *target)
1232
1243
{
1233
 
        g_string_append_printf (target, "Name%p", dep);
 
1244
        g_string_append_printf (target, "Name%p", (void *)dep);
1234
1245
}
1235
1246
 
1236
1247
static void
1241
1252
static void
1242
1253
dynamic_dep_debug_name (GnmDependent const *dep, GString *target)
1243
1254
{
1244
 
        g_string_append_printf (target, "DynamicDep%p", dep);
 
1255
        g_string_append_printf (target, "DynamicDep%p", (void *)dep);
1245
1256
}
1246
1257
 
1247
1258
void
1270
1281
                g_hash_table_insert (dep->sheet->deps->dynamic_deps, dep, dyn);
1271
1282
        }
1272
1283
 
1273
 
        gnm_cellpos_init_cellref (&range.range.start, &rr->a, pos);
1274
 
        gnm_cellpos_init_cellref (&range.range.end, &rr->b, pos);
 
1284
        gnm_cellpos_init_cellref (&range.range.start, &rr->a, pos, dep->sheet);
 
1285
        gnm_cellpos_init_cellref (&range.range.end, &rr->b, pos, dep->sheet);
1275
1286
        if (range_is_singleton (&range.range)) {
1276
1287
                flags = link_single_dep (&dyn->base, pos, &rr->a);
1277
1288
                dyn->singles = g_slist_prepend (dyn->singles, gnm_rangeref_dup (rr));
1380
1391
        GnmEvalPos       pos;
1381
1392
        int      max_iteration;
1382
1393
 
1383
 
        if (!gnm_cell_has_expr (cell))
 
1394
        if (!gnm_cell_has_expr (cell) ||        /* plain cells without expr */
 
1395
            !dependent_is_linked (&cell->base)) /* special case within TABLE */
1384
1396
                return TRUE;
1385
1397
 
1386
1398
        /* do this here rather than dependent_eval
1395
1407
#ifdef DEBUG_EVALUATION
1396
1408
        {
1397
1409
                GnmParsePos pp;
1398
 
                char *str = gnm_expr_top_as_string (cell->base.texpr,
1399
 
                        parse_pos_init_cell (&pp, cell), gnm_conventions_default);
1400
 
                g_print ("{\nEvaluating %s: %s;\n", cell_name (cell), str);
 
1410
                char *str = gnm_expr_top_as_string
 
1411
                        (cell->base.texpr,
 
1412
                         parse_pos_init_cell (&pp, cell),
 
1413
                         NULL);
 
1414
                g_printerr ("{\nEvaluating %s!%s: %s;\n",
 
1415
                            cell->base.sheet->name_quoted, cell_name (cell),
 
1416
                            str);
1401
1417
                g_free (str);
1402
1418
        }
1403
1419
#endif
1410
1426
                /* but not the first bottom */
1411
1427
                if (cell->base.flags & DEPENDENT_BEING_ITERATED) {
1412
1428
#ifdef DEBUG_EVALUATION
1413
 
                        g_print ("}; /* already-iterate (%d) */\n", iterating == NULL);
 
1429
                        g_printerr ("}; /* already-iterate (%d) */\n", iterating == NULL);
1414
1430
#endif
1415
1431
                        return iterating == NULL;
1416
1432
                }
1454
1470
                char *valtxt = v
1455
1471
                        ? value_get_as_string (v)
1456
1472
                        : g_strdup ("NULL");
1457
 
                g_print ("Evaluation(%d) %s := %s\n", max_iteration, cell_name (cell), valtxt);
 
1473
                g_printerr ("Evaluation(%d) %s := %s\n",
 
1474
                            max_iteration, cell_name (cell), valtxt);
1458
1475
                g_free (valtxt);
1459
1476
        }
1460
1477
#endif
1510
1527
                iterating = NULL;
1511
1528
 
1512
1529
#ifdef DEBUG_EVALUATION
1513
 
        g_print ("} (%d)\n", iterating == NULL);
 
1530
        g_printerr ("} (%d)\n", iterating == NULL);
1514
1531
#endif
1515
1532
        cell->base.flags &= ~DEPENDENT_BEING_CALCULATED;
1516
1533
        return iterating == NULL;
1544
1561
 
1545
1562
                /* This should always be the top of the stack */
1546
1563
                g_return_if_fail (finished);
 
1564
 
 
1565
                dep->flags &= ~GNM_CELL_HAS_NEW_EXPR;
1547
1566
        }
1548
1567
 
1549
1568
        /* Don't clear flag until after in case we iterate */
1593
1612
        /* When things get slow this is a good test to enable */
1594
1613
        static int counter = 0;
1595
1614
        if ((++counter % 100000) == 0)
1596
 
                g_print ("%d\n", counter / 100000);
 
1615
                g_printerr ("%d\n", counter / 100000);
1597
1616
#endif
1598
1617
 
1599
1618
        if (range_contains (range, c->col, c->row)) {
1730
1749
                        dependent_flag_recalc (dep););
1731
1750
 
1732
1751
                /* look for things that depend on the sheet */
1733
 
                for (i = BUCKET_LAST; i >= 0 ; i--) {
 
1752
                for (i = sheet->deps->buckets - 1; i >= 0 ; i--) {
1734
1753
                        GHashTable *hash = sheet->deps->range_hash[i];
1735
1754
                        if (hash != NULL)
1736
1755
                                g_hash_table_foreach (hash,
1906
1925
        *l = g_slist_prepend (*l, nexpr);
1907
1926
}
1908
1927
 
 
1928
struct cb_remote_names {
 
1929
        GSList *names;
 
1930
        Workbook *wb;
 
1931
};
 
1932
 
 
1933
static void
 
1934
cb_remote_names1 (G_GNUC_UNUSED const char *name,
 
1935
                  GnmNamedExpr *nexpr,
 
1936
                  struct cb_remote_names *data)
 
1937
{
 
1938
        data->names = g_slist_prepend (data->names, nexpr);
 
1939
}
 
1940
 
 
1941
static void
 
1942
cb_remote_names2 (GnmNamedExpr *nexpr,
 
1943
                  G_GNUC_UNUSED gpointer value,
 
1944
                  struct cb_remote_names *data)
 
1945
{
 
1946
        Workbook *wb =
 
1947
                nexpr->pos.sheet ? nexpr->pos.sheet->workbook : nexpr->pos.wb;
 
1948
        if (wb != data->wb)
 
1949
                data->names = g_slist_prepend (data->names, nexpr);
 
1950
}
 
1951
 
 
1952
/*
 
1953
 * Get a list of all names that (may) reference data in a given sheet.
 
1954
 * This is approximated as all names in the sheet, all global names in
 
1955
 * its workbook, and all external references that actually mention the
 
1956
 * sheet explicitly.
 
1957
 */
 
1958
static GSList *
 
1959
names_referencing_sheet (Sheet *sheet)
 
1960
{
 
1961
        struct cb_remote_names data;
 
1962
 
 
1963
        data.names = NULL;
 
1964
        data.wb = sheet->workbook;
 
1965
 
 
1966
        workbook_foreach_name (sheet->workbook, TRUE,
 
1967
                               (GHFunc)cb_remote_names1,
 
1968
                               &data);
 
1969
        gnm_sheet_foreach_name (sheet, (GHFunc)cb_remote_names1, &data);
 
1970
 
 
1971
        if (sheet->deps->referencing_names)
 
1972
                g_hash_table_foreach (sheet->deps->referencing_names,
 
1973
                                      (GHFunc)cb_remote_names2,
 
1974
                                      &data);
 
1975
 
 
1976
        return data.names;
 
1977
}
 
1978
 
 
1979
 
1909
1980
/**
1910
1981
 * dependents_relocate:
1911
1982
 * @rinfo : the descriptor record for what is being moved where.
2040
2111
 
2041
2112
        case GNM_EXPR_RELOCATE_COLS:
2042
2113
        case GNM_EXPR_RELOCATE_ROWS: {
2043
 
                GSList *names = NULL, *l;
 
2114
                GSList *l, *names = names_referencing_sheet (sheet);
 
2115
                GnmExprRelocateInfo rinfo2 = *rinfo;
2044
2116
 
2045
 
                if (sheet->deps->referencing_names)
2046
 
                        g_hash_table_foreach (sheet->deps->referencing_names,
2047
 
                                              (GHFunc)cb_collect_names,
2048
 
                                              &names);
2049
2117
                for (l = names; l; l = l->next) {
2050
2118
                        GnmNamedExpr *nexpr = l->data;
2051
 
                        GnmExprTop const *newtree =
2052
 
                                gnm_expr_top_relocate (nexpr->texpr,
2053
 
                                                       rinfo, TRUE);
 
2119
                        GnmExprTop const *newtree;
 
2120
                        rinfo2.pos = nexpr->pos;
 
2121
                        newtree = gnm_expr_top_relocate (nexpr->texpr,
 
2122
                                                         &rinfo2, TRUE);
2054
2123
                        if (newtree) {
2055
2124
                                GOUndo *u = expr_name_set_expr_undo_new (nexpr);
2056
2125
                                u_names = go_undo_combine (u_names, u);
2334
2403
                sheet->revive = NULL;
2335
2404
        }
2336
2405
 
2337
 
        for (i = BUCKET_LAST; i >= 0 ; i--) {
 
2406
        for (i = deps->buckets - 1; i >= 0 ; i--) {
2338
2407
                GHashTable *hash = deps->range_hash[i];
2339
2408
                if (hash != NULL)
2340
2409
                        dep_hash_destroy (hash, &dyn_deps, sheet);
2397
2466
 
2398
2467
        deps = sheet->deps;
2399
2468
 
2400
 
        for (i = BUCKET_LAST; i >= 0 ; i--) {
 
2469
        for (i = deps->buckets - 1; i >= 0 ; i--) {
2401
2470
                GHashTable *hash = deps->range_hash[i];
2402
2471
                if (hash != NULL)
2403
2472
                        dep_hash_destroy (hash, &dyn_deps, sheet);
2556
2625
void
2557
2626
workbook_queue_all_recalc (Workbook *wb)
2558
2627
{
2559
 
        /* FIXME: what about dependents in other workbooks */
 
2628
        /* FIXME: what about dependents in other workbooks?  */
2560
2629
        WORKBOOK_FOREACH_DEPENDENT (wb, dep, dependent_flag_recalc (dep););
2561
2630
}
2562
2631
 
2576
2645
 
2577
2646
        g_return_if_fail (IS_WORKBOOK (wb));
2578
2647
 
 
2648
        gnm_app_recalc_start ();
 
2649
 
2579
2650
        WORKBOOK_FOREACH_DEPENDENT (wb, dep, {
2580
2651
                if (dependent_needs_recalc (dep)) {
2581
2652
                        redraw = TRUE;
2583
2654
                }
2584
2655
        });
2585
2656
 
 
2657
        gnm_app_recalc_finish ();
 
2658
 
2586
2659
        /*
2587
2660
         * This is a bit of a band-aid.  If anything is recalculated, we
2588
2661
         * force a full redraw.  The alternative is to ask for updates
2590
2663
         * expensive.
2591
2664
         */
2592
2665
        if (redraw) {
2593
 
                g_signal_emit_by_name (gnm_app_get_app (), "recalc-finished");
2594
 
 
2595
2666
                WORKBOOK_FOREACH_SHEET (wb, sheet, {
2596
2667
                        SHEET_FOREACH_VIEW (sheet, sv, sv_flag_selection_change (sv););
2597
2668
                        sheet_redraw_all (sheet, FALSE);});
2649
2720
 
2650
2721
        deps->head = deps->tail = NULL;
2651
2722
 
2652
 
        deps->range_hash  = g_new0 (GHashTable *, BUCKET_LAST + 1);
 
2723
        deps->buckets = 1 + BUCKET_OF_ROW (gnm_sheet_get_last_row (sheet));
 
2724
        deps->range_hash  = g_new0 (GHashTable *, deps->buckets);
2653
2725
        deps->range_pool  = go_mem_chunk_new ("range pool",
2654
2726
                                               sizeof (DependencyRange),
2655
2727
                                               16 * 1024 - 100);
2667
2739
        return deps;
2668
2740
}
2669
2741
 
 
2742
void
 
2743
gnm_dep_container_resize (GnmDepContainer *deps, int rows)
 
2744
{
 
2745
        int i, buckets = 1 + BUCKET_OF_ROW (rows - 1);
 
2746
 
 
2747
        for (i = buckets; i < deps->buckets; i++) {
 
2748
                GHashTable *hash = deps->range_hash[i];
 
2749
                if (hash != NULL) {
 
2750
                        int s = g_hash_table_size (hash);
 
2751
                        if (s)
 
2752
                                g_printerr ("Hash table size: %d\n", s);
 
2753
                        g_hash_table_destroy (hash);
 
2754
                        deps->range_hash[i] = NULL;
 
2755
                }
 
2756
        }
 
2757
 
 
2758
        deps->range_hash = g_renew (GHashTable *, deps->range_hash, buckets);
 
2759
 
 
2760
        for (i = deps->buckets; i < buckets; i++)
 
2761
                deps->range_hash[i] = NULL;
 
2762
 
 
2763
        deps->buckets = buckets;
 
2764
}
 
2765
 
2670
2766
/****************************************************************************
2671
2767
 * Debug utils
2672
2768
 */
2673
2769
 
2674
2770
static void
2675
 
dump_range_dep (gpointer key, G_GNUC_UNUSED gpointer value,
2676
 
                G_GNUC_UNUSED gpointer closure)
 
2771
dependent_debug_name_for_sheet (GnmDependent const *dep, Sheet *sheet,
 
2772
                                GString *target)
 
2773
{
 
2774
        if (sheet && sheet == dep->sheet && dependent_is_cell (dep))
 
2775
                g_string_append (target, cell_name (GNM_DEP_TO_CELL (dep)));
 
2776
        else
 
2777
                dependent_debug_name (dep, target);
 
2778
}
 
2779
 
 
2780
 
 
2781
static void
 
2782
dump_range_dep (gpointer key, G_GNUC_UNUSED gpointer value, gpointer sheet_)
2677
2783
{
2678
2784
        DependencyRange const *deprange = key;
2679
2785
        GnmRange const *range = &(deprange->range);
 
2786
        Sheet *sheet = sheet_;
2680
2787
        GString *target = g_string_sized_new (10000);
2681
2788
        gboolean first = TRUE;
2682
2789
 
2689
2796
                        first = FALSE;
2690
2797
                else
2691
2798
                        g_string_append (target, ", ");
2692
 
                dependent_debug_name (dep, target);
 
2799
                dependent_debug_name_for_sheet (dep, sheet, target);
2693
2800
        });
2694
2801
        g_string_append_c (target, ')');
2695
2802
 
2696
 
        g_print ("%s\n", target->str);
 
2803
        g_printerr ("%s\n", target->str);
2697
2804
        g_string_free (target, TRUE);
2698
2805
}
2699
2806
 
2700
2807
static void
2701
 
dump_single_dep (gpointer key, G_GNUC_UNUSED gpointer value,
2702
 
                 G_GNUC_UNUSED gpointer closure)
 
2808
dump_single_dep (gpointer key, G_GNUC_UNUSED gpointer value, gpointer sheet_)
2703
2809
{
2704
2810
        DependencySingle *depsingle = key;
 
2811
        Sheet *sheet = sheet_;
2705
2812
        GString *target = g_string_sized_new (10000);
2706
2813
        gboolean first = TRUE;
2707
2814
 
2714
2821
                        first = FALSE;
2715
2822
                else
2716
2823
                        g_string_append (target, ", ");
2717
 
                dependent_debug_name (dep, target);
 
2824
                dependent_debug_name_for_sheet (dep, sheet, target);
2718
2825
        });
2719
2826
 
2720
 
        g_print ("%s\n", target->str);
 
2827
        g_printerr ("%s\n", target->str);
2721
2828
        g_string_free (target, TRUE);
2722
2829
}
2723
2830
 
2761
2868
        }
2762
2869
 
2763
2870
        g_string_append (out.accum, "] }");
2764
 
        g_print ("%s\n", out.accum->str);
 
2871
        g_printerr ("%s\n", out.accum->str);
2765
2872
        g_string_free (out.accum, TRUE);
2766
2873
}
2767
2874
 
2768
 
static void
2769
 
cb_dump_name_dep (gpointer key, G_GNUC_UNUSED gpointer value,
2770
 
                  gpointer closure)
2771
 
{
2772
 
        GnmDependent *dep = key;
2773
 
        GString *target = closure;
2774
 
 
2775
 
        if (target->str[target->len - 1] != '[')
2776
 
                g_string_append (target, ", ");
2777
 
        dependent_debug_name (dep, target);
2778
 
}
2779
 
 
2780
 
static void
2781
 
dump_name_dep (gpointer key, G_GNUC_UNUSED gpointer value,
2782
 
               G_GNUC_UNUSED gpointer closure)
2783
 
{
2784
 
        GnmNamedExpr *nexpr = key;
2785
 
        GString *target = g_string_new (NULL);
2786
 
 
2787
 
        g_string_append (target, "    ");
2788
 
        if (!nexpr->active) g_string_append_c (target, '(');
2789
 
        g_string_append (target, nexpr->name->str);
2790
 
        if (!nexpr->active) g_string_append_c (target, ')');
2791
 
        g_string_append (target, " -> [");
2792
 
        if (nexpr->dependents)
2793
 
                g_hash_table_foreach (nexpr->dependents, cb_dump_name_dep, target);
2794
 
        g_string_append (target, "]");
2795
 
 
2796
 
        g_print ("%s\n", target->str);
2797
 
        g_string_free (target, TRUE);
2798
 
}
2799
 
 
2800
2875
/**
2801
2876
 * gnm_dep_container_dump :
2802
2877
 * @deps :
2804
2879
 * A useful utility for checking the state of the dependency data structures.
2805
2880
 */
2806
2881
void
2807
 
gnm_dep_container_dump (GnmDepContainer const *deps)
 
2882
gnm_dep_container_dump (GnmDepContainer const *deps,
 
2883
                        Sheet *sheet)
2808
2884
{
2809
2885
        int i;
2810
 
        Sheet *sheet = NULL;
2811
2886
 
2812
2887
        g_return_if_fail (deps != NULL);
2813
2888
 
2814
2889
        gnm_dep_container_sanity_check (deps);
2815
2890
 
2816
 
        for (i = BUCKET_LAST; i >= 0 ; i--) {
 
2891
        for (i = deps->buckets - 1; i >= 0 ; i--) {
2817
2892
                GHashTable *hash = deps->range_hash[i];
2818
2893
                if (hash != NULL && g_hash_table_size (hash) > 0) {
2819
 
                        g_print ("  Bucket %d (%d-%d): Range hash size %d: range over which cells in list depend\n",
2820
 
                                 i,
2821
 
                                 BUCKET_START_ROW (i),
2822
 
                                 BUCKET_END_ROW (i),
2823
 
                                 g_hash_table_size (hash));
 
2894
                        g_printerr ("  Bucket %d (rows %d-%d): Range hash size %d: range over which cells in list depend\n",
 
2895
                                    i,
 
2896
                                    BUCKET_START_ROW (i) + 1,
 
2897
                                    BUCKET_END_ROW (i) + 1,
 
2898
                                    g_hash_table_size (hash));
2824
2899
                        g_hash_table_foreach (hash,
2825
 
                                              dump_range_dep, NULL);
 
2900
                                              dump_range_dep,
 
2901
                                              sheet);
2826
2902
                }
2827
2903
        }
2828
2904
 
2829
2905
        if (deps->single_hash && g_hash_table_size (deps->single_hash) > 0) {
2830
 
                g_print ("  Single hash size %d: cell on which list of cells depend\n",
2831
 
                         g_hash_table_size (deps->single_hash));
 
2906
                g_printerr ("  Single hash size %d: cell on which list of cells depend\n",
 
2907
                            g_hash_table_size (deps->single_hash));
2832
2908
                g_hash_table_foreach (deps->single_hash,
2833
 
                                      dump_single_dep, NULL);
 
2909
                                      dump_single_dep,
 
2910
                                      sheet);
2834
2911
        }
2835
2912
 
2836
2913
        if (deps->dynamic_deps && g_hash_table_size (deps->dynamic_deps) > 0) {
2837
 
                g_print ("  Dynamic hash size %d: cells that depend on dynamic dependencies\n",
2838
 
                         g_hash_table_size (deps->dynamic_deps));
 
2914
                g_printerr ("  Dynamic hash size %d: cells that depend on dynamic dependencies\n",
 
2915
                            g_hash_table_size (deps->dynamic_deps));
2839
2916
                g_hash_table_foreach (deps->dynamic_deps,
2840
2917
                                      dump_dynamic_dep, NULL);
2841
2918
        }
2842
2919
 
2843
2920
        if (deps->referencing_names && g_hash_table_size (deps->referencing_names) > 0) {
2844
 
                g_print ("  Names whose expressions reference this sheet mapped to dependencies\n");
 
2921
                GSList *l, *names = NULL;
 
2922
 
2845
2923
                g_hash_table_foreach (deps->referencing_names,
2846
 
                                      dump_name_dep, NULL);
 
2924
                                      (GHFunc)cb_collect_names,
 
2925
                                      &names);
 
2926
 
 
2927
                g_printerr ("  Names whose expressions explicitly reference this sheet\n    ");
 
2928
                for (l = names; l; l = l->next) {
 
2929
                        GnmNamedExpr *nexpr = l->data;
 
2930
                        g_printerr ("%s%s",
 
2931
                                    expr_name_name (nexpr),
 
2932
                                    l->next ? ", " : "\n");
 
2933
                }
 
2934
                g_slist_free (names);
2847
2935
        }
2848
2936
}
2849
2937
 
2854
2942
        GHashTable *seenb4;
2855
2943
 
2856
2944
        if (deps->head && !deps->tail)
2857
 
                g_warning ("Dependency container %p has head, but no tail.", deps);
 
2945
                g_warning ("Dependency container %p has head, but no tail.", (void *)deps);
2858
2946
        if (deps->tail && !deps->head)
2859
 
                g_warning ("Dependency container %p has tail, but no head.", deps);
 
2947
                g_warning ("Dependency container %p has tail, but no head.", (void *)deps);
2860
2948
        if (deps->head && deps->head->prev_dep)
2861
 
                g_warning ("Dependency container %p has head, but not at the beginning.", deps);
 
2949
                g_warning ("Dependency container %p has head, but not at the beginning.", (void *)deps);
2862
2950
        if (deps->tail && deps->tail->next_dep)
2863
 
                g_warning ("Dependency container %p has tail, but not at the end.", deps);
 
2951
                g_warning ("Dependency container %p has tail, but not at the end.", (void *)deps);
2864
2952
 
2865
2953
        seenb4 = g_hash_table_new (g_direct_hash, g_direct_equal);
2866
2954
        for (dep = deps->head; dep; dep = dep->next_dep) {
2867
2955
                if (dep->prev_dep && (dep->prev_dep->next_dep != dep))
2868
 
                        g_warning ("Dependency container %p has left double-link failure at %p.", deps, dep);
 
2956
                        g_warning ("Dependency container %p has left double-link failure at %p.", (void *)deps, (void *)dep);
2869
2957
                if (dep->next_dep && (dep->next_dep->prev_dep != dep))
2870
 
                        g_warning ("Dependency container %p has right double-link failure at %p.", deps, dep);
 
2958
                        g_warning ("Dependency container %p has right double-link failure at %p.", (void *)deps, (void *)dep);
2871
2959
                if (!dep->next_dep && dep != deps->tail)
2872
 
                        g_warning ("Dependency container %p ends before its tail.", deps);
 
2960
                        g_warning ("Dependency container %p ends before its tail.", (void *)deps);
2873
2961
                if (!dependent_is_linked (dep))
2874
 
                        g_warning ("Dependency container %p contains unlinked dependency %p.", deps, dep);
 
2962
                        g_warning ("Dependency container %p contains unlinked dependency %p.", (void *)deps, (void *)dep);
2875
2963
                if (g_hash_table_lookup (seenb4, dep)) {
2876
 
                        g_warning ("Dependency container %p is circular.", deps);
 
2964
                        g_warning ("Dependency container %p is circular.", (void *)deps);
2877
2965
                        break;
2878
2966
                }
2879
2967
                g_hash_table_insert (seenb4, (gpointer)dep, (gpointer)dep);