expr.c 39.5 KB
Newer Older
Miguel de Icaza's avatar
Miguel de Icaza committed
1 2 3 4 5 6
/*
 * expr.c: Expression evaluation in Gnumeriuc
 *
 * Author:
 *   Miguel de Icaza (miguel@gnu.org).
 */
7
#include <config.h>
Arturo Espinosa's avatar
Arturo Espinosa committed
8
#include <gnome.h>
Arturo Espinosa's avatar
Arturo Espinosa committed
9
#include <math.h>
10
#include <string.h>
Arturo Espinosa's avatar
Arturo Espinosa committed
11
#include "gnumeric.h"
Arturo Espinosa's avatar
Arturo Espinosa committed
12
#include "expr.h"
Arturo Espinosa's avatar
Arturo Espinosa committed
13
#include "eval.h"
Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
14
#include "format.h"
15
#include "func.h"
16
#include "utils.h"
17

18
ExprTree *
19 20
expr_parse_string (const char *expr, Sheet *sheet, int col, int row,
		   const char **desired_format, char **error_msg)
21
{
22
	ExprTree *tree;
23
	g_return_val_if_fail (expr != NULL, NULL);
24 25

	switch (gnumeric_expr_parser (expr, sheet, col, row, desired_format, &tree)) {
26 27
	case PARSE_OK:
		*error_msg = NULL;
28 29
		tree->ref_count = 1;
		return tree;
30

Arturo Espinosa's avatar
Arturo Espinosa committed
31 32 33
	case PARSE_ERR_SYNTAX:
		*error_msg = _("Syntax error");
		break;
34

35 36 37
	case PARSE_ERR_NO_QUOTE:
		*error_msg = _("Missing quote");
		break;
38
	default:
Arturo Espinosa's avatar
Arturo Espinosa committed
39 40 41
		g_assert_not_reached ();
		*error_msg = _("Impossible!");
		break;
42
	}
43 44 45
	return NULL;
}

46

47
ExprTree *
Morten Welinder's avatar
Morten Welinder committed
48
expr_tree_new (void)
49
{
50 51 52 53 54 55
	ExprTree *ans;

	ans = g_new (ExprTree, 1);
	if (!ans)
		return NULL;
	
56 57 58 59 60 61
	ans->ref_count = 1;
	ans->oper = OPER_CONSTANT;
	ans->u.constant = NULL;
	return ans;
}

Arturo Espinosa's avatar
Arturo Espinosa committed
62 63 64 65
/*
 * expr_tree_ref:
 * Increments the ref_count for part of a tree
 */
66 67 68 69 70 71
void
expr_tree_ref (ExprTree *tree)
{
	g_return_if_fail (tree != NULL);
	g_return_if_fail (tree->ref_count > 0);

Morten Welinder's avatar
Morten Welinder committed
72
	tree->ref_count++;
Arturo Espinosa's avatar
Arturo Espinosa committed
73 74 75 76 77
}

static void
do_expr_tree_unref (ExprTree *tree)
{
Morten Welinder's avatar
Morten Welinder committed
78 79 80
	if (--tree->ref_count > 0)
		return;

Arturo Espinosa's avatar
Arturo Espinosa committed
81
	switch (tree->oper){
82
	case OPER_VAR:
Arturo Espinosa's avatar
Arturo Espinosa committed
83
		break;
84

85
	case OPER_CONSTANT:
Morten Welinder's avatar
Morten Welinder committed
86
		value_release (tree->u.constant);
Arturo Espinosa's avatar
Arturo Espinosa committed
87
		break;
88

Morten Welinder's avatar
Morten Welinder committed
89 90 91 92 93 94 95
	case OPER_FUNCALL: {
		GList *l;

		for (l = tree->u.function.arg_list; l; l = l->next)
			do_expr_tree_unref (l->data);
		g_list_free (tree->u.function.arg_list);
		symbol_unref (tree->u.function.symbol);
Arturo Espinosa's avatar
Arturo Espinosa committed
96
		break;
Morten Welinder's avatar
Morten Welinder committed
97
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
98

99
	case OPER_ANY_BINARY:
Arturo Espinosa's avatar
Arturo Espinosa committed
100 101 102 103
		do_expr_tree_unref (tree->u.binary.value_a);
		do_expr_tree_unref (tree->u.binary.value_b);
		break;

104
	case OPER_ANY_UNARY:
Arturo Espinosa's avatar
Arturo Espinosa committed
105 106
		do_expr_tree_unref (tree->u.value);
		break;
107 108 109
	default:
		g_warning ("do_expr_tree_unref error\n");
		break;
Arturo Espinosa's avatar
Arturo Espinosa committed
110
	}
111

Morten Welinder's avatar
Morten Welinder committed
112
	g_free (tree);
113 114
}

Morten Welinder's avatar
Morten Welinder committed
115 116 117 118 119 120
/*
 * expr_tree_unref:
 * Decrements the ref_count for part of a tree.  (All trees are expected
 * to have been created with a ref-count of one, so when we hit zero, we
 * go down over the tree and unref the tree and its leaves stuff.)
 */
121 122 123 124 125 126
void
expr_tree_unref (ExprTree *tree)
{
	g_return_if_fail (tree != NULL);
	g_return_if_fail (tree->ref_count > 0);

Arturo Espinosa's avatar
Arturo Espinosa committed
127
	do_expr_tree_unref (tree);
128 129
}

Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
130 131 132 133
/*
 * simplistic value rendering
 */
char *
Michael Meeks's avatar
Michael Meeks committed
134
value_get_as_string (const Value *value)
Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
135 136 137 138 139 140
{
	switch (value->type){
	case VALUE_STRING:
		return g_strdup (value->v.str->str);

	case VALUE_INTEGER:
Arturo Espinosa's avatar
Arturo Espinosa committed
141
		return g_strdup_printf ("%d", value->v.v_int);
Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
142 143

	case VALUE_FLOAT:
Arturo Espinosa's avatar
Arturo Espinosa committed
144
		return g_strdup_printf ("%g", value->v.v_float);
Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
145 146

	case VALUE_ARRAY:
Arturo Espinosa's avatar
Arturo Espinosa committed
147
		return g_strdup ("ARRAY");
148

Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
149
	case VALUE_CELLRANGE:
Arturo Espinosa's avatar
Arturo Espinosa committed
150
		break;
151 152 153
	default:
		g_warning ("value_string problem\n");
		break;
Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
154
	}
155

Arturo Espinosa's avatar
Arturo Espinosa committed
156
	return g_strdup ("Internal problem");
Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
157 158
}

159 160 161
void
value_release (Value *value)
{
Arturo Espinosa's avatar
Arturo Espinosa committed
162
	g_return_if_fail (value != NULL);
163

164 165 166 167 168 169 170
	switch (value->type){
	case VALUE_STRING:
		string_unref (value->v.str);
		break;

	case VALUE_INTEGER:
		mpz_clear (value->v.v_int);
171
		break;
172

173 174 175 176
	case VALUE_FLOAT:
		mpf_clear (value->v.v_float);
		break;

177 178
	case VALUE_ARRAY:{
		guint i;
179

180 181
		for (i = 0; i < value->v.array.x; i++)
			g_free (value->v.array.vals [i]);
182

183
		g_free (value->v.array.vals);
Morten Welinder's avatar
Morten Welinder committed
184
		break;
Arturo Espinosa's avatar
Arturo Espinosa committed
185
	}
186

Arturo Espinosa's avatar
Arturo Espinosa committed
187 188
	case VALUE_CELLRANGE:
		break;
189

190 191 192
	default:
		g_warning ("value_release problem\n");
		break;
193
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
194
	g_free (value);
195
}
196

Arturo Espinosa's avatar
Arturo Espinosa committed
197 198 199 200
/*
 * Copies a Value.
 */
void
201
value_copy_to (Value *dest, const Value *source)
Arturo Espinosa's avatar
Arturo Espinosa committed
202 203 204 205 206
{
	g_return_if_fail (dest != NULL);
	g_return_if_fail (source != NULL);

	dest->type = source->type;
207

Arturo Espinosa's avatar
Arturo Espinosa committed
208 209 210 211 212 213 214 215 216 217 218 219 220 221
	switch (source->type){
	case VALUE_STRING:
		dest->v.str = source->v.str;
		string_ref (dest->v.str);
		break;

	case VALUE_INTEGER:
		dest->v.v_int = source->v.v_int;
		break;

	case VALUE_FLOAT:
		dest->v.v_float = source->v.v_float;
		break;

Arturo Espinosa's avatar
Arturo Espinosa committed
222
	case VALUE_ARRAY: {
223
		value_array_copy_to (dest, source);
Arturo Espinosa's avatar
Arturo Espinosa committed
224 225 226 227 228
		break;
	}
	case VALUE_CELLRANGE:
		dest->v.cell_range = source->v.cell_range;
		break;
229 230 231
	default:
		g_warning ("value_copy_to problem\n");
		break;
Arturo Espinosa's avatar
Arturo Espinosa committed
232 233 234
	}
}

Arturo Espinosa's avatar
Arturo Espinosa committed
235 236 237 238
/*
 * Makes a copy of a Value
 */
Value *
239
value_duplicate (const Value *value)
Arturo Espinosa's avatar
Arturo Espinosa committed
240 241 242 243 244 245
{
	Value *new_value;

	g_return_val_if_fail (value != NULL, NULL);
	new_value = g_new (Value, 1);
	value_copy_to (new_value, value);
246

Arturo Espinosa's avatar
Arturo Espinosa committed
247 248 249
	return new_value;
}

250
Value *
Michael Meeks's avatar
Michael Meeks committed
251
value_new_float (float_t f)
252 253 254 255 256 257 258 259 260 261
{
	Value *v = g_new (Value, 1);

	v->type = VALUE_FLOAT;
	v->v.v_float = f;

	return v;
}

Value *
Michael Meeks's avatar
Michael Meeks committed
262
value_new_int (int i)
263 264 265 266 267 268 269 270 271
{
	Value *v = g_new (Value, 1);

	v->type = VALUE_INTEGER;
	v->v.v_int = i;

	return v;
}

272
Value *
Michael Meeks's avatar
Michael Meeks committed
273
value_new_string (const char *str)
274 275 276 277 278 279 280 281 282
{
	Value *v = g_new (Value, 1);

	v->type = VALUE_STRING;
	v->v.str = string_get (str);

	return v;
}

283
Value *
Michael Meeks's avatar
Michael Meeks committed
284
value_new_cellrange (const CellRef *a, const CellRef *b)
285 286
{
	Value *v = g_new (Value, 1);
Morten Welinder's avatar
Morten Welinder committed
287

288
	v->type = VALUE_CELLRANGE;
Morten Welinder's avatar
Morten Welinder committed
289 290 291
	v->v.cell_range.cell_a = *a;
	v->v.cell_range.cell_b = *b;

292 293 294
	return v;
}

Arturo Espinosa's avatar
Arturo Espinosa committed
295 296 297 298
/*
 * Casts a value to float if it is integer, and returns
 * a new Value * if required
 */
299
Value *
300
value_cast_to_float (Value *v)
Arturo Espinosa's avatar
Arturo Espinosa committed
301 302
{
	Value *newv;
303

Arturo Espinosa's avatar
Arturo Espinosa committed
304 305 306 307
	g_return_val_if_fail (VALUE_IS_NUMBER (v), NULL);

	if (v->type == VALUE_FLOAT)
		return v;
308

Arturo Espinosa's avatar
Arturo Espinosa committed
309 310 311
	newv = g_new (Value, 1);
	newv->type = VALUE_FLOAT;
	mpf_set_z (newv->v.v_float, v->v.v_int);
312
	value_release (v);
313

Arturo Espinosa's avatar
Arturo Espinosa committed
314 315 316
	return newv;
}

Arturo Espinosa's avatar
Arturo Espinosa committed
317
int
Michael Meeks's avatar
Michael Meeks committed
318
value_get_as_bool (const Value *v, int *err)
Arturo Espinosa's avatar
Arturo Espinosa committed
319 320 321
{
	*err = 0;

322 323
	switch (v->type) {
	case VALUE_STRING:
Arturo Espinosa's avatar
Arturo Espinosa committed
324 325
		return atoi (v->v.str->str);

326
	case VALUE_CELLRANGE:
Arturo Espinosa's avatar
Arturo Espinosa committed
327 328
		*err = 1;
		return 0;
329 330
		
	case VALUE_INTEGER:
Arturo Espinosa's avatar
Arturo Espinosa committed
331 332
		return v->v.v_int != 0;

333
	case VALUE_FLOAT:
Arturo Espinosa's avatar
Arturo Espinosa committed
334 335
		return v->v.v_float != 0.0;

336
	case VALUE_ARRAY:
Arturo Espinosa's avatar
Arturo Espinosa committed
337
		return 0;
338 339 340 341
	default:
		g_warning ("Unhandled value in value_get_boolean");
		break;
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
342 343 344
	return 0;
}

Arturo Espinosa's avatar
Arturo Espinosa committed
345
float_t
Michael Meeks's avatar
Michael Meeks committed
346
value_get_as_float (const Value *v)
Arturo Espinosa's avatar
Arturo Espinosa committed
347
{
348 349 350
	switch (v->type)
	{
	case VALUE_STRING:
Arturo Espinosa's avatar
Arturo Espinosa committed
351 352
		return atof (v->v.str->str);

353
	case VALUE_CELLRANGE:
Arturo Espinosa's avatar
Arturo Espinosa committed
354 355 356
		g_warning ("Getting range as a double: what to do?");
		return 0.0;

357
	case VALUE_INTEGER:
Arturo Espinosa's avatar
Arturo Espinosa committed
358
		return (float_t) v->v.v_int;
359 360
		
	case VALUE_ARRAY:
Arturo Espinosa's avatar
Arturo Espinosa committed
361
		return 0.0;
362

363 364 365
	case VALUE_FLOAT:
		return (float_t) v->v.v_float;
	default:
Michael Meeks's avatar
Michael Meeks committed
366
		g_warning ("value_get_as_float type error\n");
367 368 369
		break;
	}
	return 0.0;
Arturo Espinosa's avatar
Arturo Espinosa committed
370 371
}

372
int
373
value_get_as_int (const Value *v)
374
{
375 376 377
	switch (v->type)
	{
	case VALUE_STRING:
378 379
		return atoi (v->v.str->str);

380
	case VALUE_CELLRANGE:
381 382 383
		g_warning ("Getting range as a double: what to do?");
		return 0.0;

384
	case VALUE_INTEGER:
385 386
		return v->v.v_int;

387
	case VALUE_ARRAY:
388
		return 0.0;
389

390 391 392 393 394 395
	case VALUE_FLOAT:
		return (int) v->v.v_float;
	default:
		g_warning ("value_get_as_int unknown type\n");
		break;
	}
Michael Meeks's avatar
Michael Meeks committed
396
	return 0.0;
397 398
}

399 400 401
Value *
value_array_new (guint width, guint height)
{
402
	int x, y;
403 404 405 406 407 408

	Value *v = g_new (Value, 1);
	v->type = VALUE_ARRAY;
	v->v.array.x = width;
	v->v.array.y = height;
	v->v.array.vals = g_new (Value *, width);
409 410 411 412 413 414 415

	for (x = 0; x < width; x++){
		v->v.array.vals [x] = g_new (Value, height);

		for (y = 0; y < height; y++){
			v->v.array.vals[x][y].type = VALUE_INTEGER;
			v->v.array.vals[x][y].v.v_int = 0;
416 417 418 419 420
		}
	}
	return v;
}

Michael Meeks's avatar
Michael Meeks committed
421 422 423 424 425 426 427 428 429 430 431 432 433
void
value_array_set (Value *array, guint col, guint row, Value *v)
{
	g_return_if_fail (v);
	g_return_if_fail (v->type == VALUE_ARRAY);
	g_return_if_fail (col>=0);
	g_return_if_fail (row>=0);
	g_return_if_fail (v->v.array.y <= row);
	g_return_if_fail (v->v.array.x <= col);

	memcpy (&array->v.array.vals[col][row], v, sizeof (Value));
}

434 435 436
void
value_array_resize (Value *v, guint width, guint height)
{
437
	int x, xcpy, ycpy;
438 439 440 441 442 443 444 445 446 447
	Value *newval;

	g_return_if_fail (v);
	g_return_if_fail (v->type == VALUE_ARRAY);

	newval = value_array_new (width, height);

	if (width>v->v.array.x)
		xcpy = v->v.array.x;
	else
448
		xcpy = width;
449 450 451 452 453 454

	if (height>v->v.array.y)
		ycpy = v->v.array.y;
	else
		ycpy = height;

455 456 457 458
	for (x = 0; x < xcpy; x++){
		memcpy (newval->v.array.vals [x],
			v->v.array.vals [x],
			sizeof (Value) * ycpy);
459 460 461 462
	}
	v->v.array.vals = newval->v.array.vals;
	v->v.array.x = width;
	v->v.array.y = height;
463
	value_release (newval);
464 465 466 467 468
}

void
value_array_copy_to (Value *v, const Value *src)
{
469
	int x;
470 471 472 473 474 475

	g_return_if_fail (src->type == VALUE_ARRAY);
	v->type = VALUE_ARRAY;
	v->v.array.x = src->v.array.x;
	v->v.array.y = src->v.array.y;
	v->v.array.vals = g_new (Value *, v->v.array.x);
476 477 478

	for (x = 0; x < v->v.array.x; x++){
		v->v.array.vals [x] = g_new (Value,v->v.array.y);
479

480 481 482
		memcpy (v->v.array.vals   [x],
			src->v.array.vals [x],
			sizeof(Value)*v->v.array.y);
483 484 485 486 487 488 489 490 491
	}
}

guint
value_area_get_width (Value *v)
{
	g_return_val_if_fail (v, 0);
	g_return_val_if_fail (v->type == VALUE_ARRAY ||
			      v->type == VALUE_CELLRANGE, 1);
492

493 494 495 496 497 498 499 500 501 502 503 504 505
	if (v->type == VALUE_ARRAY)
		return v->v.array.x;
	else
		return v->v.cell_range.cell_b.col -
		       v->v.cell_range.cell_a.col + 1;
}

guint
value_area_get_height (Value *v)
{
	g_return_val_if_fail (v, 0);
	g_return_val_if_fail (v->type == VALUE_ARRAY ||
			      v->type == VALUE_CELLRANGE, 1);
506

507 508 509 510 511 512 513 514 515 516 517 518 519
	if (v->type == VALUE_ARRAY)
		return v->v.array.y;
	else
		return v->v.cell_range.cell_b.row -
		       v->v.cell_range.cell_a.row + 1;
}

const Value *
value_area_get_at_x_y (Value *v, guint x, guint y)
{
	g_return_val_if_fail (v, 0);
	g_return_val_if_fail (v->type == VALUE_ARRAY ||
			      v->type == VALUE_CELLRANGE,
Michael Meeks's avatar
Michael Meeks committed
520
			     value_new_int (0));
521 522

	if (v->type == VALUE_ARRAY){
523
		g_return_val_if_fail (v->v.array.x < x &&
524
				      v->v.array.y < y,
Michael Meeks's avatar
Michael Meeks committed
525
				     value_new_int (0));
526
		return &v->v.array.vals [x][y];
527 528 529
	} else {
		CellRef *a, *b;
		Cell *cell;
530

531 532 533
		a = &v->v.cell_range.cell_a;
		b = &v->v.cell_range.cell_b;
		g_return_val_if_fail (!a->col_relative,
Michael Meeks's avatar
Michael Meeks committed
534
				     value_new_int (0));
535
		g_return_val_if_fail (!b->col_relative,
Michael Meeks's avatar
Michael Meeks committed
536
				      value_new_int (0));
537
		g_return_val_if_fail (!a->row_relative,
Michael Meeks's avatar
Michael Meeks committed
538
				     value_new_int (0));
539
		g_return_val_if_fail (!b->row_relative,
Michael Meeks's avatar
Michael Meeks committed
540
				     value_new_int (0));
541
		g_return_val_if_fail (a->col<=b->col,
Michael Meeks's avatar
Michael Meeks committed
542
				     value_new_int (0));
543
		g_return_val_if_fail (a->row<=b->row,
Michael Meeks's avatar
Michael Meeks committed
544
				     value_new_int (0));
545

546
		cell = sheet_cell_get (a->sheet, a->col+x, a->row+y);
547

548 549 550
		if (cell && cell->value)
			return cell->value;
	}
Michael Meeks's avatar
Michael Meeks committed
551 552
	
	g_warning ("Leaked on array\n");
Michael Meeks's avatar
Michael Meeks committed
553
	return value_new_int (0);
554 555
}

556 557 558 559 560 561
static void
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)
562
		cell_ref->col = eval_col + cell_ref->col;
563 564 565

	if (cell_ref->row_relative)
		cell_ref->row = eval_row + cell_ref->row;
566

Arturo Espinosa's avatar
Arturo Espinosa committed
567 568
	cell_ref->row_relative = 0;
	cell_ref->col_relative = 0;
569 570
}

571 572 573 574 575 576 577 578 579 580 581 582 583 584
static void
cell_ref_restore_absolute (CellRef *cell_ref, const CellRef *orig, int eval_col, int eval_row)
{
	if (orig->col_relative) {
		cell_ref->col -= eval_col;
		cell_ref->col_relative = 1;
	}

	if (orig->row_relative) {
		cell_ref->row -= eval_row;
		cell_ref->row_relative = 1;
	}
}

Arturo Espinosa's avatar
Arturo Espinosa committed
585 586
static Value *
eval_cell_value (Sheet *sheet, Value *value)
587
{
Arturo Espinosa's avatar
Arturo Espinosa committed
588
	Value *res;
589

Arturo Espinosa's avatar
Arturo Espinosa committed
590 591
	res = g_new (Value, 1);
	res->type = value->type;
592

Arturo Espinosa's avatar
Arturo Espinosa committed
593 594 595
	switch (res->type){
	case VALUE_STRING:
		res->v.str = value->v.str;
596
		string_ref (res->v.str);
Arturo Espinosa's avatar
Arturo Espinosa committed
597
		break;
598

Arturo Espinosa's avatar
Arturo Espinosa committed
599
	case VALUE_INTEGER:
600
		res->v.v_int = value->v.v_int;
Arturo Espinosa's avatar
Arturo Espinosa committed
601
		break;
602

Arturo Espinosa's avatar
Arturo Espinosa committed
603
	case VALUE_FLOAT:
604
		res->v.v_float = value->v.v_float;
Arturo Espinosa's avatar
Arturo Espinosa committed
605
		break;
Arturo Espinosa's avatar
Arturo Espinosa committed
606 607 608 609 610 611

	case VALUE_ARRAY:
		g_warning ("VALUE_ARRAY not handled in eval_cell_value\n");
		res->type = VALUE_INTEGER;
		res->v.v_int = 0;
		break;
612

Arturo Espinosa's avatar
Arturo Espinosa committed
613 614 615
	case VALUE_CELLRANGE:
		res->v.cell_range = value->v.cell_range;
		break;
616 617 618
	default:
		g_warning ("eval_cell_value error\n");
		break;
Arturo Espinosa's avatar
Arturo Espinosa committed
619 620 621 622
	}
	return res;
}

623 624 625 626
static void
free_values (Value **values, int top)
{
	int i;
627

628 629 630 631 632
	for (i = 0; i < top; i++)
		value_release (values [i]);
	g_free (values);
}

Arturo Espinosa's avatar
Arturo Espinosa committed
633 634 635 636 637 638 639
static Value *
eval_funcall (Sheet *sheet, ExprTree *tree, int eval_col, int eval_row, char **error_string)
{
	FunctionDefinition *fd;
	GList *l;
	int argc, arg, i;
	Value *v;
640

Arturo Espinosa's avatar
Arturo Espinosa committed
641
	fd = (FunctionDefinition *) tree->u.function.symbol->data;
642

Arturo Espinosa's avatar
Arturo Espinosa committed
643 644 645 646 647 648 649 650 651 652 653 654
	l = tree->u.function.arg_list;
	argc = g_list_length (l);

	if (fd->expr_fn)
	{
		/* Functions that deal with ExprNodes */
		v = fd->expr_fn (sheet, l, eval_col, eval_row, error_string);
	}
	else
	{
		/* Functions that take pre-computed Values */
		Value **values;
Arturo Espinosa's avatar
Arturo Espinosa committed
655 656 657
		int fn_argc_min = 0, fn_argc_max = 0, var_len = 0;
		char *arg_type = fd->args;
		char *argptr = fd->args;
658

659
		/* Get variable limits */
Arturo Espinosa's avatar
Arturo Espinosa committed
660 661 662 663
		while (*argptr){
			if (*argptr++ == '|'){
				var_len = 1;
				continue;
664 665
			}
			if (!var_len)
Arturo Espinosa's avatar
Arturo Espinosa committed
666 667
				fn_argc_min++;
			fn_argc_max++;
668
		}
669

Arturo Espinosa's avatar
Arturo Espinosa committed
670
		if (argc > fn_argc_max || argc < fn_argc_min){
Arturo Espinosa's avatar
Arturo Espinosa committed
671 672 673 674
			*error_string = _("Invalid number of arguments");
			return NULL;
		}

675
		values = g_new (Value *, fn_argc_max);
676

677
		for (arg = 0; l; l = l->next, arg++, arg_type++){
Arturo Espinosa's avatar
Arturo Espinosa committed
678
			ExprTree *t = (ExprTree *) l->data;
679
			int type_mismatch = 0;
680

Arturo Espinosa's avatar
Arturo Espinosa committed
681 682
			if (*arg_type=='|')
				arg_type++;
683 684 685 686 687 688 689 690 691

			if ((*arg_type != 'A' &&          /* This is so a cell reference */
			     *arg_type != 'r') ||         /* can be converted to a cell range */
			    !t || (t->oper != OPER_VAR)) { /* without being evaluated */
				if ((v = eval_expr (sheet, t, eval_col,
						    eval_row, error_string))==NULL)
					goto free_list;
			} else {
				g_assert (t->oper == OPER_VAR);
Michael Meeks's avatar
Michael Meeks committed
692 693
				v =value_new_cellrange (&t->u.ref,
							 &t->u.ref);
694 695 696 697 698
				if (!v->v.cell_range.cell_a.sheet)
					v->v.cell_range.cell_a.sheet = sheet;
				if (!v->v.cell_range.cell_b.sheet)
					v->v.cell_range.cell_b.sheet = sheet;
			}
699

Arturo Espinosa's avatar
Arturo Espinosa committed
700
			switch (*arg_type){
701
			case 'f':
702

703 704 705 706
				if (v->type != VALUE_INTEGER &&
				    v->type != VALUE_FLOAT)
					type_mismatch = 1;
				break;
707
			case 's':
708 709
				if (v->type != VALUE_STRING)
					type_mismatch = 1;
Arturo Espinosa's avatar
Arturo Espinosa committed
710
				break;
711
			case 'r':
712 713 714 715 716
				if (v->type != VALUE_CELLRANGE)
					type_mismatch = 1;
				else {
					cell_ref_make_absolute (&v->v.cell_range.cell_a, eval_col, eval_row);
					cell_ref_make_absolute (&v->v.cell_range.cell_b, eval_col, eval_row);
717
				}
Arturo Espinosa's avatar
Arturo Espinosa committed
718
				break;
719 720 721 722 723 724 725 726
			case 'a':
				if (v->type != VALUE_ARRAY)
					type_mismatch = 1;
				break;
			case 'A':
				if (v->type != VALUE_ARRAY &&
				    v->type != VALUE_CELLRANGE)
					type_mismatch = 1;
Michael Meeks's avatar
Michael Meeks committed
727 728 729 730 731

				if (v->type == VALUE_CELLRANGE) {
					cell_ref_make_absolute (&v->v.cell_range.cell_a, eval_col, eval_row);
					cell_ref_make_absolute (&v->v.cell_range.cell_b, eval_col, eval_row);
				}
732 733
				break;
			}
734
			if (type_mismatch){
735 736 737
				free_values (values, arg);
				*error_string = _("Type mismatch");
				return NULL;
738
			}
Arturo Espinosa's avatar
Arturo Espinosa committed
739 740
			values [arg] = v;
		}
Arturo Espinosa's avatar
Arturo Espinosa committed
741 742
		while (arg < fn_argc_max)
			values [arg++] = NULL;
743
		v = fd->fn (fd, values, error_string);
Arturo Espinosa's avatar
Arturo Espinosa committed
744 745

	free_list:
746
		for (i = 0; i < arg; i++){
Arturo Espinosa's avatar
Arturo Espinosa committed
747 748
			if (values [i] != NULL)
				value_release (values [i]);
749
		}
Arturo Espinosa's avatar
Arturo Espinosa committed
750 751 752 753 754 755
		g_free (values);
		return v;
	}
	return v;
}

756 757 758 759 760
Value *
function_def_call_with_values (Sheet *sheet, FunctionDefinition *fd, int argc,
			       Value *values [], char **error_string)
{
	Value *retval;
761

762 763 764 765 766 767 768 769 770 771 772
	if (fd->expr_fn){
		/*
		 * If function deals with ExprNodes, create some
		 * temporary ExprNodes with constants.
		 */
		ExprTree *tree = NULL;
		GList *l = NULL;
		int i;

		if (argc){
			tree = g_new (ExprTree, argc);
773

774
			for (i = 0; i < argc; i++){
775
				tree [i].oper = OPER_CONSTANT;
776 777
				tree [i].ref_count = 1;
				tree [i].u.constant = values [i];
778

779 780 781
				l = g_list_append (l, &(tree[i]));
			}
		}
782

783 784 785 786 787 788 789
		retval = fd->expr_fn (sheet, l, 0, 0, error_string);

		if (tree){
			g_free (tree);
			g_list_free (l);
		}

790
	} else
791 792 793 794 795 796 797 798 799 800
		retval = fd->fn (fd, values, error_string);

	return retval;
}

/*
 * Use this to invoke a register function: the only drawback is that
 * you have to compute/expand all of the values to use this
 */
Value *
801
function_call_with_values (Sheet *sheet, const char *name, int argc, Value *values[], char **error_string)
802 803 804 805 806 807 808 809 810
{
	FunctionDefinition *fd;
	Value *retval;
	Symbol *sym;

	g_return_val_if_fail (sheet != NULL, NULL);
	g_return_val_if_fail (IS_SHEET (sheet), NULL);
	g_return_val_if_fail (name != NULL, NULL);

Miguel de Icaza's avatar
Miguel de Icaza committed
811
	sym = symbol_lookup (global_symbol_table, name);
812
	if (sym == NULL){
813
		*error_string = _("Function does not exist");
814 815
		return NULL;
	}
816
	if (sym->type != SYMBOL_FUNCTION){
817
		*error_string = _("Calling non-function");
818 819
		return NULL;
	}
820

821 822 823 824 825 826 827 828 829 830
	fd = sym->data;

	symbol_ref (sym);
	retval = function_def_call_with_values (sheet, fd, argc, values, error_string);

	symbol_unref (sym);

	return retval;
}

831
typedef enum {
Arturo Espinosa's avatar
Arturo Espinosa committed
832 833
	IS_EQUAL,
	IS_LESS,
834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858
	IS_GREATER,
	TYPE_ERROR
} compare_t;

static compare_t
compare_int_int (int a, int b)
{
	if (a == b)
		return IS_EQUAL;
	else if (a < b)
		return IS_LESS;
	else
		return IS_GREATER;
}

static compare_t
compare_float_float (float_t a, float_t b)
{
	if (a == b)
		return IS_EQUAL;
	else if (a < b)
		return IS_LESS;
	else
		return IS_GREATER;
}
Arturo Espinosa's avatar
Arturo Espinosa committed
859

860 861 862 863
/*
 * Compares two (Value *) and returns one of compare_t
 */
static compare_t
Arturo Espinosa's avatar
Arturo Espinosa committed
864 865
compare (Value *a, Value *b)
{
866 867
	if (a->type == VALUE_INTEGER){
		int f;
868

869 870 871 872 873 874 875 876
		switch (b->type){
		case VALUE_INTEGER:
			return compare_int_int (a->v.v_int, b->v.v_int);

		case VALUE_FLOAT:
			return compare_float_float (a->v.v_int, b->v.v_float);

		case VALUE_STRING:
Michael Meeks's avatar
Michael Meeks committed
877
			f =value_get_as_float (b);
878 879 880 881 882 883
			return compare_float_float (a->v.v_int, f);

		default:
			return TYPE_ERROR;
		}
	}
884

885 886 887 888 889 890 891 892 893 894 895
	if (a->type == VALUE_FLOAT){
		float_t f;

		switch (b->type){
		case VALUE_INTEGER:
			return compare_float_float (a->v.v_float, b->v.v_int);

		case VALUE_FLOAT:
			return compare_float_float (a->v.v_float, b->v.v_float);

		case VALUE_STRING:
Michael Meeks's avatar
Michael Meeks committed
896
			f =value_get_as_float (b);
897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916
			return compare_float_float (a->v.v_float, f);

		default:
			return TYPE_ERROR;
		}
	}

	if (a->type == VALUE_STRING && b->type == VALUE_STRING){
		int t;

		t = strcasecmp (a->v.str->str, b->v.str->str);
		if (t == 0)
			return IS_EQUAL;
		else if (t > 0)
			return IS_GREATER;
		else
			return IS_LESS;
	}

	return TYPE_ERROR;
Arturo Espinosa's avatar
Arturo Espinosa committed
917 918
}

Arturo Espinosa's avatar
Arturo Espinosa committed
919
Value *
920
eval_expr (Sheet *sheet, ExprTree *tree, int eval_col, int eval_row, char **error_string)
Arturo Espinosa's avatar
Arturo Espinosa committed
921 922
{
	Value *a, *b, *res;
Arturo Espinosa's avatar
Arturo Espinosa committed
923 924

	g_return_val_if_fail (tree != NULL, NULL);
925
	g_return_val_if_fail (sheet != NULL, NULL);
Arturo Espinosa's avatar
Arturo Espinosa committed
926
	g_return_val_if_fail (error_string != NULL, NULL);
927
	g_return_val_if_fail (IS_SHEET (sheet), NULL);
928

929
	switch (tree->oper){
930 931 932 933 934 935
	case OPER_EQUAL:
	case OPER_NOT_EQUAL:
	case OPER_GT:
	case OPER_GTE:
	case OPER_LT:
	case OPER_LTE: {
Arturo Espinosa's avatar
Arturo Espinosa committed
936
		int comp;
937