expr.c 38.2 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
56
57
{
	ExprTree *ans = g_new (ExprTree, 1);
	if (!ans) return NULL;
	ans->ref_count = 1;
	ans->oper = OPER_CONSTANT;
	ans->u.constant = NULL;
	return ans;
}

Arturo Espinosa's avatar
Arturo Espinosa committed
58
59
60
61
/*
 * expr_tree_ref:
 * Increments the ref_count for part of a tree
 */
62
63
64
65
66
67
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
68
	tree->ref_count++;
Arturo Espinosa's avatar
Arturo Espinosa committed
69
70
71
72
73
}

static void
do_expr_tree_unref (ExprTree *tree)
{
Morten Welinder's avatar
Morten Welinder committed
74
75
76
	if (--tree->ref_count > 0)
		return;

Arturo Espinosa's avatar
Arturo Espinosa committed
77
	switch (tree->oper){
78
	case OPER_VAR:
Arturo Espinosa's avatar
Arturo Espinosa committed
79
		break;
80

81
	case OPER_CONSTANT:
Morten Welinder's avatar
Morten Welinder committed
82
		value_release (tree->u.constant);
Arturo Espinosa's avatar
Arturo Espinosa committed
83
		break;
84

Morten Welinder's avatar
Morten Welinder committed
85
86
87
88
89
90
91
	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
92
		break;
Morten Welinder's avatar
Morten Welinder committed
93
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
94

95
	case OPER_ANY_BINARY:
Arturo Espinosa's avatar
Arturo Espinosa committed
96
97
98
99
		do_expr_tree_unref (tree->u.binary.value_a);
		do_expr_tree_unref (tree->u.binary.value_b);
		break;

100
	case OPER_ANY_UNARY:
Arturo Espinosa's avatar
Arturo Espinosa committed
101
102
103
		do_expr_tree_unref (tree->u.value);
		break;
	}
104

Morten Welinder's avatar
Morten Welinder committed
105
	g_free (tree);
106
107
}

Morten Welinder's avatar
Morten Welinder committed
108
109
110
111
112
113
/*
 * 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.)
 */
114
115
116
117
118
119
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
120
	do_expr_tree_unref (tree);
121
122
}

Miguel de Icaza's avatar
Today:    
Miguel de Icaza committed
123
124
125
126
/*
 * simplistic value rendering
 */
char *
127
value_string (const Value *value)
Miguel de Icaza's avatar
Today:    
Miguel de Icaza committed
128
129
130
131
132
133
{
	switch (value->type){
	case VALUE_STRING:
		return g_strdup (value->v.str->str);

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

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

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

Miguel de Icaza's avatar
Today:    
Miguel de Icaza committed
142
	case VALUE_CELLRANGE:
Arturo Espinosa's avatar
Arturo Espinosa committed
143
		break;
Miguel de Icaza's avatar
Today:    
Miguel de Icaza committed
144
	}
145

Arturo Espinosa's avatar
Arturo Espinosa committed
146
	return g_strdup ("Internal problem");
Miguel de Icaza's avatar
Today:    
Miguel de Icaza committed
147
148
}

149
150
151
void
value_release (Value *value)
{
Arturo Espinosa's avatar
Arturo Espinosa committed
152
	g_return_if_fail (value != NULL);
153

154
155
156
157
158
159
160
	switch (value->type){
	case VALUE_STRING:
		string_unref (value->v.str);
		break;

	case VALUE_INTEGER:
		mpz_clear (value->v.v_int);
161
		break;
162

163
164
165
166
	case VALUE_FLOAT:
		mpf_clear (value->v.v_float);
		break;

167
168
	case VALUE_ARRAY:{
		guint i;
169

170
171
		for (i = 0; i < value->v.array.x; i++)
			g_free (value->v.array.vals [i]);
172

173
		g_free (value->v.array.vals);
Morten Welinder's avatar
Morten Welinder committed
174
		break;
Arturo Espinosa's avatar
Arturo Espinosa committed
175
	}
176

Arturo Espinosa's avatar
Arturo Espinosa committed
177
178
	case VALUE_CELLRANGE:
		break;
179

180
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
181
	g_free (value);
182
}
183

Arturo Espinosa's avatar
Arturo Espinosa committed
184
185
186
187
/*
 * Copies a Value.
 */
void
188
value_copy_to (Value *dest, const Value *source)
Arturo Espinosa's avatar
Arturo Espinosa committed
189
190
191
192
193
{
	g_return_if_fail (dest != NULL);
	g_return_if_fail (source != NULL);

	dest->type = source->type;
194

Arturo Espinosa's avatar
Arturo Espinosa committed
195
196
197
198
199
200
201
202
203
204
205
206
207
208
	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
209
	case VALUE_ARRAY: {
210
		value_array_copy_to (dest, source);
Arturo Espinosa's avatar
Arturo Espinosa committed
211
212
213
214
215
		break;
	}
	case VALUE_CELLRANGE:
		dest->v.cell_range = source->v.cell_range;
		break;
Arturo Espinosa's avatar
Arturo Espinosa committed
216
217
218
	}
}

Arturo Espinosa's avatar
Arturo Espinosa committed
219
220
221
222
/*
 * Makes a copy of a Value
 */
Value *
223
value_duplicate (const Value *value)
Arturo Espinosa's avatar
Arturo Espinosa committed
224
225
226
227
228
229
{
	Value *new_value;

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

Arturo Espinosa's avatar
Arturo Espinosa committed
231
232
233
	return new_value;
}

234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
Value *
value_float (float_t f)
{
	Value *v = g_new (Value, 1);

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

	return v;
}

Value *
value_int (int i)
{
	Value *v = g_new (Value, 1);

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

	return v;
}

256
Value *
257
value_str (const char *str)
258
259
260
261
262
263
264
265
266
{
	Value *v = g_new (Value, 1);

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

	return v;
}

267
Value *
Morten Welinder's avatar
Morten Welinder committed
268
value_cellrange (const CellRef *a, const CellRef *b)
269
270
{
	Value *v = g_new (Value, 1);
Morten Welinder's avatar
Morten Welinder committed
271

272
	v->type = VALUE_CELLRANGE;
Morten Welinder's avatar
Morten Welinder committed
273
274
275
	v->v.cell_range.cell_a = *a;
	v->v.cell_range.cell_b = *b;

276
277
278
	return v;
}

Arturo Espinosa's avatar
Arturo Espinosa committed
279
280
281
282
/*
 * Casts a value to float if it is integer, and returns
 * a new Value * if required
 */
283
Value *
284
value_cast_to_float (Value *v)
Arturo Espinosa's avatar
Arturo Espinosa committed
285
286
{
	Value *newv;
287

Arturo Espinosa's avatar
Arturo Espinosa committed
288
289
290
291
	g_return_val_if_fail (VALUE_IS_NUMBER (v), NULL);

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

Arturo Espinosa's avatar
Arturo Espinosa committed
293
294
295
	newv = g_new (Value, 1);
	newv->type = VALUE_FLOAT;
	mpf_set_z (newv->v.v_float, v->v.v_int);
296
	value_release (v);
297

Arturo Espinosa's avatar
Arturo Espinosa committed
298
299
300
	return newv;
}

Arturo Espinosa's avatar
Arturo Espinosa committed
301
int
302
value_get_bool (const Value *v, int *err)
Arturo Espinosa's avatar
Arturo Espinosa committed
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
{
	*err = 0;

	if (v->type == VALUE_STRING)
		return atoi (v->v.str->str);

	if (v->type == VALUE_CELLRANGE){
		*err = 1;
		return 0;
	}

	if (v->type == VALUE_INTEGER)
		return v->v.v_int != 0;

	if (v->type == VALUE_FLOAT)
		return v->v.v_float != 0.0;

	if (v->type == VALUE_ARRAY)
		return 0;
322

Arturo Espinosa's avatar
Arturo Espinosa committed
323
324
325
326
327
	g_warning ("Unhandled value in value_get_boolean");

	return 0;
}

Arturo Espinosa's avatar
Arturo Espinosa committed
328
float_t
329
value_get_as_double (const Value *v)
Arturo Espinosa's avatar
Arturo Espinosa committed
330
331
332
333
334
335
336
337
338
339
340
341
342
{
	if (v->type == VALUE_STRING){
		return atof (v->v.str->str);
	}

	if (v->type == VALUE_CELLRANGE){
		g_warning ("Getting range as a double: what to do?");
		return 0.0;
	}

	if (v->type == VALUE_INTEGER)
		return (float_t) v->v.v_int;

Arturo Espinosa's avatar
Arturo Espinosa committed
343
344
	if (v->type == VALUE_ARRAY)
		return 0.0;
345

Arturo Espinosa's avatar
Arturo Espinosa committed
346
	return (float_t) v->v.v_float;
Arturo Espinosa's avatar
Arturo Espinosa committed
347
348
}

349
int
350
value_get_as_int (const Value *v)
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
{
	if (v->type == VALUE_STRING){
		return atoi (v->v.str->str);
	}

	if (v->type == VALUE_CELLRANGE){
		g_warning ("Getting range as a double: what to do?");
		return 0.0;
	}

	if (v->type == VALUE_INTEGER)
		return v->v.v_int;

	if (v->type == VALUE_ARRAY)
		return 0.0;
366

367
368
369
	return (int) v->v.v_float;
}

370
371
372
Value *
value_array_new (guint width, guint height)
{
373
	int x, y;
374
375
376
377
378
379

	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);
380
381
382
383
384
385
386

	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;
387
388
389
390
391
392
393
394
		}
	}
	return v;
}

void
value_array_resize (Value *v, guint width, guint height)
{
395
	int x, xcpy, ycpy;
396
397
398
399
400
401
402
403
404
405
	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
406
		xcpy = width;
407
408
409
410
411
412

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

413
414
415
416
	for (x = 0; x < xcpy; x++){
		memcpy (newval->v.array.vals [x],
			v->v.array.vals [x],
			sizeof (Value) * ycpy);
417
418
419
420
	}
	v->v.array.vals = newval->v.array.vals;
	v->v.array.x = width;
	v->v.array.y = height;
421
	value_release (newval);
422
423
424
425
426
}

void
value_array_copy_to (Value *v, const Value *src)
{
427
	int x;
428
429
430
431
432
433

	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);
434
435
436

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

438
439
440
		memcpy (v->v.array.vals   [x],
			src->v.array.vals [x],
			sizeof(Value)*v->v.array.y);
441
442
443
444
445
446
447
448
449
	}
}

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);
450

451
452
453
454
455
456
457
458
459
460
461
462
463
	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);
464

465
466
467
468
469
470
471
472
473
474
475
476
477
	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,
478
479
480
			      value_int (0));

	if (v->type == VALUE_ARRAY){
481
		g_return_val_if_fail (v->v.array.x < x &&
482
483
484
				      v->v.array.y < y,
				      value_int (0));
		return &v->v.array.vals [x][y];
485
486
487
	} else {
		CellRef *a, *b;
		Cell *cell;
488

489
490
491
		a = &v->v.cell_range.cell_a;
		b = &v->v.cell_range.cell_b;
		g_return_val_if_fail (!a->col_relative,
492
				      value_int (0));
493
		g_return_val_if_fail (!b->col_relative,
494
				      value_int (0));
495
		g_return_val_if_fail (!a->row_relative,
496
				      value_int (0));
497
		g_return_val_if_fail (!b->row_relative,
498
				      value_int (0));
499
		g_return_val_if_fail (a->col<=b->col,
500
				      value_int (0));
501
		g_return_val_if_fail (a->row<=b->row,
502
				      value_int (0));
503

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

506
507
508
		if (cell && cell->value)
			return cell->value;
		else
509
			return value_int (0);
510
	}
511
	return value_int (0);
512
513
}

514
515
516
517
518
519
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)
520
		cell_ref->col = eval_col + cell_ref->col;
521
522
523

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

Arturo Espinosa's avatar
Arturo Espinosa committed
525
526
	cell_ref->row_relative = 0;
	cell_ref->col_relative = 0;
527
528
}

529
530
531
532
533
534
535
536
537
538
539
540
541
542
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
543
544
static Value *
eval_cell_value (Sheet *sheet, Value *value)
545
{
Arturo Espinosa's avatar
Arturo Espinosa committed
546
	Value *res;
547

Arturo Espinosa's avatar
Arturo Espinosa committed
548
549
	res = g_new (Value, 1);
	res->type = value->type;
550

Arturo Espinosa's avatar
Arturo Espinosa committed
551
552
553
	switch (res->type){
	case VALUE_STRING:
		res->v.str = value->v.str;
554
		string_ref (res->v.str);
Arturo Espinosa's avatar
Arturo Espinosa committed
555
		break;
556

Arturo Espinosa's avatar
Arturo Espinosa committed
557
	case VALUE_INTEGER:
558
		res->v.v_int = value->v.v_int;
Arturo Espinosa's avatar
Arturo Espinosa committed
559
		break;
560

Arturo Espinosa's avatar
Arturo Espinosa committed
561
	case VALUE_FLOAT:
562
		res->v.v_float = value->v.v_float;
Arturo Espinosa's avatar
Arturo Espinosa committed
563
		break;
Arturo Espinosa's avatar
Arturo Espinosa committed
564
565
566
567
568
569

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

Arturo Espinosa's avatar
Arturo Espinosa committed
571
572
573
574
575
576
577
	case VALUE_CELLRANGE:
		res->v.cell_range = value->v.cell_range;
		break;
	}
	return res;
}

578
579
580
581
static void
free_values (Value **values, int top)
{
	int i;
582

583
584
585
586
587
	for (i = 0; i < top; i++)
		value_release (values [i]);
	g_free (values);
}

Arturo Espinosa's avatar
Arturo Espinosa committed
588
589
590
591
592
593
594
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;
595

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

Arturo Espinosa's avatar
Arturo Espinosa committed
598
599
600
601
602
603
604
605
606
607
608
609
	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
610
611
612
		int fn_argc_min = 0, fn_argc_max = 0, var_len = 0;
		char *arg_type = fd->args;
		char *argptr = fd->args;
613

614
		/* Get variable limits */
Arturo Espinosa's avatar
Arturo Espinosa committed
615
616
617
618
		while (*argptr){
			if (*argptr++ == '|'){
				var_len = 1;
				continue;
619
620
			}
			if (!var_len)
Arturo Espinosa's avatar
Arturo Espinosa committed
621
622
				fn_argc_min++;
			fn_argc_max++;
623
		}
624

Arturo Espinosa's avatar
Arturo Espinosa committed
625
		if (argc > fn_argc_max || argc < fn_argc_min){
Arturo Espinosa's avatar
Arturo Espinosa committed
626
627
628
629
			*error_string = _("Invalid number of arguments");
			return NULL;
		}

630
		values = g_new (Value *, fn_argc_max);
631

632
		for (arg = 0; l; l = l->next, arg++, arg_type++){
Arturo Espinosa's avatar
Arturo Espinosa committed
633
			ExprTree *t = (ExprTree *) l->data;
634
			int type_mismatch = 0;
635

Arturo Espinosa's avatar
Arturo Espinosa committed
636
637
			if (*arg_type=='|')
				arg_type++;
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653

			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);
				v = value_cellrange (&t->u.ref,
						     &t->u.ref);
				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;
			}
654

Arturo Espinosa's avatar
Arturo Espinosa committed
655
			switch (*arg_type){
656
			case 'f':
657

658
659
660
661
				if (v->type != VALUE_INTEGER &&
				    v->type != VALUE_FLOAT)
					type_mismatch = 1;
				break;
662
			case 's':
663
664
				if (v->type != VALUE_STRING)
					type_mismatch = 1;
Arturo Espinosa's avatar
Arturo Espinosa committed
665
				break;
666
			case 'r':
667
668
669
670
671
				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);
672
				}
Arturo Espinosa's avatar
Arturo Espinosa committed
673
				break;
674
675
676
677
678
679
680
681
			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
682
683
684
685
686

				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);
				}
687
688
				break;
			}
689
			if (type_mismatch){
690
691
692
				free_values (values, arg);
				*error_string = _("Type mismatch");
				return NULL;
693
			}
Arturo Espinosa's avatar
Arturo Espinosa committed
694
695
			values [arg] = v;
		}
Arturo Espinosa's avatar
Arturo Espinosa committed
696
697
		while (arg < fn_argc_max)
			values [arg++] = NULL;
698
		v = fd->fn (fd, values, error_string);
Arturo Espinosa's avatar
Arturo Espinosa committed
699
700

	free_list:
701
		for (i = 0; i < arg; i++){
Arturo Espinosa's avatar
Arturo Espinosa committed
702
703
			if (values [i] != NULL)
				value_release (values [i]);
704
		}
Arturo Espinosa's avatar
Arturo Espinosa committed
705
706
707
708
709
710
		g_free (values);
		return v;
	}
	return v;
}

711
712
713
714
715
Value *
function_def_call_with_values (Sheet *sheet, FunctionDefinition *fd, int argc,
			       Value *values [], char **error_string)
{
	Value *retval;
716

717
718
719
720
721
722
723
724
725
726
727
	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);
728

729
			for (i = 0; i < argc; i++){
730
				tree [i].oper = OPER_CONSTANT;
731
732
				tree [i].ref_count = 1;
				tree [i].u.constant = values [i];
733

734
735
736
				l = g_list_append (l, &(tree[i]));
			}
		}
737

738
739
740
741
742
743
744
		retval = fd->expr_fn (sheet, l, 0, 0, error_string);

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

745
	} else
746
747
748
749
750
751
752
753
754
755
		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 *
756
function_call_with_values (Sheet *sheet, const char *name, int argc, Value *values[], char **error_string)
757
758
759
760
761
762
763
764
765
{
	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
766
	sym = symbol_lookup (global_symbol_table, name);
767
	if (sym == NULL){
768
		*error_string = _("Function does not exist");
769
770
		return NULL;
	}
771
	if (sym->type != SYMBOL_FUNCTION){
772
		*error_string = _("Calling non-function");
773
774
		return NULL;
	}
775

776
777
778
779
780
781
782
783
784
785
	fd = sym->data;

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

	symbol_unref (sym);

	return retval;
}

786
typedef enum {
Arturo Espinosa's avatar
Arturo Espinosa committed
787
788
	IS_EQUAL,
	IS_LESS,
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
	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
814

815
816
817
818
/*
 * Compares two (Value *) and returns one of compare_t
 */
static compare_t
Arturo Espinosa's avatar
Arturo Espinosa committed
819
820
compare (Value *a, Value *b)
{
821
822
	if (a->type == VALUE_INTEGER){
		int f;
823

824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
		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:
			f = value_get_as_double (b);
			return compare_float_float (a->v.v_int, f);

		default:
			return TYPE_ERROR;
		}
	}
839

840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
	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:
			f = value_get_as_double (b);
			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
872
873
}

Arturo Espinosa's avatar
Arturo Espinosa committed
874
Value *
875
eval_expr (Sheet *sheet, ExprTree *tree, int eval_col, int eval_row, char **error_string)
Arturo Espinosa's avatar
Arturo Espinosa committed
876
877
{
	Value *a, *b, *res;
Arturo Espinosa's avatar
Arturo Espinosa committed
878
879

	g_return_val_if_fail (tree != NULL, NULL);
880
	g_return_val_if_fail (sheet != NULL, NULL);
Arturo Espinosa's avatar
Arturo Espinosa committed
881
	g_return_val_if_fail (error_string != NULL, NULL);
882
	g_return_val_if_fail (IS_SHEET (sheet), NULL);
883

884
	switch (tree->oper){
885
886
887
888
889
890
	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
891
		int comp;
892

Arturo Espinosa's avatar
Arturo Espinosa committed
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
		a = eval_expr (sheet, tree->u.binary.value_a,
			       eval_col, eval_row, error_string);
		b = eval_expr (sheet, tree->u.binary.value_b,
			       eval_col, eval_row, error_string);
		if (!(a && b)){
			if (a)
				value_release (a);
			if (b)
				value_release (b);
			return NULL;
		}
		res = g_new (Value, 1);
		res->type = VALUE_INTEGER;

		comp = compare (a, b);

909
910
911
912
913
914
		if (comp == TYPE_ERROR){
			value_release (a);
			value_release (b);
			*error_string = _("Type error");
			return NULL;
		}
915

Arturo Espinosa's avatar
Arturo Espinosa committed
916
		switch (tree->oper){
917
		case OPER_EQUAL:
Arturo Espinosa's avatar
Arturo Espinosa committed
918
919
920
			res->v.v_int = comp == IS_EQUAL;
			break;

921
		case OPER_GT:
922
			res->v.v_int = comp == IS_GREATER;
Arturo Espinosa's avatar
Arturo Espinosa committed
923
924
			break;

925
		case OPER_LT:
Arturo Espinosa's avatar
Arturo Espinosa committed
926
927
928
			res->v.v_int = comp == IS_LESS;
			break;

929
		case OPER_LTE:
Arturo Espinosa's avatar
Arturo Espinosa committed
930
931
932
			res->v.v_int = (comp == IS_EQUAL || comp == IS_LESS);
			break;

933
		case OPER_GTE:
934
			res->v.v_int = (comp == IS_EQUAL || comp == IS_GREATER);
Arturo Espinosa's avatar
Arturo Espinosa committed
935
936
			break;

937
		case OPER_NOT_EQUAL:
Arturo Espinosa's avatar
Arturo Espinosa committed
938
939
			res->v.v_int = comp != IS_EQUAL;
			break;
940

Arturo Espinosa's avatar
Arturo Espinosa committed
941
942
943
944
945
946
947
		default:
			g_warning ("This should never be reached: comparission ops\n");
		}
		value_release (a);
		value_release (b);
		return res;
	}
948

949
950
951
952
953
	case OPER_ADD:
	case OPER_SUB:
	case OPER_MULT:
	case OPER_DIV:
	case OPER_EXP:
954
955
		a = eval_expr (sheet, tree->u.binary.value_a,
			       eval_col, eval_row, error_string);
956
957
958

		if (!a)
			return NULL;
959

960
961
		b = eval_expr (sheet, tree->u.binary.value_b,
			       eval_col, eval_row, error_string);
Arturo Espinosa's avatar
Arturo Espinosa committed
962

963
964
		if (!b){
			value_release (a);
Arturo Espinosa's avatar
Arturo Espinosa committed
965
966
			return NULL;
		}
967

Arturo Espinosa's avatar
Arturo Espinosa committed
968
		if (!VALUE_IS_NUMBER (a) || !VALUE_IS_NUMBER (b)){
969
970
			value_release (a);
			value_release (b);
Arturo Espinosa's avatar
Arturo Espinosa committed
971
972
973
			*error_string = _("Type mismatch");
			return NULL;
		}
974

Arturo Espinosa's avatar
Arturo Espinosa committed
975
976
		res = g_new (Value, 1);
		if (a->type == VALUE_INTEGER && b->type == VALUE_INTEGER){
977
978
			int ia = a->v.v_int;
			int ib = b->v.v_int;
979

Arturo Espinosa's avatar
Arturo Espinosa committed
980
			res->type = VALUE_INTEGER;
981

982
			switch (tree->oper){
983
			case OPER_SUB:
984
985
986
987
			case OPER_ADD: {
				int sum;

				if (tree->oper == OPER_SUB){
Arturo Espinosa's avatar
0.20    
Arturo Espinosa committed
988
					ib = -ib;
989
990
991
				}

				sum = ia + ib;
992

993
				if ((ia > 0) && (ib > 0)){
994

995
996
997
998
999
1000
					if (sum < ia){
						res->type = VALUE_FLOAT;
						res->v.v_float = ((double)ia) + ib;
					} else
						res->v.v_int = sum;
				} else if ((ia < 0) && (ib < 0)){
For faster browsing, not all history is shown. View entire blame