Commit 2a1a864d authored by Morten Welinder's avatar Morten Welinder

First go at expr_tree_invalidate_references.

parent 811ce7e8
1999-04-29 Morten Welinder <terra@diku.dk>
* src/expr.c (do_expr_tree_relocate): Remove strange and incorrect
refcount fiddling.
* src/workbook.c (workbook_fixup_references,
workbook_invalidate_references): Fix cell walking.
* src/expr.c (do_expr_decode_tree): rename binary_operation_names
to operation_names and fill in the rest.
* src/fn-misc.c (gnumeric_error): New function.
* src/expr.c (value_str): Constify.
(expr_tree_invalidate_references): Mostly implement.
* src/fn-math.c (gnumeric_multinomial, gnumeric_product,
gnumeric_sumsq): Fix type.
......
1999-04-29 Morten Welinder <terra@diku.dk>
* src/expr.c (do_expr_tree_relocate): Remove strange and incorrect
refcount fiddling.
* src/workbook.c (workbook_fixup_references,
workbook_invalidate_references): Fix cell walking.
* src/expr.c (do_expr_decode_tree): rename binary_operation_names
to operation_names and fill in the rest.
* src/fn-misc.c (gnumeric_error): New function.
* src/expr.c (value_str): Constify.
(expr_tree_invalidate_references): Mostly implement.
* src/fn-math.c (gnumeric_multinomial, gnumeric_product,
gnumeric_sumsq): Fix type.
......
1999-04-29 Morten Welinder <terra@diku.dk>
* src/expr.c (do_expr_tree_relocate): Remove strange and incorrect
refcount fiddling.
* src/workbook.c (workbook_fixup_references,
workbook_invalidate_references): Fix cell walking.
* src/expr.c (do_expr_decode_tree): rename binary_operation_names
to operation_names and fill in the rest.
* src/fn-misc.c (gnumeric_error): New function.
* src/expr.c (value_str): Constify.
(expr_tree_invalidate_references): Mostly implement.
* src/fn-math.c (gnumeric_multinomial, gnumeric_product,
gnumeric_sumsq): Fix type.
......
1999-04-29 Morten Welinder <terra@diku.dk>
* src/expr.c (do_expr_tree_relocate): Remove strange and incorrect
refcount fiddling.
* src/workbook.c (workbook_fixup_references,
workbook_invalidate_references): Fix cell walking.
* src/expr.c (do_expr_decode_tree): rename binary_operation_names
to operation_names and fill in the rest.
* src/fn-misc.c (gnumeric_error): New function.
* src/expr.c (value_str): Constify.
(expr_tree_invalidate_references): Mostly implement.
* src/fn-math.c (gnumeric_multinomial, gnumeric_product,
gnumeric_sumsq): Fix type.
......
1999-04-29 Michael Meeks <michael@edenproject.org>
* ms-ole.c (ms_ole_new): Revert to read-only mapping on failure.
(MW: there has got to be a reason why we don't start that way.)
1999-04-29 Morten Welinder <terra@diku.dk>
* ms-excel.c (ms_excel_workbook_detach): Add new extra parameter
......
......@@ -549,6 +549,7 @@ MS_OLE *
ms_ole_new (const char *name)
{
struct stat st;
int prot = PROT_READ | PROT_WRITE;
int file;
MS_OLE *f;
......@@ -557,6 +558,10 @@ ms_ole_new (const char *name)
f = g_new0 (MS_OLE, 1);
f->file_descriptor = file = open (name, O_RDWR);
if (file == -1) {
f->file_descriptor = file = open (name, O_RDONLY);
prot &= ~PROT_WRITE;
}
if (file == -1 || fstat(file, &st))
{
printf ("No such file '%s'\n", name);
......@@ -572,7 +577,7 @@ ms_ole_new (const char *name)
return 0;
}
f->mem = mmap (0, f->length, PROT_READ|PROT_WRITE, MAP_SHARED, file, 0);
f->mem = mmap (0, f->length, prot, MAP_SHARED, file, 0);
if (GET_GUINT32(f->mem ) != 0xe011cfd0 ||
GET_GUINT32(f->mem + 4) != 0xe11ab1a1)
......
......@@ -963,14 +963,13 @@ cell_relocate (Cell *cell, int col_diff, int row_diff)
sheet_cell_formula_unlink (cell);
if (col_diff != 0 || row_diff != 0){
ExprTree *new_tree;
char *text, *formula;
new_tree = expr_tree_relocate (cell->parsed_node, col_diff, row_diff);
expr_tree_unref (cell->parsed_node);
cell->parsed_node = new_tree;
}
/* The follwing call also relinks the cell. */
/* The following call also relinks the cell. */
cell_formula_changed (cell);
}
......
......@@ -253,7 +253,7 @@ value_int (int i)
}
Value *
value_str (char *str)
value_str (const char *str)
{
Value *v = g_new (Value, 1);
......@@ -514,7 +514,7 @@ cell_ref_make_absolute (CellRef *cell_ref, int eval_col, int eval_row)
g_return_if_fail (cell_ref != NULL);
if (cell_ref->col_relative)
cell_ref-> col = eval_col + cell_ref->col;
cell_ref->col = eval_col + cell_ref->col;
if (cell_ref->row_relative)
cell_ref->row = eval_row + cell_ref->row;
......@@ -1216,9 +1216,10 @@ bigger_prec (Operation parent, Operation this)
static char *
do_expr_decode_tree (ExprTree *tree, Sheet *sheet, int col, int row, Operation parent_op)
{
static const char *binary_operation_names [] = {
static const char *operation_names [] = {
"=", ">", "<", ">=", "<=", "<>",
"+", "-", "*", "/", "^", "&"
"+", "-", "*", "/", "^", "&",
NULL, NULL, NULL, "-"
};
switch (tree->oper){
......@@ -1228,7 +1229,7 @@ do_expr_decode_tree (ExprTree *tree, Sheet *sheet, int col, int row, Operation p
a = do_expr_decode_tree (tree->u.binary.value_a, sheet, col, row, tree->oper);
b = do_expr_decode_tree (tree->u.binary.value_b, sheet, col, row, tree->oper);
op = binary_operation_names [tree->oper];
op = operation_names [tree->oper];
if (bigger_prec (parent_op, tree->oper))
res = g_strconcat ("(", a, op, b, ")", NULL);
......@@ -1244,7 +1245,7 @@ do_expr_decode_tree (ExprTree *tree, Sheet *sheet, int col, int row, Operation p
char *res, *a;
a = do_expr_decode_tree (tree->u.value, sheet, col, row, tree->oper);
res = g_strconcat ("-", a, NULL);
res = g_strconcat (operation_names[tree->oper], a, NULL);
g_free (a);
return res;
}
......@@ -1365,9 +1366,6 @@ do_expr_tree_relocate (ExprTree *tree, int coldiff, int rowdiff)
case OPER_FUNCALL: {
GList *l, *arg_list;
/* Why this? */
tree->ref_count++;
symbol_ref (tree->u.function.symbol);
new_tree->u.function.arg_list = NULL;
......@@ -1419,20 +1417,235 @@ expr_tree_relocate (ExprTree *tree, int coldiff, int rowdiff)
return do_expr_tree_relocate (tree, coldiff, rowdiff);
}
static ExprTree *
build_error_string (const char *txt)
{
ExprTree *val, *call;
Symbol *func;
val = g_new (ExprTree, 1);
val->oper = OPER_CONSTANT;
val->ref_count = 1;
val->u.constant = value_str (txt);
func = symbol_lookup (global_symbol_table, "ERROR");
if (func == NULL) {
g_assert_not_reached ();
return val;
}
call = g_new (ExprTree, 1);
call->oper = OPER_FUNCALL;
call->ref_count = 1;
symbol_ref ((call->u.function.symbol = func));
call->u.function.arg_list = g_list_prepend (NULL, val);
return call;
}
struct expr_tree_invalidate_references {
Sheet *sheet;
int src_col, src_row;
gboolean invalidating_columns;
/* Columns being invalidated. */
int col, colcount;
/* Rows being invalidated. */
int row, rowcount;
};
static ExprTree *
do_expr_tree_invalidate_references (ExprTree *src, const struct expr_tree_invalidate_references *info)
{
switch (src->oper) {
case OPER_ANY_BINARY: {
ExprTree *a =
do_expr_tree_invalidate_references (src->u.binary.value_a, info);
ExprTree *b =
do_expr_tree_invalidate_references (src->u.binary.value_b, info);
if (a == NULL && b == NULL)
return NULL;
else {
ExprTree *dst;
if (a == NULL)
expr_tree_ref ((a = src->u.binary.value_a));
if (b == NULL)
expr_tree_ref ((b = src->u.binary.value_b));
dst = g_new (ExprTree, 1);
dst->oper = src->oper;
dst->ref_count = 1;
dst->u.binary.value_a = a;
dst->u.binary.value_b = b;
return dst;
}
}
case OPER_ANY_UNARY: {
ExprTree *a =
do_expr_tree_invalidate_references (src->u.value, info);
if (a == NULL)
return NULL;
else {
ExprTree *dst;
dst = g_new (ExprTree, 1);
dst->oper = src->oper;
dst->ref_count = 1;
dst->u.value = a;
return dst;
}
}
case OPER_FUNCALL: {
gboolean any = FALSE;
GList *new_args = NULL;
GList *l;
for (l = src->u.function.arg_list; l; l = l->next) {
ExprTree *arg = do_expr_tree_invalidate_references (l->data, info);
new_args = g_list_append (new_args, arg);
if (arg) any = TRUE;
}
if (any) {
ExprTree *dst;
GList *m;
for (l = src->u.function.arg_list, m = new_args; l; l = l->next, m = m->next) {
if (m->data == NULL)
expr_tree_ref ((m->data = l->data));
}
dst = g_new (ExprTree, 1);
dst->oper = OPER_FUNCALL;
dst->ref_count = 1;
symbol_ref ((dst->u.function.symbol = src->u.function.symbol));
dst->u.function.arg_list = new_args;
return dst;
} else {
g_list_free (new_args);
return NULL;
}
}
case OPER_VAR: {
CellRef cr = src->u.ref; /* Copy a structure, not a pointer. */
cell_ref_make_absolute (&cr, info->src_col, info->src_row);
if (info->invalidating_columns
? (cr.col >= info->col && cr.col < info->col + info->colcount)
: (cr.row >= info->row && cr.row < info->row + info->rowcount)) {
return build_error_string ("#Reference to deleted cell!");
} else
return NULL;
}
case OPER_CONSTANT: {
Value *v = src->u.constant;
switch (v->type) {
case VALUE_STRING:
case VALUE_INTEGER:
case VALUE_FLOAT:
return NULL;
case VALUE_CELLRANGE:
case VALUE_ARRAY:
fprintf (stderr, "Reminder: FIXME in do_expr_tree_invalidate_references\n");
/* ??? */
return NULL;
}
g_assert_not_reached ();
return NULL;
}
}
g_assert_not_reached ();
return NULL;
}
ExprTree *
expr_tree_invalidate_references (ExprTree *src, Sheet *sheet,
int src_col, int src_row,
int col, int row,
int colcount, int rowcount)
{
struct expr_tree_invalidate_references info;
ExprTree *dst;
char *str;
g_return_val_if_fail (src != NULL, NULL);
g_return_val_if_fail (sheet != NULL, NULL);
g_return_val_if_fail (IS_SHEET (sheet), NULL);
info.sheet = sheet;
info.src_col = src_col;
info.src_row = src_row;
info.invalidating_columns = (colcount > 0);
info.col = col;
info.colcount = colcount;
info.row = row;
info.rowcount = rowcount;
str = expr_decode_tree (src, sheet, src_col, src_row);
printf ("%s: [%s]\n", cell_name (src_col, src_row), str);
g_free (str);
dst = do_expr_tree_invalidate_references (src, &info);
str = dst ? expr_decode_tree (dst, sheet, src_col, src_row) : g_strdup ("*");
printf ("%s: [%s]\n\n", cell_name (src_col, src_row), str);
g_free (str);
return dst;
}
struct expr_tree_fixup_references {
Sheet *sheet;
int src_col, src_row;
/* Starting point of fixup. */
int col, row;
/* Relative move. */
int coldelta, rowdelta;
};
static ExprTree *
do_expr_tree_fixup_references (ExprTree *src, const struct expr_tree_fixup_references *info)
{
/* FIXME */
return NULL;
}
ExprTree *
expr_tree_fixup_references (ExprTree *src, Sheet *sheet,
int col, int row,
int src_col, int src_row, int col, int row,
int coldelta, int rowdelta)
{
/* FIXME */
return NULL;
struct expr_tree_fixup_references info;
g_return_val_if_fail (src != NULL, NULL);
g_return_val_if_fail (sheet != NULL, NULL);
g_return_val_if_fail (IS_SHEET (sheet), NULL);
info.sheet = sheet;
info.src_col = src_col;
info.src_row = src_row;
info.col = col;
info.row = row;
info.coldelta = coldelta;
info.rowdelta = rowdelta;
return do_expr_tree_fixup_references (src, &info);
}
......@@ -162,11 +162,11 @@ void expr_tree_ref (ExprTree *tree);
void expr_tree_unref (ExprTree *tree);
ExprTree *expr_tree_invalidate_references (ExprTree *src, struct _Sheet *sheet,
int col, int row,
int src_col, int src_row, int col, int row,
int colcount, int rowcount);
ExprTree *expr_tree_fixup_references (ExprTree *src, struct _Sheet *sheet,
int col, int row,
int src_col, int src_row, int col, int row,
int coldelta, int rowdelta);
Value *eval_expr (struct _Sheet *sheet, ExprTree *tree,
......@@ -197,7 +197,7 @@ Value *value_duplicate (const Value *value);
Value *value_float (float_t f);
Value *value_int (int i);
Value *value_str (char *str);
Value *value_str (const char *str);
/* Setup of the symbol table */
void functions_init (void);
......
......@@ -22,7 +22,7 @@ static char *help_iserror = {
"Returns a TRUE value if the expression has an error\n"
"\n"
"@SEEALSO=")
"@SEEALSO=ERROR")
};
static Value *
......@@ -45,7 +45,35 @@ gnumeric_iserror (Sheet *sheet, GList *expr_node_list, int eval_col, int eval_ro
return retval;
}
static char *help_error = {
N_("@FUNCTION=ERROR\n"
"@SYNTAX=ERROR(text)\n"
"@DESCRIPTION="
"Return the specified error\n"
"\n"
"@SEEALSO=ISERROR")
};
static Value *
gnumeric_error (struct FunctionDefinition *i, Value *argv [], char **error_string)
{
if (argv [0]->type != VALUE_STRING){
*error_string = _("Type mismatch");
return NULL;
}
/* The error signaling system is broken. We really cannot allocate a
dynamic error string. Let's hope the string stays around for long
enough... */
*error_string = argv [0]->v.str->str;
return NULL;
}
FunctionDefinition misc_functions [] = {
{ "iserror", "", "", &help_iserror, gnumeric_iserror, NULL },
{ "error", "s", "text", &help_error, NULL, gnumeric_error },
{ "iserror", "", "", &help_iserror, gnumeric_iserror, NULL },
{ NULL, NULL }
};
......@@ -22,7 +22,7 @@ static char *help_iserror = {
"Returns a TRUE value if the expression has an error\n"
"\n"
"@SEEALSO=")
"@SEEALSO=ERROR")
};
static Value *
......@@ -45,7 +45,35 @@ gnumeric_iserror (Sheet *sheet, GList *expr_node_list, int eval_col, int eval_ro
return retval;
}
static char *help_error = {
N_("@FUNCTION=ERROR\n"
"@SYNTAX=ERROR(text)\n"
"@DESCRIPTION="
"Return the specified error\n"
"\n"
"@SEEALSO=ISERROR")
};
static Value *
gnumeric_error (struct FunctionDefinition *i, Value *argv [], char **error_string)
{
if (argv [0]->type != VALUE_STRING){
*error_string = _("Type mismatch");
return NULL;
}
/* The error signaling system is broken. We really cannot allocate a
dynamic error string. Let's hope the string stays around for long
enough... */
*error_string = argv [0]->v.str->str;
return NULL;
}
FunctionDefinition misc_functions [] = {
{ "iserror", "", "", &help_iserror, gnumeric_iserror, NULL },
{ "error", "s", "text", &help_error, NULL, gnumeric_error },
{ "iserror", "", "", &help_iserror, gnumeric_iserror, NULL },
{ NULL, NULL }
};
......@@ -2950,6 +2950,8 @@ sheet_insert_row (Sheet *sheet, int row, int count)
g_list_free (cell_store);
workbook_fixup_references (sheet->workbook, 0, row, 0, count);
/* 4. Recompute any changes required */
deps = region_get_dependencies (sheet, 0, row, SHEET_MAX_COLS-1, SHEET_MAX_ROWS-1);
cell_queue_recalc_list (deps);
......
......@@ -2085,7 +2085,6 @@ workbook_fixup_references (Workbook *wb, int col, int row,
int coldelta, int rowdelta)
{
GList *cells, *l;
gboolean debug = TRUE;
g_return_if_fail (wb != NULL);
......@@ -2094,7 +2093,7 @@ workbook_fixup_references (Workbook *wb, int col, int row,
/* Copy the list since it will change underneath us. */
cells = g_list_copy (wb->formula_cell_list);
for (l = wb->formula_cell_list; l; l = l->next) {
for (l = cells; l; l = l->next) {
Cell *cell = l->data;
ExprTree *newtree;
int thiscol, thisrow;
......@@ -2102,14 +2101,8 @@ workbook_fixup_references (Workbook *wb, int col, int row,
thiscol = cell->col->pos;
thisrow = cell->row->pos;
if (debug) {
char *str = cell_get_content (cell);
const char *cellname = cell_name (thiscol, thisrow);
printf ("Before %s: [%s]\n", cellname, str);
g_free (str);
}
newtree = expr_tree_fixup_references (cell->parsed_node, cell->sheet,
thiscol, thisrow,
col, row, coldelta, rowdelta);
if (newtree) {
char *exprtxt, *eqexprtxt;
......@@ -2121,15 +2114,6 @@ workbook_fixup_references (Workbook *wb, int col, int row,
g_free (exprtxt);
g_free (eqexprtxt);
expr_tree_unref (newtree);
if (debug) {
char *str = cell_get_content (cell);
const char *cellname = cell_name (thiscol, thisrow);
printf ("After %s: [%s]\n", cellname, str);
g_free (str);
}
} else {
printf ("Unchanged.\n");
}
}
......@@ -2152,7 +2136,6 @@ workbook_invalidate_references (Workbook *wb, int col, int row,
int colcount, int rowcount)
{
GList *cells, *l;
gboolean debug = TRUE;
g_return_if_fail (wb != NULL);
g_return_if_fail (colcount == 0 || rowcount == 0);
......@@ -2163,7 +2146,7 @@ workbook_invalidate_references (Workbook *wb, int col, int row,
/* Copy the list since it will change underneath us. */
cells = g_list_copy (wb->formula_cell_list);
for (l = wb->formula_cell_list; l; l = l->next) {
for (l = cells; l; l = l->next) {
Cell *cell = l->data;
ExprTree *newtree;
int thiscol, thisrow;
......@@ -2171,14 +2154,8 @@ workbook_invalidate_references (Workbook *wb, int col, int row,
thiscol = cell->col->pos;
thisrow = cell->row->pos;
if (debug) {
char *str = cell_get_content (cell);
const char *cellname = cell_name (thiscol, thisrow);
printf ("Before %s: [%s]\n", cellname, str);
g_free (str);
}
newtree = expr_tree_invalidate_references (cell->parsed_node, cell->sheet,
thiscol, thisrow,
col, row, colcount, rowcount);
if (newtree) {
char *exprtxt, *eqexprtxt;
......@@ -2190,15 +2167,6 @@ workbook_invalidate_references (Workbook *wb, int col, int row,
g_free (exprtxt);
g_free (eqexprtxt);
expr_tree_unref (newtree);
if (debug) {
char *str = cell_get_content (cell);
const char *cellname = cell_name (thiscol, thisrow);
printf ("After %s: [%s]\n", cellname, str);
g_free (str);
}
} else {
printf ("Unchanged.\n");
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment