1 /*
2  * expr.c : Expression evaluation in Gnumeric
3  *
4  * Copyright (C) 2001-2006 Jody Goldberg (jody@gnome.org)
5  * Copyright (C) 1998-2000 Miguel de Icaza (miguel@gnu.org)
6  * Copyright (C) 2000-2018 Morten Welinder (terra@gnome.org)
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of the
11  * License, or (at your option) version 3.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
21  * USA
22  */
23 #include <gnumeric-config.h>
24 #include <glib/gi18n-lib.h>
25 #include <gnumeric.h>
26 #include <expr.h>
27 
28 #include <expr-impl.h>
29 #include <expr-name.h>
30 #include <dependent.h>
31 #include <application.h>
32 #include <func.h>
33 #include <cell.h>
34 #include <sheet.h>
35 #include <value.h>
36 #include <parse-util.h>
37 #include <ranges.h>
38 #include <number-match.h>
39 #include <workbook.h>
40 #include <gutils.h>
41 #include <parse-util.h>
42 #include <mathfunc.h>
43 
44 #include <goffice/goffice.h>
45 #include <math.h>
46 #include <string.h>
47 #include <stdlib.h>
48 
49 /*
50  * Using pools here probably does not save anything, but it's a darn
51  * good debugging tool.
52  */
53 #ifndef USE_EXPR_POOLS
54 #define USE_EXPR_POOLS 1
55 #endif
56 
57 #if USE_EXPR_POOLS
58 /* Memory pools for expressions.  */
59 static GOMemChunk *expression_pool_small, *expression_pool_big;
60 #define CHUNK_ALLOC(T,p) ((T*)go_mem_chunk_alloc (p))
61 #define CHUNK_FREE(p,v) go_mem_chunk_free ((p), (v))
62 #else
63 #define CHUNK_ALLOC(T,c) g_new (T,1)
64 #define CHUNK_FREE(p,v) g_free ((v))
65 #endif
66 
67 /***************************************************************************/
68 
69 /**
70  * gnm_expr_new_constant:
71  * @v: (transfer full): #GnmValue
72  *
73  * Returns: (transfer full): constant expression.
74  **/
75 GnmExpr const *
gnm_expr_new_constant(GnmValue * v)76 gnm_expr_new_constant (GnmValue *v)
77 {
78 	GnmExprConstant *ans;
79 
80 	g_return_val_if_fail (v != NULL, NULL);
81 
82 	ans = CHUNK_ALLOC (GnmExprConstant, expression_pool_small);
83 	if (!ans)
84 		return NULL;
85 	gnm_expr_constant_init (ans, v);
86 
87 	return (GnmExpr *)ans;
88 }
89 
90 /***************************************************************************/
91 
92 /**
93  * gnm_expr_new_funcallv: (skip)
94  * @func: #GnmFunc
95  * @argc: argument count
96  * @argv: (in) (transfer full) (array length=argc): transfers everything
97  *
98  * Returns: (transfer full): function call expression.
99  */
100 static GnmExpr const *
gnm_expr_new_funcallv(GnmFunc * func,int argc,GnmExprConstPtr * argv)101 gnm_expr_new_funcallv (GnmFunc *func, int argc, GnmExprConstPtr *argv)
102 {
103 	GnmExprFunction *ans;
104 	g_return_val_if_fail (func, NULL);
105 
106 	ans = CHUNK_ALLOC (GnmExprFunction, expression_pool_small);
107 
108 	ans->oper = GNM_EXPR_OP_FUNCALL;
109 	gnm_func_inc_usage (func);
110 	ans->func = func;
111 	ans->argc = argc;
112 	ans->argv = argv;
113 
114 	return (GnmExpr *)ans;
115 }
116 
117 /**
118  * gnm_expr_new_funcall:
119  * @func: #GnmFunc
120  * @args: (transfer full): argument list
121  *
122  * Returns: (transfer full): function call expression.
123  */
124 GnmExpr const *
gnm_expr_new_funcall(GnmFunc * func,GnmExprList * args)125 gnm_expr_new_funcall (GnmFunc *func, GnmExprList *args)
126 {
127 	int argc = gnm_expr_list_length (args);
128 	GnmExprConstPtr *argv = NULL;
129 
130 	if (args) {
131 		GnmExprList *args0 = args;
132 		int i = 0;
133 
134 		argv = g_new (GnmExprConstPtr, argc);
135 		for (; args; args = args->next)
136 			argv[i++] = args->data;
137 		gnm_expr_list_free (args0);
138 	}
139 
140 	return gnm_expr_new_funcallv (func, argc, argv);
141 }
142 
143 /**
144  * gnm_expr_new_funcall1:
145  * @func: #GnmFunc
146  * @arg0: (transfer full): argument
147  *
148  * Returns: (transfer full): function call expression.
149  */
150 GnmExpr const *
gnm_expr_new_funcall1(GnmFunc * func,GnmExpr const * arg0)151 gnm_expr_new_funcall1 (GnmFunc *func,
152 		       GnmExpr const *arg0)
153 {
154 	GnmExprConstPtr *argv = g_new (GnmExprConstPtr, 1);
155 	argv[0] = arg0;
156 	return gnm_expr_new_funcallv (func, 1, argv);
157 }
158 
159 /**
160  * gnm_expr_new_funcall2:
161  * @func: #GnmFunc
162  * @arg0: (transfer full): argument
163  * @arg1: (transfer full): argument
164  *
165  * Returns: (transfer full): function call expression.
166  */
167 GnmExpr const *
gnm_expr_new_funcall2(GnmFunc * func,GnmExpr const * arg0,GnmExpr const * arg1)168 gnm_expr_new_funcall2 (GnmFunc *func,
169 		       GnmExpr const *arg0,
170 		       GnmExpr const *arg1)
171 {
172 	GnmExprConstPtr *argv = g_new (GnmExprConstPtr, 2);
173 	argv[0] = arg0;
174 	argv[1] = arg1;
175 	return gnm_expr_new_funcallv (func, 2, argv);
176 }
177 
178 /**
179  * gnm_expr_new_funcall3:
180  * @func: #GnmFunc
181  * @arg0: (transfer full): argument
182  * @arg1: (transfer full): argument
183  * @arg2: (transfer full): argument
184  *
185  * Returns: (transfer full): function call expression.
186  */
187 GnmExpr const *
gnm_expr_new_funcall3(GnmFunc * func,GnmExpr const * arg0,GnmExpr const * arg1,GnmExpr const * arg2)188 gnm_expr_new_funcall3 (GnmFunc *func,
189 		       GnmExpr const *arg0,
190 		       GnmExpr const *arg1,
191 		       GnmExpr const *arg2)
192 {
193 	GnmExprConstPtr *argv = g_new (GnmExprConstPtr, 3);
194 	argv[0] = arg0;
195 	argv[1] = arg1;
196 	argv[2] = arg2;
197 	return gnm_expr_new_funcallv (func, 3, argv);
198 }
199 
200 /**
201  * gnm_expr_new_funcall4:
202  * @func: #GnmFunc
203  * @arg0: (transfer full): argument
204  * @arg1: (transfer full): argument
205  * @arg2: (transfer full): argument
206  * @arg3: (transfer full): argument
207  *
208  * Returns: (transfer full): function call expression.
209  */
210 GnmExpr const *
gnm_expr_new_funcall4(GnmFunc * func,GnmExpr const * arg0,GnmExpr const * arg1,GnmExpr const * arg2,GnmExpr const * arg3)211 gnm_expr_new_funcall4 (GnmFunc *func,
212 		       GnmExpr const *arg0,
213 		       GnmExpr const *arg1,
214 		       GnmExpr const *arg2,
215 		       GnmExpr const *arg3)
216 {
217 	GnmExprConstPtr *argv = g_new (GnmExprConstPtr, 4);
218 	argv[0] = arg0;
219 	argv[1] = arg1;
220 	argv[2] = arg2;
221 	argv[3] = arg3;
222 	return gnm_expr_new_funcallv (func, 4, argv);
223 }
224 
225 /**
226  * gnm_expr_new_funcall5:
227  * @func: #GnmFunc
228  * @arg0: (transfer full): argument
229  * @arg1: (transfer full): argument
230  * @arg2: (transfer full): argument
231  * @arg3: (transfer full): argument
232  * @arg4: (transfer full): argument
233  *
234  * Returns: (transfer full): function call expression.
235  */
236 GnmExpr const *
gnm_expr_new_funcall5(GnmFunc * func,GnmExpr const * arg0,GnmExpr const * arg1,GnmExpr const * arg2,GnmExpr const * arg3,GnmExpr const * arg4)237 gnm_expr_new_funcall5 (GnmFunc *func,
238 		       GnmExpr const *arg0,
239 		       GnmExpr const *arg1,
240 		       GnmExpr const *arg2,
241 		       GnmExpr const *arg3,
242 		       GnmExpr const *arg4)
243 {
244 	GnmExprConstPtr *argv = g_new (GnmExprConstPtr, 5);
245 	argv[0] = arg0;
246 	argv[1] = arg1;
247 	argv[2] = arg2;
248 	argv[3] = arg3;
249 	argv[4] = arg4;
250 	return gnm_expr_new_funcallv (func, 5, argv);
251 }
252 
253 
254 /***************************************************************************/
255 
256 /**
257  * gnm_expr_new_unary:
258  * @op: Unary operator
259  * @e: (transfer full): #GnmExpr
260  *
261  * Returns: (transfer full): Unary expression
262  */
263 GnmExpr const *
gnm_expr_new_unary(GnmExprOp op,GnmExpr const * e)264 gnm_expr_new_unary (GnmExprOp op, GnmExpr const *e)
265 {
266 	GnmExprUnary *ans;
267 
268 	ans = CHUNK_ALLOC (GnmExprUnary, expression_pool_small);
269 	if (!ans)
270 		return NULL;
271 
272 	ans->oper = op;
273 	ans->value = e;
274 
275 	return (GnmExpr *)ans;
276 }
277 
278 /***************************************************************************/
279 
280 /**
281  * gnm_expr_new_binary:
282  * @l: (transfer full): left operand.
283  * @op: Unary operator
284  * @r: (transfer full): right operand.
285  *
286  * Returns: (transfer full): Binary expression
287  */
288 GnmExpr const *
gnm_expr_new_binary(GnmExpr const * l,GnmExprOp op,GnmExpr const * r)289 gnm_expr_new_binary (GnmExpr const *l, GnmExprOp op, GnmExpr const *r)
290 {
291 	GnmExprBinary *ans;
292 
293 	ans = CHUNK_ALLOC (GnmExprBinary, expression_pool_small);
294 	if (!ans)
295 		return NULL;
296 
297 	ans->oper = op;
298 	ans->value_a = l;
299 	ans->value_b = r;
300 
301 	return (GnmExpr *)ans;
302 }
303 
304 /***************************************************************************/
305 
306 GnmExpr const *
gnm_expr_new_name(GnmNamedExpr * name,Sheet * optional_scope,Workbook * optional_wb_scope)307 gnm_expr_new_name (GnmNamedExpr *name,
308 		   Sheet *optional_scope, Workbook *optional_wb_scope)
309 {
310 	GnmExprName *ans;
311 
312 	ans = CHUNK_ALLOC (GnmExprName, expression_pool_big);
313 	if (!ans)
314 		return NULL;
315 
316 	ans->oper = GNM_EXPR_OP_NAME;
317 	ans->name = name;
318 	expr_name_ref (name);
319 
320 	ans->optional_scope = optional_scope;
321 	ans->optional_wb_scope = optional_wb_scope;
322 
323 	return (GnmExpr *)ans;
324 }
325 
326 /***************************************************************************/
327 
328 /**
329  * gnm_expr_new_cellref:
330  * @cr: (transfer none): cell reference
331  *
332  * Returns: (transfer full): expression referencing @cr.
333  */
334 GnmExpr const *
gnm_expr_new_cellref(GnmCellRef const * cr)335 gnm_expr_new_cellref (GnmCellRef const *cr)
336 {
337 	GnmExprCellRef *ans;
338 
339 	ans = CHUNK_ALLOC (GnmExprCellRef, expression_pool_big);
340 	if (!ans)
341 		return NULL;
342 
343 	ans->oper = GNM_EXPR_OP_CELLREF;
344 	ans->ref = *cr;
345 
346 	return (GnmExpr *)ans;
347 }
348 
349 /***************************************************************************/
350 
351 /**
352  * gnm_expr_is_array:
353  * @expr: #GnmExpr
354  *
355  * Returns: %TRUE if @expr is an array expression, either a corner or a
356  * non-corner element.
357  */
358 static gboolean
gnm_expr_is_array(GnmExpr const * expr)359 gnm_expr_is_array (GnmExpr const *expr)
360 {
361 	return expr &&
362 		(GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_ARRAY_ELEM ||
363 		 GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_ARRAY_CORNER);
364 }
365 
366 /**
367  * gnm_expr_new_array_corner:
368  * @cols: Number of columns
369  * @rows: Number of rows
370  * @expr: (transfer full) (nullable): #GnmExpr
371  *
372  * Returns: (transfer full): An array corner expression
373  **/
374 static GnmExpr const *
gnm_expr_new_array_corner(int cols,int rows,GnmExpr const * expr)375 gnm_expr_new_array_corner(int cols, int rows, GnmExpr const *expr)
376 {
377 	GnmExprArrayCorner *ans;
378 
379 	g_return_val_if_fail (!gnm_expr_is_array (expr), NULL);
380 
381 	ans = CHUNK_ALLOC (GnmExprArrayCorner, expression_pool_big);
382 	ans->oper = GNM_EXPR_OP_ARRAY_CORNER;
383 	ans->rows = rows;
384 	ans->cols = cols;
385 	ans->value = NULL;
386 	ans->expr = expr;
387 	return (GnmExpr *)ans;
388 }
389 
390 /**
391  * gnm_expr_new_array_elem:
392  * @x: Column number relative to corner
393  * @y: Row number relative to corner
394  *
395  * Returns: (transfer full): An array non-corner expression
396  **/
397 static GnmExpr const *
gnm_expr_new_array_elem(int x,int y)398 gnm_expr_new_array_elem  (int x, int y)
399 {
400 	GnmExprArrayElem *ans;
401 
402 	ans = CHUNK_ALLOC (GnmExprArrayElem, expression_pool_small);
403 	ans->oper = GNM_EXPR_OP_ARRAY_ELEM;
404 	ans->x = x;
405 	ans->y = y;
406 	return (GnmExpr *)ans;
407 }
408 
409 /***************************************************************************/
410 
411 static GnmExpr const *
gnm_expr_new_setv(int argc,GnmExprConstPtr * argv)412 gnm_expr_new_setv (int argc, GnmExprConstPtr *argv)
413 {
414 	GnmExprSet *ans = CHUNK_ALLOC (GnmExprSet, expression_pool_small);
415 
416 	ans->oper = GNM_EXPR_OP_SET;
417 	ans->argc = argc;
418 	ans->argv = argv;
419 
420 	return (GnmExpr *)ans;
421 }
422 
423 /**
424  * gnm_expr_new_set:
425  * @args: (transfer full): element list
426  *
427  * Returns: (transfer full): set expression.
428  */
429 GnmExpr const *
gnm_expr_new_set(GnmExprList * set)430 gnm_expr_new_set (GnmExprList *set)
431 {
432 	int i, argc;
433 	GnmExprConstPtr *argv;
434 	GnmExprList *set0 = set;
435 
436 	argc = gnm_expr_list_length (set);
437 	argv = argc ? g_new (GnmExprConstPtr, argc) : NULL;
438 	for (i = 0; set; i++, set = set->next)
439 		argv[i] = set->data;
440 	gnm_expr_list_free (set0);
441 
442 	return gnm_expr_new_setv (argc, argv);
443 }
444 
445 /***************************************************************************/
446 
447 /**
448  * gnm_expr_new_range_ctor:
449  * @l: (transfer full): start range
450  * @r: (transfer full): end range
451  *
452  * This function builds a range constructor or something simpler,
453  * but equivalent, if the arguments allow it.
454  *
455  * Returns: (transfer full): And expression referencing @l to @r.
456  **/
457 GnmExpr const *
gnm_expr_new_range_ctor(GnmExpr const * l,GnmExpr const * r)458 gnm_expr_new_range_ctor (GnmExpr const *l, GnmExpr const *r)
459 {
460 	GnmValue *v;
461 
462 	g_return_val_if_fail (l != NULL, NULL);
463 	g_return_val_if_fail (r != NULL, NULL);
464 
465 	if (GNM_EXPR_GET_OPER (l) != GNM_EXPR_OP_CELLREF)
466 		goto fallback;
467 	if (GNM_EXPR_GET_OPER (r) != GNM_EXPR_OP_CELLREF)
468 		goto fallback;
469 
470 	v = value_new_cellrange_unsafe (&l->cellref.ref, &r->cellref.ref);
471 	gnm_expr_free (l);
472 	gnm_expr_free (r);
473 	return gnm_expr_new_constant (v);
474 
475  fallback:
476 	return gnm_expr_new_binary (l, GNM_EXPR_OP_RANGE_CTOR, r);
477 }
478 
479 /***************************************************************************/
480 
481 /**
482  * gnm_expr_copy:
483  * @expr: (transfer none): #GnmExpr
484  *
485  * Returns: (transfer full): A deep copy of @expr.
486  **/
487 GnmExpr const *
gnm_expr_copy(GnmExpr const * expr)488 gnm_expr_copy (GnmExpr const *expr)
489 {
490 	g_return_val_if_fail (expr != NULL, NULL);
491 
492 	switch (GNM_EXPR_GET_OPER (expr)) {
493 	case GNM_EXPR_OP_RANGE_CTOR:
494 	case GNM_EXPR_OP_INTERSECT:
495 	case GNM_EXPR_OP_ANY_BINARY:
496 		return gnm_expr_new_binary
497 			(gnm_expr_copy (expr->binary.value_a),
498 			 GNM_EXPR_GET_OPER (expr),
499 			 gnm_expr_copy (expr->binary.value_b));
500 
501 	case GNM_EXPR_OP_ANY_UNARY:
502 		return gnm_expr_new_unary
503 			(GNM_EXPR_GET_OPER (expr),
504 			 gnm_expr_copy (expr->unary.value));
505 
506 	case GNM_EXPR_OP_FUNCALL: {
507 		GnmExprConstPtr *argv =
508 			g_new (GnmExprConstPtr, expr->func.argc);
509 		int i;
510 
511 		for (i = 0; i < expr->func.argc; i++)
512 			argv[i] = gnm_expr_copy (expr->func.argv[i]);
513 
514 		return gnm_expr_new_funcallv
515 			(expr->func.func,
516 			 expr->func.argc,
517 			 argv);
518 	}
519 
520 	case GNM_EXPR_OP_NAME:
521 		return gnm_expr_new_name
522 			(expr->name.name,
523 			 expr->name.optional_scope,
524 			 expr->name.optional_wb_scope);
525 
526 	case GNM_EXPR_OP_CONSTANT:
527 		return gnm_expr_new_constant
528 			(value_dup (expr->constant.value));
529 
530 	case GNM_EXPR_OP_CELLREF:
531 		return gnm_expr_new_cellref (&expr->cellref.ref);
532 
533 	case GNM_EXPR_OP_ARRAY_CORNER:
534 		return gnm_expr_new_array_corner
535 			(expr->array_corner.cols, expr->array_corner.rows,
536 			 gnm_expr_copy (expr->array_corner.expr));
537 
538 	case GNM_EXPR_OP_ARRAY_ELEM:
539 		return gnm_expr_new_array_elem
540 			(expr->array_elem.x,
541 			 expr->array_elem.y);
542 
543 	case GNM_EXPR_OP_SET: {
544 		GnmExprConstPtr *argv =
545 			g_new (GnmExprConstPtr, expr->set.argc);
546 		int i;
547 
548 		for (i = 0; i < expr->set.argc; i++)
549 			argv[i] = gnm_expr_copy (expr->set.argv[i]);
550 
551 		return gnm_expr_new_setv
552 			(expr->set.argc,
553 			 argv);
554 	}
555 
556 #ifndef DEBUG_SWITCH_ENUM
557 	default:
558 		g_assert_not_reached ();
559 		break;
560 #endif
561 	}
562 }
563 
564 /**
565  * gnm_expr_free:
566  * @expr: (transfer full): #GnmExpr
567  *
568  * Deletes @expr with all its subexpressions.
569  */
570 void
gnm_expr_free(GnmExpr const * expr)571 gnm_expr_free (GnmExpr const *expr)
572 {
573 	g_return_if_fail (expr != NULL);
574 
575 	switch (GNM_EXPR_GET_OPER (expr)) {
576 	case GNM_EXPR_OP_RANGE_CTOR:
577 	case GNM_EXPR_OP_INTERSECT:
578 	case GNM_EXPR_OP_ANY_BINARY:
579 		gnm_expr_free (expr->binary.value_a);
580 		gnm_expr_free (expr->binary.value_b);
581 		CHUNK_FREE (expression_pool_small, (gpointer)expr);
582 		break;
583 
584 	case GNM_EXPR_OP_FUNCALL: {
585 		int i;
586 
587 		for (i = 0; i < expr->func.argc; i++)
588 			gnm_expr_free (expr->func.argv[i]);
589 		g_free (expr->func.argv);
590 		gnm_func_dec_usage (expr->func.func);
591 		CHUNK_FREE (expression_pool_small, (gpointer)expr);
592 		break;
593 	}
594 
595 	case GNM_EXPR_OP_NAME:
596 		expr_name_unref (expr->name.name);
597 		CHUNK_FREE (expression_pool_big, (gpointer)expr);
598 		break;
599 
600 	case GNM_EXPR_OP_CONSTANT:
601 		value_release ((GnmValue *)expr->constant.value);
602 		CHUNK_FREE (expression_pool_small, (gpointer)expr);
603 		break;
604 
605 	case GNM_EXPR_OP_CELLREF:
606 		CHUNK_FREE (expression_pool_big, (gpointer)expr);
607 		break;
608 
609 	case GNM_EXPR_OP_ANY_UNARY:
610 		gnm_expr_free (expr->unary.value);
611 		CHUNK_FREE (expression_pool_small, (gpointer)expr);
612 		break;
613 
614 	case GNM_EXPR_OP_ARRAY_CORNER:
615 		value_release (expr->array_corner.value);
616 		// A proper corner will not have NULL here, but we explicitly allow it
617 		// during construction, so allow it here too.
618 		if (expr->array_corner.expr)
619 			gnm_expr_free (expr->array_corner.expr);
620 		CHUNK_FREE (expression_pool_big, (gpointer)expr);
621 		break;
622 
623 	case GNM_EXPR_OP_ARRAY_ELEM:
624 		CHUNK_FREE (expression_pool_small, (gpointer)expr);
625 		break;
626 
627 	case GNM_EXPR_OP_SET: {
628 		int i;
629 
630 		for (i = 0; i < expr->set.argc; i++)
631 			gnm_expr_free (expr->set.argv[i]);
632 		g_free (expr->set.argv);
633 		CHUNK_FREE (expression_pool_small, (gpointer)expr);
634 		break;
635 	}
636 
637 #ifndef DEBUG_SWITCH_ENUM
638 	default:
639 		g_assert_not_reached ();
640 		break;
641 #endif
642 	}
643 }
644 
645 GType
gnm_expr_get_type(void)646 gnm_expr_get_type (void)
647 {
648 	static GType t = 0;
649 
650 	if (t == 0) {
651 		t = g_boxed_type_register_static ("GnmExpr",
652 			 (GBoxedCopyFunc)gnm_expr_copy,
653 			 (GBoxedFreeFunc)gnm_expr_free);
654 	}
655 	return t;
656 }
657 
658 GType
gnm_expr_array_corner_get_type(void)659 gnm_expr_array_corner_get_type (void)
660 {
661 	static GType t = 0;
662 
663 	if (t == 0) {
664 		t = g_boxed_type_register_static ("GnmExprArrayCorner",
665 			 (GBoxedCopyFunc)gnm_expr_copy,
666 			 (GBoxedFreeFunc)gnm_expr_free);
667 	}
668 	return t;
669 }
670 
671 /**
672  * gnm_expr_equal:
673  * @a: first #GnmExpr
674  * @b: first #GnmExpr
675  *
676  * Returns: %TRUE, if the supplied expressions are exactly the
677  *   same and %FALSE otherwise.  No eval position is used to see if they
678  *   are effectively the same.  Named expressions must refer the same name,
679  *   having equivalent names is insufficient.
680  */
681 gboolean
gnm_expr_equal(GnmExpr const * a,GnmExpr const * b)682 gnm_expr_equal (GnmExpr const *a, GnmExpr const *b)
683 {
684 	if (a == b)
685 		return TRUE;
686 
687 	g_return_val_if_fail (a != NULL, FALSE);
688 	g_return_val_if_fail (b != NULL, FALSE);
689 
690 	if (GNM_EXPR_GET_OPER (a) != GNM_EXPR_GET_OPER (b))
691 		return FALSE;
692 
693 	switch (GNM_EXPR_GET_OPER (a)) {
694 	case GNM_EXPR_OP_RANGE_CTOR:
695 	case GNM_EXPR_OP_INTERSECT:
696 	case GNM_EXPR_OP_ANY_BINARY:
697 		return	gnm_expr_equal (a->binary.value_a, b->binary.value_a) &&
698 			gnm_expr_equal (a->binary.value_b, b->binary.value_b);
699 
700 	case GNM_EXPR_OP_ANY_UNARY:
701 		return gnm_expr_equal (a->unary.value, b->unary.value);
702 
703 	case GNM_EXPR_OP_FUNCALL: {
704 		int i;
705 
706 		if (a->func.func != b->func.func ||
707 		    a->func.argc != b->func.argc)
708 			return FALSE;
709 
710 		for (i = 0; i < a->func.argc; i++)
711 			if (!gnm_expr_equal (a->func.argv[i], b->func.argv[i]))
712 				return FALSE;
713 		return TRUE;
714 	}
715 
716 	case GNM_EXPR_OP_NAME:
717 		return	a->name.name == b->name.name &&
718 			a->name.optional_scope == b->name.optional_scope &&
719 			a->name.optional_wb_scope == b->name.optional_wb_scope;
720 
721 	case GNM_EXPR_OP_CELLREF:
722 		return gnm_cellref_equal (&a->cellref.ref, &b->cellref.ref);
723 
724 	case GNM_EXPR_OP_CONSTANT:
725 		return value_equal (a->constant.value, b->constant.value);
726 
727 	case GNM_EXPR_OP_ARRAY_CORNER: {
728 		GnmExprArrayCorner const *aa = &a->array_corner;
729 		GnmExprArrayCorner const *ab = &b->array_corner;
730 
731 		return	aa->cols == ab->cols &&
732 			aa->rows == ab->rows &&
733 			gnm_expr_equal (aa->expr, ab->expr);
734 	}
735 	case GNM_EXPR_OP_ARRAY_ELEM: {
736 		GnmExprArrayElem const *aa = &a->array_elem;
737 		GnmExprArrayElem const *ab = &b->array_elem;
738 		return	aa->x == ab->x && aa->y == ab->y;
739 	}
740 
741 	case GNM_EXPR_OP_SET: {
742 		int i;
743 
744 		if (a->set.argc != b->set.argc)
745 			return FALSE;
746 
747 		for (i = 0; i < a->set.argc; i++)
748 			if (!gnm_expr_equal (a->set.argv[i], b->set.argv[i]))
749 				return FALSE;
750 		return TRUE;
751 	}
752 	}
753 
754 	return FALSE;
755 }
756 
757 static GnmCell *
array_elem_get_corner(GnmExprArrayElem const * elem,Sheet const * sheet,GnmCellPos const * pos)758 array_elem_get_corner (GnmExprArrayElem const *elem,
759 		       Sheet const *sheet, GnmCellPos const *pos)
760 {
761 	GnmCell *corner = sheet_cell_get (sheet,
762 		pos->col - elem->x, pos->row - elem->y);
763 
764 	/* Sanity check incase the corner gets removed for some reason */
765 	g_return_val_if_fail (corner != NULL, NULL);
766 	g_return_val_if_fail (gnm_cell_has_expr (corner), NULL);
767 	g_return_val_if_fail (corner->base.texpr != (void *)0xdeadbeef, NULL);
768 	g_return_val_if_fail (GNM_IS_EXPR_TOP (corner->base.texpr), NULL);
769 
770 	return corner;
771 }
772 
773 static gboolean
gnm_expr_extract_ref(GnmRangeRef * res,GnmExpr const * expr,GnmEvalPos const * pos,GnmExprEvalFlags flags)774 gnm_expr_extract_ref (GnmRangeRef *res, GnmExpr const *expr,
775 		      GnmEvalPos const *pos, GnmExprEvalFlags flags)
776 {
777 	switch (GNM_EXPR_GET_OPER (expr)) {
778 	case GNM_EXPR_OP_FUNCALL : {
779 		gboolean failed = TRUE;
780 		GnmValue *v;
781 		GnmFuncEvalInfo ei;
782 
783 		ei.pos = pos;
784 		ei.func_call = &expr->func;
785 		ei.flags = flags;
786 		v = function_call_with_exprs (&ei);
787 
788 		if (v != NULL) {
789 			if (VALUE_IS_CELLRANGE (v)) {
790 				*res = v->v_range.cell;
791 				failed = FALSE;
792 			}
793 			value_release (v);
794 		}
795 		return failed;
796 	}
797 
798 	case GNM_EXPR_OP_CELLREF:
799 		res->a = expr->cellref.ref;
800 		res->b = expr->cellref.ref;
801 		return FALSE;
802 
803 	case GNM_EXPR_OP_CONSTANT: {
804 		GnmValue const *v = expr->constant.value;
805 		if (VALUE_IS_CELLRANGE (v)) {
806 			*res = v->v_range.cell;
807 			return FALSE;
808 		}
809 		return TRUE;
810 	}
811 
812 	case GNM_EXPR_OP_NAME:
813 		if (!expr_name_is_active (expr->name.name))
814 			return TRUE;
815 		return gnm_expr_extract_ref (res, expr->name.name->texpr->expr,
816 					     pos, flags);
817 	default:
818 		break;
819 	}
820 	return TRUE;
821 }
822 
823 static inline GnmValue *
handle_empty(GnmValue * res,GnmExprEvalFlags flags)824 handle_empty (GnmValue *res, GnmExprEvalFlags flags)
825 {
826 	if (res == NULL)
827 		return (flags & GNM_EXPR_EVAL_PERMIT_EMPTY)
828 		    ? NULL : value_new_int (0);
829 
830 	if (VALUE_IS_EMPTY (res)) {
831 		value_release (res);
832 		return (flags & GNM_EXPR_EVAL_PERMIT_EMPTY)
833 		    ? NULL : value_new_int (0);
834 	}
835 	return res;
836 }
837 
838 /**
839  * value_intersection:
840  * @v: a VALUE_CELLRANGE or VALUE_ARRAY
841  * @pos:
842  *
843  * Handle the implicit union of a single row or column with the eval position.
844  *
845  * NOTE : We do not need to know if this is expression is being evaluated as an
846  * array or not because we can differentiate based on the required type for the
847  * argument.
848  *
849  * Always release the value passed in.
850  *
851  * NOTE: This should match link_unlink_constant.
852  *
853  * Return value:
854  *     If the intersection succeeded return a duplicate of the value
855  *     at the intersection point.  This value needs to be freed.
856  *     %NULL if there is no intersection
857  * Returns the upper left corner of an array.
858  **/
859 static GnmValue *
value_intersection(GnmValue * v,GnmEvalPos const * pos)860 value_intersection (GnmValue *v, GnmEvalPos const *pos)
861 {
862 	GnmValue *res = NULL;
863 	GnmRange r;
864 	Sheet *start_sheet, *end_sheet;
865 	gboolean found = FALSE;
866 
867 	if (VALUE_IS_ARRAY (v)) {
868 		res = (v->v_array.x == 0 || v->v_array.y == 0)
869 			? value_new_error_VALUE (NULL)
870 			: value_dup (v->v_array.vals[0][0]);
871 		value_release (v);
872 		return res;
873 	}
874 
875 	/* inverted ranges */
876 	gnm_rangeref_normalize (&v->v_range.cell, pos, &start_sheet, &end_sheet, &r);
877 	value_release (v);
878 
879 	if (start_sheet == end_sheet || end_sheet == NULL) {
880 		int col = pos->eval.col;
881 		int row = pos->eval.row;
882 
883 		if (pos->dep && !dependent_is_cell (pos->dep)) {
884 			/* See bug #142412.  */
885 			col = r.start.col;
886 			row = r.start.row;
887 			found = TRUE;
888 		} else if (range_is_singleton (&r)) {
889 			// A single cell
890 			col = r.start.col;
891 			row = r.start.row;
892 			found = TRUE;
893 		} else if (r.start.row == r.end.row &&
894 			   r.start.col <= col && col <= r.end.col) {
895 			// A horizontal sliver
896 			row = r.start.row;
897 			found = TRUE;
898 		} else if (r.start.col == r.end.col &&
899 			   r.start.row <= row && row <= r.end.row) {
900 			// A vertical sliver
901 			col = r.start.col;
902 			found = TRUE;
903 		}
904 		if (found) {
905 			GnmCell *cell = sheet_cell_get (
906 				eval_sheet (start_sheet, pos->sheet),
907 				col, row);
908 			if (cell == NULL)
909 				return value_new_empty ();
910 			gnm_cell_eval (cell);
911 			return value_dup (cell->value);
912 		}
913 	}
914 
915 	return value_new_error_VALUE (pos);
916 }
917 
918 static GnmValue *
bin_arith(GnmExpr const * expr,GnmEvalPos const * ep,GnmValue const * a,GnmValue const * b)919 bin_arith (GnmExpr const *expr, GnmEvalPos const *ep,
920 	   GnmValue const *a, GnmValue const *b)
921 {
922 	gnm_float const va = value_get_as_float (a);
923 	gnm_float const vb = value_get_as_float (b);
924 	gnm_float res;
925 
926 	switch (GNM_EXPR_GET_OPER (expr)) {
927 	case GNM_EXPR_OP_ADD:
928 		res = va + vb;
929 		break;
930 
931 	case GNM_EXPR_OP_SUB:
932 		res = va - vb;
933 		break;
934 
935 	case GNM_EXPR_OP_MULT:
936 		res = va * vb;
937 		break;
938 
939 	case GNM_EXPR_OP_DIV:
940 		if (vb == 0.0)
941 			return value_new_error_DIV0 (ep);
942 		res = va / vb;
943 		break;
944 
945 	case GNM_EXPR_OP_EXP:
946 		if ((va == 0 && vb <= 0) || (va < 0 && vb != (int)vb))
947 			return value_new_error_NUM (ep);
948 
949 		res = gnm_pow (va, vb);
950 		break;
951 
952 	default:
953 		g_assert_not_reached ();
954 	}
955 
956 	if (gnm_finite (res))
957 		return value_new_float (res);
958 	else
959 		return value_new_error_NUM (ep);
960 }
961 
962 static GnmValue *
bin_cmp(GnmExprOp op,GnmValDiff comp,GnmEvalPos const * ep)963 bin_cmp (GnmExprOp op, GnmValDiff comp, GnmEvalPos const *ep)
964 {
965 	if (comp == TYPE_MISMATCH) {
966 		/* TODO TODO TODO : Make error more informative
967 		 *    regarding what is comparing to what
968 		 */
969 		/* For equality comparisons even errors are ok */
970 		if (op == GNM_EXPR_OP_EQUAL)
971 			return value_new_bool (FALSE);
972 		if (op == GNM_EXPR_OP_NOT_EQUAL)
973 			return value_new_bool (TRUE);
974 
975 		return value_new_error_VALUE (ep);
976 	}
977 
978 	switch (op) {
979 	case GNM_EXPR_OP_EQUAL:     return value_new_bool (comp == IS_EQUAL);
980 	case GNM_EXPR_OP_GT:	    return value_new_bool (comp == IS_GREATER);
981 	case GNM_EXPR_OP_LT:	    return value_new_bool (comp == IS_LESS);
982 	case GNM_EXPR_OP_NOT_EQUAL: return value_new_bool (comp != IS_EQUAL);
983 	case GNM_EXPR_OP_LTE:	    return value_new_bool (comp != IS_GREATER);
984 	case GNM_EXPR_OP_GTE:	    return value_new_bool (comp != IS_LESS);
985 
986 #ifndef DEBUG_SWITCH_ENUM
987 	default:
988 		g_assert_not_reached ();
989 #endif
990 	}
991 	return value_new_error (ep, _("Internal type error"));
992 }
993 
994 static GnmValue *
cb_bin_cmp(GnmEvalPos const * ep,GnmValue const * a,GnmValue const * b,GnmExpr const * expr)995 cb_bin_cmp (GnmEvalPos const *ep, GnmValue const *a, GnmValue const *b,
996 	    GnmExpr const *expr)
997 {
998 	if (a != NULL && VALUE_IS_ERROR (a))
999 		return value_dup (a);
1000 	if (b != NULL && VALUE_IS_ERROR (b))
1001 		return value_dup (b);
1002 	return bin_cmp (GNM_EXPR_GET_OPER (expr), value_compare (a, b, FALSE), ep);
1003 }
1004 
1005 static GnmValue *
cb_bin_arith(GnmEvalPos const * ep,GnmValue const * a,GnmValue const * b,GnmExpr const * expr)1006 cb_bin_arith (GnmEvalPos const *ep, GnmValue const *a, GnmValue const *b,
1007 	      GnmExpr const *expr)
1008 {
1009 	GnmValue *res, *va, *vb;
1010 
1011 	if (a != NULL && VALUE_IS_ERROR (a))
1012 		return value_dup (a);
1013 	if (b != NULL && VALUE_IS_ERROR (b))
1014 		return value_dup (b);
1015 	if (VALUE_IS_EMPTY (a))
1016 		a = va = (GnmValue *)value_zero;
1017 	else if (VALUE_IS_STRING (a)) {
1018 		va = format_match_number (value_peek_string (a), NULL,
1019 			sheet_date_conv (ep->sheet));
1020 		if (va == NULL)
1021 			return value_new_error_VALUE (ep);
1022 	} else if (!VALUE_IS_NUMBER (a))
1023 		return value_new_error_VALUE (ep);
1024 	else
1025 		va = (GnmValue *)a;
1026 	if (VALUE_IS_EMPTY (b))
1027 		b = vb = (GnmValue *)value_zero;
1028 	else if (VALUE_IS_STRING (b)) {
1029 		vb = format_match_number (value_peek_string (b), NULL,
1030 			sheet_date_conv (ep->sheet));
1031 		if (vb == NULL) {
1032 			if (va != a)
1033 				value_release (va);
1034 			return value_new_error_VALUE (ep);
1035 		}
1036 	} else if (!VALUE_IS_NUMBER (b)) {
1037 		if (va != a)
1038 			value_release (va);
1039 		return value_new_error_VALUE (ep);
1040 	} else
1041 		vb = (GnmValue *)b;
1042 
1043 	res = bin_arith (expr, ep, va, vb);
1044 	if (va != a)
1045 		value_release (va);
1046 	if (vb != b)
1047 		value_release (vb);
1048 	return res;
1049 }
1050 
1051 static GnmValue *
cb_bin_cat(GnmEvalPos const * ep,GnmValue const * a,GnmValue const * b,GnmExpr const * expr)1052 cb_bin_cat (GnmEvalPos const *ep, GnmValue const *a, GnmValue const *b,
1053 	    GnmExpr const *expr)
1054 {
1055 	if (a != NULL && VALUE_IS_ERROR (a))
1056 		return value_dup (a);
1057 	if (b != NULL && VALUE_IS_ERROR (b))
1058 		return value_dup (b);
1059 	if (a == NULL) {
1060 		if (b != NULL)
1061 			return value_new_string (value_peek_string (b));
1062 		else
1063 			return value_new_string ("");
1064 	} else if (b == NULL)
1065 		return value_new_string (value_peek_string (a));
1066 	else {
1067 		char *tmp = g_strconcat (value_peek_string (a),
1068 					 value_peek_string (b), NULL);
1069 		return value_new_string_nocopy (tmp);
1070 	}
1071 }
1072 
1073 typedef GnmValue *(*BinOpImplicitIteratorFunc) (GnmEvalPos const *ep,
1074 						GnmValue const *a,
1075 						GnmValue const *b,
1076 						gpointer user_data);
1077 typedef struct {
1078 	GnmEvalPos const *ep;
1079 	GnmValue *res;
1080 	GnmValue const *a, *b;
1081 	BinOpImplicitIteratorFunc	func;
1082 
1083 	/* multiply by 0 in unused dimensions.
1084 	 * this is simpler than lots of conditions
1085 	 *	state->use_x.a ? x : 0
1086 	 **/
1087 	struct {
1088 		int a, b;
1089 	} x, y;
1090 	gpointer	user_data;
1091 } BinOpImplicitIteratorState;
1092 
1093 static GnmValue *
cb_implicit_iter_a_and_b(GnmValueIter const * v_iter,BinOpImplicitIteratorState const * state)1094 cb_implicit_iter_a_and_b (GnmValueIter const *v_iter,
1095 			  BinOpImplicitIteratorState const *state)
1096 {
1097 	state->res->v_array.vals [v_iter->x][v_iter->y] =
1098 		(*state->func) (v_iter->ep,
1099 			value_area_get_x_y (state->a,
1100 				state->x.a * v_iter->x,
1101 				state->y.a * v_iter->y, v_iter->ep),
1102 			value_area_get_x_y (state->b,
1103 				state->x.b * v_iter->x,
1104 				state->y.b * v_iter->y, v_iter->ep),
1105 			state->user_data);
1106 	return NULL;
1107 }
1108 static GnmValue *
cb_implicit_iter_a_to_scalar_b(GnmValueIter const * v_iter,BinOpImplicitIteratorState const * state)1109 cb_implicit_iter_a_to_scalar_b (GnmValueIter const *v_iter,
1110 				BinOpImplicitIteratorState const *state)
1111 {
1112 	state->res->v_array.vals [v_iter->x][v_iter->y] =
1113 		(*state->func) (v_iter->ep,
1114 			v_iter->v, state->b, state->user_data);
1115 	return NULL;
1116 }
1117 
1118 /* This is only triggered if something returns an array or a range which can
1119  * only happen if we are in array eval mode. */
1120 static GnmValue *
bin_array_iter_a(GnmEvalPos const * ep,GnmValue * a,GnmValue * b,BinOpImplicitIteratorFunc func,GnmExpr const * expr)1121 bin_array_iter_a (GnmEvalPos const *ep,
1122 		  GnmValue *a, GnmValue *b,
1123 		  BinOpImplicitIteratorFunc func,
1124 		  GnmExpr const *expr)
1125 {
1126 	BinOpImplicitIteratorState iter_info;
1127 
1128 	/* a must be a cellrange or array, it cannot be NULL */
1129 	iter_info.ep   = ep;
1130 	iter_info.func = func;
1131 	iter_info.user_data = (gpointer) expr;
1132 	iter_info.a = a;
1133 	iter_info.b = b;
1134 
1135 	/* matrix to matrix
1136 	 * Use matching positions unless the dimension is singular, in which
1137 	 * case use the zero item
1138 	 * res[x][y] = f(a[singular.a.x ? 0 : x, b[singular.b.x ? 0 : x)
1139 	 *
1140 	 * If both items have non-singular sizes for
1141 	 * the same dimension use the min size (see samples/array.xls) */
1142 	if (b != NULL &&
1143 	    (VALUE_IS_CELLRANGE (b) || VALUE_IS_ARRAY (b))) {
1144 		int sa, sb, w = 1, h = 1;
1145 
1146 		sa = value_area_get_width  (a, ep);
1147 		sb = value_area_get_width  (b, ep);
1148 		if ((iter_info.x.a = (sa == 1) ? 0 : 1))
1149 			w = sa;
1150 		if ((iter_info.x.b = (sb == 1) ? 0 : 1) && (w > sb || w == 1))
1151 			w = sb;
1152 
1153 		sa = value_area_get_height  (a, ep);
1154 		sb = value_area_get_height  (b, ep);
1155 		if ((iter_info.y.a = (sa == 1) ? 0 : 1))
1156 			h = sa;
1157 		if ((iter_info.y.b = (sb == 1) ? 0 : 1) && (h > sb || h == 1))
1158 			h = sb;
1159 
1160 		iter_info.res = value_new_array_empty (w, h);
1161 		value_area_foreach (iter_info.res, ep, CELL_ITER_ALL,
1162 			(GnmValueIterFunc) cb_implicit_iter_a_and_b, &iter_info);
1163 	} else {
1164 		iter_info.res = value_new_array_empty (
1165 			value_area_get_width  (a, ep),
1166 			value_area_get_height (a, ep));
1167 		value_area_foreach (a, ep, CELL_ITER_ALL,
1168 			(GnmValueIterFunc) cb_implicit_iter_a_to_scalar_b, &iter_info);
1169 	}
1170 
1171 	value_release (a);
1172 	value_release (b);
1173 	return iter_info.res;
1174 }
1175 
1176 static GnmValue *
cb_implicit_iter_b_to_scalar_a(GnmValueIter const * v_iter,BinOpImplicitIteratorState const * state)1177 cb_implicit_iter_b_to_scalar_a (GnmValueIter const *v_iter,
1178 				BinOpImplicitIteratorState const *state)
1179 {
1180 	state->res->v_array.vals [v_iter->x][v_iter->y] =
1181 		(*state->func) (v_iter->ep,
1182 			state->a, v_iter->v, state->user_data);
1183 	return NULL;
1184 }
1185 static GnmValue *
bin_array_iter_b(GnmEvalPos const * ep,GnmValue * a,GnmValue * b,BinOpImplicitIteratorFunc func,GnmExpr const * expr)1186 bin_array_iter_b (GnmEvalPos const *ep,
1187 		  GnmValue *a, GnmValue *b,
1188 		  BinOpImplicitIteratorFunc func,
1189 		  GnmExpr const *expr)
1190 {
1191 	BinOpImplicitIteratorState iter_info;
1192 
1193 	iter_info.func = func;
1194 	iter_info.user_data = (gpointer) expr;
1195 	iter_info.a = a;
1196 	iter_info.b = b;
1197 
1198 	/* b must be a cellrange or array, it cannot be NULL */
1199 	iter_info.res = value_new_array_empty (
1200 		value_area_get_width  (b, ep),
1201 		value_area_get_height (b, ep));
1202 	value_area_foreach (b, ep, CELL_ITER_ALL,
1203 		(GnmValueIterFunc) cb_implicit_iter_b_to_scalar_a, &iter_info);
1204 	value_release (a);
1205 	value_release (b);
1206 
1207 	return iter_info.res;
1208 }
1209 
1210 static GnmValue *
negate_value(GnmValue const * v)1211 negate_value (GnmValue const *v)
1212 {
1213 	if (VALUE_IS_NUMBER (v)) {
1214 		GnmValue *tmp = value_new_float (0 - value_get_as_float (v));
1215 		value_set_fmt (tmp, VALUE_FMT (v));
1216 		return tmp;
1217 	} else
1218 		return NULL;
1219 }
1220 
1221 static GnmValue *
cb_iter_unary_neg(GnmValueIter const * v_iter,GnmValue * res)1222 cb_iter_unary_neg (GnmValueIter const *v_iter, GnmValue *res)
1223 {
1224 	GnmValue const *v = v_iter->v;
1225 	GnmValue *tmp = NULL;
1226 
1227 	if (VALUE_IS_EMPTY (v))
1228 		tmp = value_new_int (0);
1229 	else if (VALUE_IS_ERROR (v))
1230 		tmp = value_dup (v);
1231 	else if (VALUE_IS_STRING (v)) {
1232 		GnmValue *conv = format_match_number (
1233 			value_peek_string (v), NULL,
1234 			sheet_date_conv (v_iter->ep->sheet));
1235 		if (conv != NULL) {
1236 			tmp = negate_value (conv);
1237 			value_release (conv);
1238 		}
1239 	} else {
1240 		/* BOOL goes here.  */
1241 		tmp = negate_value (v);
1242 	}
1243 
1244 	if (NULL == tmp)
1245 		tmp = value_new_error_VALUE (v_iter->ep);
1246 	res->v_array.vals[v_iter->x][v_iter->y] = tmp;
1247 	return NULL;
1248 }
1249 
1250 static GnmValue *
cb_iter_percentage(GnmValueIter const * v_iter,GnmValue * res)1251 cb_iter_percentage (GnmValueIter const *v_iter, GnmValue *res)
1252 {
1253 	GnmValue const *v = v_iter->v;
1254 	GnmValue *tmp;
1255 
1256 	if (VALUE_IS_EMPTY (v))
1257 		tmp = value_new_int (0);
1258 	else if (VALUE_IS_ERROR (v))
1259 		tmp = value_dup (v);
1260 	else {
1261 		GnmValue *conv = NULL;
1262 		if (VALUE_IS_STRING (v)) {
1263 			conv = format_match_number (
1264 				value_peek_string (v), NULL,
1265 				sheet_date_conv (v_iter->ep->sheet));
1266 			if (conv != NULL)
1267 				v = conv;
1268 		}
1269 
1270 		if (VALUE_IS_NUMBER (v)){
1271 			tmp = value_new_float (value_get_as_float (v) / 100);
1272 			value_set_fmt (tmp, go_format_default_percentage ());
1273 		} else
1274 			tmp = value_new_error_VALUE (v_iter->ep);
1275 
1276 		value_release (conv);
1277 	}
1278 
1279 	res->v_array.vals[v_iter->x][v_iter->y] = tmp;
1280 	return NULL;
1281 }
1282 
1283 static GnmValue *
gnm_expr_range_op(GnmExpr const * expr,GnmEvalPos const * ep,GnmExprEvalFlags flags)1284 gnm_expr_range_op (GnmExpr const *expr, GnmEvalPos const *ep,
1285 		   GnmExprEvalFlags flags)
1286 {
1287 	GnmRangeRef a_ref, b_ref;
1288 	GnmRange a_range, b_range, res_range;
1289 	Sheet *a_start, *a_end, *b_start, *b_end;
1290 	GnmValue *res = NULL;
1291 
1292 	if (gnm_expr_extract_ref (&a_ref, expr->binary.value_a, ep, flags) ||
1293 	    gnm_expr_extract_ref (&b_ref, expr->binary.value_b, ep, flags))
1294 		return value_new_error_REF (ep);
1295 
1296 	gnm_rangeref_normalize (&a_ref, ep, &a_start, &a_end, &a_range);
1297 	gnm_rangeref_normalize (&b_ref, ep, &b_start, &b_end, &b_range);
1298 
1299 	switch (GNM_EXPR_GET_OPER (expr)) {
1300 	case GNM_EXPR_OP_RANGE_CTOR:
1301 		res_range = range_union (&a_range, &b_range);
1302 		/* b_range might be on a bigger sheet.  */
1303 		range_ensure_sanity (&res_range, a_start);
1304 		break;
1305 	case GNM_EXPR_OP_INTERSECT:
1306 		/* 3D references not allowed.  */
1307 		if (a_start != a_end || b_start != b_end)
1308 			return value_new_error_VALUE (ep);
1309 
1310 		/* Must be same sheet.  */
1311 		if (a_start != b_start)
1312 			return value_new_error_VALUE (ep);
1313 
1314 		if (!range_intersection  (&res_range, &a_range, &b_range))
1315 			return value_new_error_NULL (ep);
1316 		break;
1317 	default:
1318 		g_assert_not_reached ();
1319 		return NULL;
1320 	}
1321 
1322 	res = value_new_cellrange_r (a_start, &res_range);
1323 	dependent_add_dynamic_dep (ep->dep, &res->v_range.cell);
1324 	if (!(flags & GNM_EXPR_EVAL_PERMIT_NON_SCALAR)) {
1325 		res = value_intersection (res, ep);
1326 		return (res != NULL)
1327 			? handle_empty (res, flags)
1328 			: value_new_error_VALUE (ep);
1329 	}
1330 	return res;
1331 }
1332 
1333 /**
1334  * gnm_expr_eval:
1335  * @expr: #GnmExpr
1336  * @pos: evaluation position
1337  * @flags: #GnmExprEvalFlags
1338  *
1339  * Evaluatates the given expression.  If GNM_EXPR_EVAL_PERMIT_EMPTY is not set
1340  * then return zero if the expression instead of the empty value, or the value
1341  * of an unused cell.
1342  *
1343  * Returns: (transfer full): result.
1344  **/
1345 GnmValue *
gnm_expr_eval(GnmExpr const * expr,GnmEvalPos const * pos,GnmExprEvalFlags flags)1346 gnm_expr_eval (GnmExpr const *expr, GnmEvalPos const *pos,
1347 	       GnmExprEvalFlags flags)
1348 {
1349 	GnmValue *res = NULL, *a = NULL, *b = NULL;
1350 
1351 	g_return_val_if_fail (expr != NULL, handle_empty (NULL, flags));
1352 	g_return_val_if_fail (pos != NULL, handle_empty (NULL, flags));
1353 
1354  retry:
1355 	switch (GNM_EXPR_GET_OPER (expr)){
1356 	case GNM_EXPR_OP_EQUAL:
1357 	case GNM_EXPR_OP_NOT_EQUAL:
1358 	case GNM_EXPR_OP_GT:
1359 	case GNM_EXPR_OP_GTE:
1360 	case GNM_EXPR_OP_LT:
1361 	case GNM_EXPR_OP_LTE:
1362 		flags |= GNM_EXPR_EVAL_PERMIT_EMPTY;
1363 		flags &= ~GNM_EXPR_EVAL_WANT_REF;
1364 
1365 		a = gnm_expr_eval (expr->binary.value_a, pos, flags);
1366 		if (a != NULL) {
1367 			if (VALUE_IS_ERROR (a))
1368 				return a;
1369 			if (VALUE_IS_CELLRANGE (a) || VALUE_IS_ARRAY (a))
1370 				return bin_array_iter_a (pos, a,
1371 					gnm_expr_eval (expr->binary.value_b, pos, flags),
1372 					(BinOpImplicitIteratorFunc) cb_bin_cmp,
1373 					expr);
1374 		}
1375 
1376 		b = gnm_expr_eval (expr->binary.value_b, pos, flags);
1377 		if (b != NULL) {
1378 			if (VALUE_IS_ERROR (b)) {
1379 				value_release (a);
1380 				return b;
1381 			}
1382 			if (VALUE_IS_CELLRANGE (b) || VALUE_IS_ARRAY (b))
1383 				return bin_array_iter_b (pos, a, b,
1384 					(BinOpImplicitIteratorFunc) cb_bin_cmp,
1385 					expr);
1386 		}
1387 
1388 		res = bin_cmp (GNM_EXPR_GET_OPER (expr), value_compare (a, b, FALSE), pos);
1389 		value_release (a);
1390 		value_release (b);
1391 		return res;
1392 
1393 	case GNM_EXPR_OP_ADD:
1394 	case GNM_EXPR_OP_SUB:
1395 	case GNM_EXPR_OP_MULT:
1396 	case GNM_EXPR_OP_DIV:
1397 	case GNM_EXPR_OP_EXP:
1398 		/*
1399 		 * Priority
1400 		 * 1) Error from A
1401 		 * 2) #!VALUE error if A is not a number
1402 		 * 3) Error from B
1403 		 * 4) #!VALUE error if B is not a number
1404 		 * 5) result of operation, or error specific to the operation
1405 		 */
1406 
1407 		/* Guarantees value != NULL */
1408 		flags &= ~GNM_EXPR_EVAL_PERMIT_EMPTY;
1409 		flags &= ~GNM_EXPR_EVAL_WANT_REF;
1410 
1411 		/* 1) Error from A */
1412 		a = gnm_expr_eval (expr->binary.value_a, pos, flags);
1413 		if (VALUE_IS_ERROR (a))
1414 			return value_error_set_pos (&a->v_err, pos);
1415 
1416 		/* 2) #!VALUE error if A is not a number */
1417 		if (VALUE_IS_STRING (a)) {
1418 			GnmValue *tmp = format_match_number (value_peek_string (a), NULL,
1419 				sheet_date_conv (pos->sheet));
1420 
1421 			value_release (a);
1422 			if (tmp == NULL)
1423 				return value_new_error_VALUE (pos);
1424 			a = tmp;
1425 		} else if (VALUE_IS_CELLRANGE (a) || VALUE_IS_ARRAY (a)) {
1426 			b = gnm_expr_eval (expr->binary.value_b, pos, flags);
1427 			if (VALUE_IS_STRING (b)) {
1428 				res = format_match_number (value_peek_string (b), NULL,
1429 					sheet_date_conv (pos->sheet));
1430 				value_release (b);
1431 				b = (res == NULL) ? value_new_error_VALUE (pos) : res;
1432 			}
1433 			return bin_array_iter_a (pos, a, b,
1434 				(BinOpImplicitIteratorFunc) cb_bin_arith,
1435 				expr);
1436 		} else if (!VALUE_IS_NUMBER (a)) {
1437 			value_release (a);
1438 			return value_new_error_VALUE (pos);
1439 		}
1440 
1441 		/* 3) Error from B */
1442 		b = gnm_expr_eval (expr->binary.value_b, pos, flags);
1443 		if (VALUE_IS_ERROR (b)) {
1444 			value_release (a);
1445 			return value_error_set_pos (&b->v_err, pos);
1446 		}
1447 
1448 		/* 4) #!VALUE error if B is not a number */
1449 		if (VALUE_IS_STRING (b)) {
1450 			GnmValue *tmp = format_match_number (value_peek_string (b), NULL,
1451 				sheet_date_conv (pos->sheet));
1452 
1453 			value_release (b);
1454 			if (tmp == NULL) {
1455 				value_release (a);
1456 				return value_new_error_VALUE (pos);
1457 			}
1458 			b = tmp;
1459 		} else if (VALUE_IS_CELLRANGE (b) || VALUE_IS_ARRAY (b))
1460 			return bin_array_iter_b (pos, a, b,
1461 				(BinOpImplicitIteratorFunc) cb_bin_arith,
1462 				expr);
1463 		else if (!VALUE_IS_NUMBER (b)) {
1464 			value_release (a);
1465 			value_release (b);
1466 			return value_new_error_VALUE (pos);
1467 		}
1468 
1469 		res = bin_arith (expr, pos, a, b);
1470 		value_release (a);
1471 		value_release (b);
1472 		return res;
1473 
1474 	case GNM_EXPR_OP_PAREN:
1475 		/* Avoid recursive call to save stack.  */
1476 		expr = expr->unary.value;
1477 		goto retry;
1478 
1479 	case GNM_EXPR_OP_PERCENTAGE:
1480 	case GNM_EXPR_OP_UNARY_NEG:
1481 	case GNM_EXPR_OP_UNARY_PLUS:
1482 		/* Guarantees value != NULL */
1483 		flags &= ~GNM_EXPR_EVAL_PERMIT_EMPTY;
1484 		flags &= ~GNM_EXPR_EVAL_WANT_REF;
1485 
1486 		a = gnm_expr_eval (expr->unary.value, pos, flags);
1487 		if (VALUE_IS_ERROR (a))
1488 			return a;
1489 		if (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_UNARY_PLUS)
1490 			return a;
1491 
1492 		/* 2) #!VALUE error if A is not a number */
1493 		if (VALUE_IS_STRING (a)) {
1494 			GnmValue *tmp = format_match_number (value_peek_string (a), NULL,
1495 				sheet_date_conv (pos->sheet));
1496 
1497 			value_release (a);
1498 			if (tmp == NULL)
1499 				return value_new_error_VALUE (pos);
1500 			a = tmp;
1501 		} else if (VALUE_IS_CELLRANGE (a) || VALUE_IS_ARRAY (a)) {
1502 			res = value_new_array_empty (
1503 				value_area_get_width  (a, pos),
1504 				value_area_get_height (a, pos));
1505 			value_area_foreach (a, pos, CELL_ITER_ALL,
1506 				(GnmValueIterFunc) ((GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_UNARY_NEG)
1507 					? cb_iter_unary_neg : cb_iter_percentage),
1508 				res);
1509 			value_release (a);
1510 			return res;
1511 		}
1512 		if (!VALUE_IS_NUMBER (a))
1513 			res = value_new_error_VALUE (pos);
1514 		else if (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_UNARY_NEG)
1515 			res = negate_value (a);
1516 		else {
1517 			res = value_new_float (value_get_as_float (a) / 100);
1518 			value_set_fmt (res, go_format_default_percentage ());
1519 		}
1520 		value_release (a);
1521 		return res;
1522 
1523 	case GNM_EXPR_OP_CAT:
1524 		flags |= GNM_EXPR_EVAL_PERMIT_EMPTY;
1525 		flags &= ~GNM_EXPR_EVAL_WANT_REF;
1526 		a = gnm_expr_eval (expr->binary.value_a, pos, flags);
1527 		if (a != NULL) {
1528 			if (VALUE_IS_ERROR (a))
1529 				return a;
1530 			if (VALUE_IS_CELLRANGE (a) || VALUE_IS_ARRAY (a))
1531 				return bin_array_iter_a (pos, a,
1532 					gnm_expr_eval (expr->binary.value_b, pos, flags),
1533 					(BinOpImplicitIteratorFunc) cb_bin_cat,
1534 					expr);
1535 		}
1536 		b = gnm_expr_eval (expr->binary.value_b, pos, flags);
1537 		if (b != NULL) {
1538 			if (VALUE_IS_ERROR (b)) {
1539 				value_release (a);
1540 				return b;
1541 			}
1542 			if (VALUE_IS_CELLRANGE (b) || VALUE_IS_ARRAY (b))
1543 				return bin_array_iter_b (pos, a, b,
1544 					(BinOpImplicitIteratorFunc) cb_bin_cat,
1545 					expr);
1546 		}
1547 
1548 		if (a == NULL) {
1549 			if (b != NULL) {
1550 				res = value_new_string (value_peek_string (b));
1551 				value_release (b);
1552 			} else
1553 				res = value_new_string ("");
1554 		} else if (b == NULL) {
1555 			res = value_new_string (value_peek_string (a));
1556 			value_release (a);
1557 		} else {
1558 			char *tmp = g_strconcat (value_peek_string (a),
1559 						 value_peek_string (b), NULL);
1560 			res = value_new_string_nocopy (tmp);
1561 			value_release (a);
1562 			value_release (b);
1563 		}
1564 		return res;
1565 
1566 	case GNM_EXPR_OP_FUNCALL: {
1567 		GnmFuncEvalInfo ei;
1568 		ei.pos = pos;
1569 		ei.func_call = &expr->func;
1570 		ei.flags = flags;
1571 		res = function_call_with_exprs (&ei);
1572 		if (res == NULL)
1573 			return (flags & GNM_EXPR_EVAL_PERMIT_EMPTY)
1574 			    ? NULL : value_new_int (0);
1575 		if (VALUE_IS_CELLRANGE (res)) {
1576 			/*
1577 			 * pos->dep really shouldn't be NULL here, but it
1578 			 * will be if someone puts "indirect" into an
1579 			 * expression used for conditional formats.
1580 			 */
1581 			if (pos->dep)
1582 				dependent_add_dynamic_dep (pos->dep,
1583 							   &res->v_range.cell);
1584 			if (!(flags & GNM_EXPR_EVAL_PERMIT_NON_SCALAR)) {
1585 				res = value_intersection (res, pos);
1586 				return (res != NULL)
1587 					? handle_empty (res, flags)
1588 					: value_new_error_VALUE (pos);
1589 			}
1590 			return res;
1591 		}
1592 		if (VALUE_IS_ARRAY (res) &&
1593 		    !(flags & GNM_EXPR_EVAL_PERMIT_NON_SCALAR)) {
1594 			a = (res->v_array.x > 0 && res->v_array.y > 0)
1595 				? value_dup (res->v_array.vals[0][0])
1596 				: value_new_error_REF (pos);
1597 			value_release (res);
1598 			return a;
1599 		}
1600 		return res;
1601 	}
1602 
1603 	case GNM_EXPR_OP_NAME:
1604 		if (expr_name_is_active (expr->name.name))
1605 			return handle_empty (expr_name_eval (expr->name.name, pos, flags), flags);
1606 		return value_new_error_REF (pos);
1607 
1608 	case GNM_EXPR_OP_CELLREF: {
1609 		GnmCell *cell;
1610 		GnmCellRef r;
1611 
1612 		gnm_cellref_make_abs (&r, &expr->cellref.ref, pos);
1613 
1614 		cell = sheet_cell_get (eval_sheet (r.sheet, pos->sheet),
1615 				       r.col, r.row);
1616 		if (cell)
1617 			gnm_cell_eval (cell);
1618 
1619 		if (flags & GNM_EXPR_EVAL_WANT_REF) {
1620 			return value_new_cellrange_unsafe (&r, &r);
1621 		} else {
1622 			GnmValue *v = cell ? value_dup (cell->value) : NULL;
1623 			return handle_empty (v, flags);
1624 		}
1625 	}
1626 
1627 	case GNM_EXPR_OP_CONSTANT:
1628 		res = value_dup (expr->constant.value);
1629 		if (VALUE_IS_CELLRANGE (res) || VALUE_IS_ARRAY (res)) {
1630 			if (flags & GNM_EXPR_EVAL_PERMIT_NON_SCALAR)
1631 				return res;
1632 			res = value_intersection (res, pos);
1633 			return (res != NULL)
1634 				? handle_empty (res, flags)
1635 				: value_new_error_VALUE (pos);
1636 		}
1637 		return handle_empty (res, flags);
1638 
1639 	case GNM_EXPR_OP_ARRAY_CORNER:
1640 	case GNM_EXPR_OP_ARRAY_ELEM:
1641 		g_warning ("Unexpected array expressions encountered");
1642 		return value_new_error_VALUE (pos);
1643 
1644 	case GNM_EXPR_OP_SET:
1645 		if (flags & GNM_EXPR_EVAL_PERMIT_NON_SCALAR) {
1646 			int i;
1647 			int argc = expr->set.argc;
1648 
1649 			res = value_new_array_non_init (1, expr->set.argc);
1650 			res->v_array.vals[0] = g_new (GnmValue *, expr->set.argc);
1651 			for (i = 0; i < argc; i++)
1652 				res->v_array.vals[0][i] = gnm_expr_eval (
1653 					expr->set.argv[i], pos,
1654 					GNM_EXPR_EVAL_SCALAR_NON_EMPTY);
1655 			return res;
1656 		}
1657 		return value_new_error_VALUE (pos);
1658 
1659 	case GNM_EXPR_OP_RANGE_CTOR:
1660 	case GNM_EXPR_OP_INTERSECT:
1661 		return gnm_expr_range_op (expr, pos, flags);
1662 	}
1663 
1664 	g_assert_not_reached ();
1665 	return value_new_error (pos, _("Unknown evaluation error"));
1666 }
1667 
1668 /**
1669  * gnm_expr_simplify_if:
1670  * @expr: Expression
1671  *
1672  * Simplifies @expr if it is a call to "if" with a constant condition.
1673  *
1674  * Returns: (transfer full) (nullable): simpler expression.
1675  */
1676 GnmExpr const *
gnm_expr_simplify_if(GnmExpr const * expr)1677 gnm_expr_simplify_if (GnmExpr const *expr)
1678 {
1679 	static GnmFunc *f_if = NULL;
1680 	GnmExpr const *cond;
1681 	gboolean c;
1682 
1683 	g_return_val_if_fail (expr != NULL, NULL);
1684 
1685 	if (GNM_EXPR_GET_OPER (expr) != GNM_EXPR_OP_FUNCALL)
1686 		return NULL;
1687 
1688 	if (!f_if)
1689 		f_if = gnm_func_lookup ("if", NULL);
1690 
1691 	if (expr->func.func != f_if || expr->func.argc != 3)
1692 		return NULL;
1693 
1694 	cond = expr->func.argv[0];
1695 	if (GNM_EXPR_GET_OPER (cond) == GNM_EXPR_OP_CONSTANT) {
1696 		GnmValue const *condval = cond->constant.value;
1697 		gboolean err;
1698 		c = value_get_as_bool (condval, &err);
1699 		if (err)
1700 			return NULL;
1701 	} else
1702 		return NULL;
1703 
1704 	// We used to test for true() and false() as conditions too, but the code
1705 	// never worked and has been unreachable until now.
1706 
1707 	return gnm_expr_copy (expr->func.argv[c ? 1 : 2]);
1708 }
1709 
1710 
1711 
1712 /*
1713  * Converts a parsed tree into its string representation
1714  * assuming that we are evaluating at col, row
1715  *
1716  * This routine is pretty simple: it walks the GnmExpr and
1717  * appends a string representation to the target.
1718  */
1719 static void
do_expr_as_string(GnmExpr const * expr,int paren_level,GnmConventionsOut * out)1720 do_expr_as_string (GnmExpr const *expr, int paren_level,
1721 		   GnmConventionsOut *out)
1722 {
1723 	static struct {
1724 		char const name[4];
1725 		guint8 prec;			 /* Precedences -- should match parser.y  */
1726 		guint8 assoc_left, assoc_right;  /* 0: no, 1: yes.  */
1727 		guint8 is_prefix;                /* for unary operators */
1728 	} const operations[] = {
1729 		{ "",   0, 0, 0, 0 }, /* Parentheses for clarity */
1730 		{ "=",  1, 1, 0, 0 },
1731 		{ ">",  1, 1, 0, 0 },
1732 		{ "<",  1, 1, 0, 0 },
1733 		{ ">=", 1, 1, 0, 0 },
1734 		{ "<=", 1, 1, 0, 0 },
1735 		{ "<>", 1, 1, 0, 0 },
1736 		{ "+",  3, 1, 0, 0 },
1737 		{ "-",  3, 1, 0, 0 },
1738 		{ "*",  4, 1, 0, 0 },
1739 		{ "/",  4, 1, 0, 0 },
1740 		{ "^",  5, 0, 0, 0 }, /* Note: neither left nor right */
1741 		{ "&",  2, 1, 0, 0 },
1742 		{ "",   0, 0, 0, 0 }, /* Funcall  */
1743 		{ "",   0, 0, 0, 0 }, /* Name     */
1744 		{ "",   0, 0, 0, 0 }, /* Constant */
1745 		{ "",   0, 0, 0, 0 }, /* Var      */
1746 		{ "-",  7, 0, 0, 1 }, /* Unary -  */
1747 		{ "+",  7, 0, 0, 1 }, /* Unary +  */
1748 		{ "%",  6, 0, 0, 0 }, /* Percentage (NOT MODULO) */
1749 		{ "",   0, 0, 0, 0 }, /* ArrayCorner    */
1750 		{ "",   0, 0, 0, 0 }, /* ArrayElem */
1751 		{ "",   8, 0, 0, 0 }, /* Set       */
1752 		{ ":", 10, 1, 0, 0 }, /* Range Ctor   */
1753 		{ " ",  9, 1, 0, 0 }  /* Intersection */
1754 	};
1755 	GnmExprOp const op = GNM_EXPR_GET_OPER (expr);
1756 	GString *target = out->accum;
1757 
1758 	switch (op) {
1759 	case GNM_EXPR_OP_RANGE_CTOR:
1760 	case GNM_EXPR_OP_INTERSECT:
1761 	case GNM_EXPR_OP_ANY_BINARY: {
1762 		char const *opname = operations[op].name;
1763 		int prec = operations[op].prec;
1764 		gboolean need_par = (prec <= paren_level);
1765 		size_t prelen = target->len;
1766 
1767 		if (need_par) g_string_append_c (target, '(');
1768 		do_expr_as_string (expr->binary.value_a,
1769 			prec - operations[op].assoc_left, out);
1770 
1771 		/*
1772 		 * Avoid getting "-2^2".  We want to make sure files do not
1773 		 * contain that construct as we might later change precedence.
1774 		 *
1775 		 * Always produce either "-(2^2)" or "(-2)^2".
1776 		 *
1777 		 * Note, that the parser introduces an explicit parenthesis in
1778 		 * this case also, so parsed expressions should not be
1779 		 * affected by the code here.
1780 		 */
1781 		if (op == GNM_EXPR_OP_EXP &&
1782 		    (target->str[prelen] == '-' || target->str[prelen] == '+')) {
1783 			g_string_insert_c (target, prelen, '(');
1784 			g_string_append_c (target, ')');
1785 		}
1786 
1787 		/* Instead of this we ought to move the whole operations
1788 		   table into the conventions.  */
1789 		if (op == GNM_EXPR_OP_INTERSECT)
1790 			g_string_append_unichar (target, out->convs->intersection_char);
1791 		else
1792 			g_string_append (target, opname);
1793 
1794 		do_expr_as_string (expr->binary.value_b,
1795 			prec - operations[op].assoc_right, out);
1796 		if (need_par) g_string_append_c (target, ')');
1797 		return;
1798 	}
1799 
1800 	case GNM_EXPR_OP_ANY_UNARY: {
1801 		char const *opname = operations[op].name;
1802 		int prec = operations[op].prec;
1803 		gboolean is_prefix = operations[op].is_prefix;
1804 		gboolean need_par = (prec <= paren_level);
1805 
1806 		if (need_par) g_string_append_c (target, '(');
1807 		if (is_prefix) g_string_append (target, opname);
1808 		do_expr_as_string (expr->unary.value, prec, out);
1809 		if (!is_prefix) g_string_append (target, opname);
1810 		if (need_par) g_string_append_c (target, ')');
1811 		return;
1812 	}
1813 
1814 	case GNM_EXPR_OP_FUNCALL:
1815 		out->convs->output.func (out, &expr->func);
1816 		return;
1817 
1818 	case GNM_EXPR_OP_NAME:
1819 		out->convs->output.name (out, &expr->name);
1820 		return;
1821 
1822 	case GNM_EXPR_OP_CELLREF:
1823 		out->convs->output.cell_ref (out, &expr->cellref.ref, FALSE);
1824 		return;
1825 
1826 	case GNM_EXPR_OP_CONSTANT: {
1827 		GnmValue const *v = expr->constant.value;
1828 		size_t prelen = target->len;
1829 
1830 		if (VALUE_IS_STRING (v)) {
1831 			out->convs->output.string (out, v->v_str.val);
1832 			return;
1833 		}
1834 
1835 		if (VALUE_IS_CELLRANGE (v)) {
1836 			out->convs->output.range_ref (out, &v->v_range.cell);
1837 			return;
1838 		}
1839 
1840 		if (VALUE_IS_BOOLEAN (v) &&
1841 		    out->convs->output.boolean != NULL) {
1842 			out->convs->output.boolean (out, v->v_bool.val);
1843 			return;
1844 		}
1845 
1846 
1847 		value_get_as_gstring (v, target, out->convs);
1848 
1849 		/* If the number has a sign, pretend that it is the result of
1850 		 * OPER_UNARY_{NEG,PLUS}.
1851 		 */
1852 		if ((target->str[prelen] == '-' || target->str[prelen] == '+') &&
1853 		    operations[GNM_EXPR_OP_UNARY_NEG].prec <= paren_level) {
1854 			g_string_insert_c (target, prelen, '(');
1855 			g_string_append_c (target, ')');
1856 		}
1857 		return;
1858 	}
1859 
1860 	case GNM_EXPR_OP_ARRAY_CORNER:
1861 		do_expr_as_string (expr->array_corner.expr, 0, out);
1862 		return;
1863 
1864 	case GNM_EXPR_OP_ARRAY_ELEM: {
1865 		GnmCell const *corner = array_elem_get_corner (&expr->array_elem,
1866 			out->pp->sheet, &out->pp->eval);
1867 		if (NULL != corner) {
1868 			GnmParsePos const *real_pp = out->pp;
1869 			GnmParsePos  pp = *real_pp;
1870 
1871 			pp.eval.col -= expr->array_elem.x;
1872 			pp.eval.row -= expr->array_elem.y;
1873 			out->pp = &pp;
1874 			do_expr_as_string (
1875 				corner->base.texpr->expr->array_corner.expr,
1876 				0, out);
1877 			out->pp = real_pp;
1878 			return;
1879 		}
1880 		break;
1881 	}
1882 
1883 	case GNM_EXPR_OP_SET:
1884 		gnm_expr_list_as_string (expr->set.argc, expr->set.argv, out);
1885 		return;
1886 	}
1887 
1888 	g_string_append (target, "<ERROR>");
1889 }
1890 
1891 /**
1892  * gnm_expr_as_gstring:
1893  * @expr: #GnmExpr
1894  * @out: output conventions
1895  *
1896  * Renders the expression as a string according to @out and places the
1897  * result in @out's accumulator.
1898  */
1899 void
gnm_expr_as_gstring(GnmExpr const * expr,GnmConventionsOut * out)1900 gnm_expr_as_gstring (GnmExpr const *expr, GnmConventionsOut *out)
1901 {
1902 	g_return_if_fail (expr != NULL);
1903 	g_return_if_fail (out  != NULL);
1904 
1905 	do_expr_as_string (expr, 0, out);
1906 }
1907 
1908 /**
1909  * gnm_expr_as_string:
1910  * @expr: #GnmExpr
1911  * @pp: (nullable): Parse position.  %NULL should be used for debugging only.
1912  * @convs: (nullable): #GnmConventions.  %NULL should be used for debugging
1913  * or when @pp identifies a #Sheet.
1914  *
1915  * Renders the expression as a string according to @convs.
1916  *
1917  * Returns: (transfer full): @expr as a string.
1918  */
1919 char *
gnm_expr_as_string(GnmExpr const * expr,GnmParsePos const * pp,GnmConventions const * convs)1920 gnm_expr_as_string (GnmExpr const *expr, GnmParsePos const *pp,
1921 		    GnmConventions const *convs)
1922 {
1923 	GnmConventionsOut out;
1924 	GnmParsePos pp0;
1925 
1926 	g_return_val_if_fail (expr != NULL, NULL);
1927 
1928 	/*
1929 	 * Defaults for debugging only!
1930 	 */
1931 	if (!pp) {
1932 		/* UGH: Just get the first sheet in the first workbook! */
1933 		Workbook *wb = gnm_app_workbook_get_by_index (0);
1934 		Sheet *sheet = workbook_sheet_by_index (wb, 0);
1935 		parse_pos_init (&pp0, NULL, sheet, 0, 0);
1936 		pp = &pp0;
1937 	}
1938 	if (!convs)
1939 		convs = pp->sheet
1940 			? sheet_get_conventions (pp->sheet)
1941 			: gnm_conventions_default;
1942 
1943 	out.accum = g_string_new (NULL);
1944 	out.pp    = pp;
1945 	out.convs = convs;
1946 	do_expr_as_string (expr, 0, &out);
1947 	return g_string_free (out.accum, FALSE);
1948 }
1949 
1950 /****************************************************************************/
1951 
1952 static gboolean
gnm_expr_is_err(GnmExpr const * expr,GnmStdError err)1953 gnm_expr_is_err (GnmExpr const *expr, GnmStdError err)
1954 {
1955 	GnmStdError err2;
1956 
1957 	if (GNM_EXPR_GET_OPER (expr) != GNM_EXPR_OP_CONSTANT)
1958 		return FALSE;
1959 
1960 	err2 = value_error_classify (expr->constant.value);
1961 	return err == err2;
1962 }
1963 
1964 /**
1965  * gnm_expr_get_constant:
1966  * @expr: #GnmExpr
1967  *
1968  * Returns: (transfer none) (nullable): If this expression consists of just
1969  * a constant, return it.  Otherwise, %NULL.
1970  */
1971 GnmValue const *
gnm_expr_get_constant(GnmExpr const * expr)1972 gnm_expr_get_constant (GnmExpr const *expr)
1973 {
1974 	if (GNM_EXPR_GET_OPER (expr) != GNM_EXPR_OP_CONSTANT)
1975 		return NULL;
1976 
1977 	return expr->constant.value;
1978 }
1979 
1980 /**
1981  * gnm_expr_get_name:
1982  * @expr: #GnmExpr
1983  *
1984  * Returns: (transfer none) (nullable): If this expression consists of just
1985  * a name, return it.  Otherwise, %NULL.
1986  */
1987 GnmNamedExpr const *
gnm_expr_get_name(GnmExpr const * expr)1988 gnm_expr_get_name (GnmExpr const *expr)
1989 {
1990 	if (GNM_EXPR_GET_OPER (expr) != GNM_EXPR_OP_NAME)
1991 		return NULL;
1992 
1993 	return expr->name.name;
1994 }
1995 
1996 
1997 /**
1998  * gnm_expr_get_cellref:
1999  * @expr: #GnmExpr
2000  *
2001  * Returns: (transfer none) (nullable): If this expression consists of just
2002  * a cell reference, return it.  Otherwise, %NULL.
2003  */
2004 GnmCellRef const *
gnm_expr_get_cellref(GnmExpr const * expr)2005 gnm_expr_get_cellref (GnmExpr const *expr)
2006 {
2007 	if (GNM_EXPR_GET_OPER (expr) != GNM_EXPR_OP_CELLREF)
2008 		return NULL;
2009 
2010 	return &expr->cellref.ref;
2011 }
2012 
2013 
2014 typedef struct {
2015 	GnmExprRelocateInfo const *details;
2016 	gboolean from_inside;
2017 	gboolean check_rels;
2018 } RelocInfoInternal;
2019 
2020 static GnmExpr const *
invalidate_sheet_cellrange(RelocInfoInternal const * rinfo,GnmValueRange const * v)2021 invalidate_sheet_cellrange (RelocInfoInternal const *rinfo,
2022 			    GnmValueRange const *v)
2023 {
2024 	GnmCellRef ref_a = v->cell.a;
2025 	GnmCellRef ref_b = v->cell.b;
2026 
2027 	Sheet const *sheet_a = ref_a.sheet;
2028 	Sheet const *sheet_b = ref_b.sheet;
2029 	Workbook *wb;
2030 	gboolean hit_a = sheet_a && sheet_a->being_invalidated;
2031 	gboolean hit_b = sheet_b && sheet_b->being_invalidated;
2032 	int dir;
2033 
2034 	if (!hit_a && !hit_b)
2035 		return NULL;
2036 
2037 	if (sheet_a == NULL || sheet_b == NULL ||
2038 	    sheet_a->workbook != sheet_b->workbook)
2039 		/* A 3D reference between workbooks?  */
2040 		return gnm_expr_new_constant (value_new_error_REF (NULL));
2041 
2042 	/* Narrow the sheet range.  */
2043 	wb = sheet_a->workbook;
2044 	dir = (sheet_a->index_in_wb < sheet_b->index_in_wb) ? +1 : -1;
2045 	while (sheet_a != sheet_b && sheet_a->being_invalidated)
2046 		sheet_a = workbook_sheet_by_index (wb, sheet_a->index_in_wb + dir);
2047 	while (sheet_a != sheet_b && sheet_b->being_invalidated)
2048 		sheet_b = workbook_sheet_by_index (wb, sheet_b->index_in_wb - dir);
2049 
2050 	if (sheet_a->being_invalidated)
2051 		return gnm_expr_new_constant (value_new_error_REF (NULL));
2052 
2053 	ref_a.sheet = (Sheet *)sheet_a;
2054 	ref_b.sheet = (Sheet *)sheet_b;
2055 	return gnm_expr_new_constant (value_new_cellrange_unsafe (&ref_a, &ref_b));
2056 }
2057 
2058 static gboolean
reloc_range(GnmExprRelocateInfo const * rinfo,Sheet const * start_sheet,Sheet const * end_sheet,GnmRange * rng)2059 reloc_range (GnmExprRelocateInfo const *rinfo,
2060 	     Sheet const *start_sheet, Sheet const *end_sheet,
2061 	     GnmRange *rng)
2062 {
2063 	GnmRange t, b, l, r;
2064 	gboolean start, end;
2065 
2066 	if (start_sheet != end_sheet ||		/* ignore 3d refs */
2067 	    start_sheet != rinfo->origin_sheet)	/* ref is to a different sheet */
2068 		return FALSE;
2069 
2070 	t.start.col = b.start.col = l.start.col = l.end.col   = rng->start.col;
2071 	t.end.col   = b.end.col   = r.start.col = r.end.col   = rng->end.col;
2072 	t.start.row = t.end.row   = l.start.row = r.start.row = rng->start.row;
2073 	b.start.row = b.end.row   = l.end.row   = r.end.row   = rng->end.row;
2074 
2075 	start = range_contained (&t, &rinfo->origin);
2076 	end   = range_contained (&b, &rinfo->origin);
2077 	if (start && end) { /* full enclosure */
2078 		rng->start.col += rinfo->col_offset;
2079 		rng->end.col   += rinfo->col_offset;
2080 		rng->start.row += rinfo->row_offset;
2081 		rng->end.row   += rinfo->row_offset;
2082 		return TRUE;
2083 	}
2084 
2085 	if (rinfo->col_offset == 0) {
2086 		if (start && rinfo->row_offset < range_height (rng)) {
2087 			rng->start.row += rinfo->row_offset;
2088 			return TRUE;
2089 		}
2090 		if (end && rinfo->row_offset > -range_height (rng)) {
2091 			/* Special case invalidating the bottom of a range while
2092 			 * deleting rows. Otherwise we #REF! before  we can shorten
2093 			 * The -1 is safe, origin.start.row == 0 is handled above */
2094 			if (rinfo->reloc_type == GNM_EXPR_RELOCATE_ROWS &&
2095 			    rinfo->row_offset >= gnm_sheet_get_max_rows (end_sheet))
2096 				rng->end.row  = rinfo->origin.start.row - 1;
2097 			else
2098 				rng->end.row += rinfo->row_offset;
2099 			return TRUE;
2100 		}
2101 	}
2102 
2103 	if (rinfo->row_offset == 0) {
2104 		if (range_contained (&l, &rinfo->origin) &&
2105 		    rinfo->col_offset < range_width (rng)) {
2106 			rng->start.col += rinfo->col_offset;
2107 			return TRUE;
2108 		}
2109 		if (range_contained (&r, &rinfo->origin) &&
2110 		    rinfo->col_offset > -range_width (rng)) {
2111 			/* Special case invalidating the right side of a range while
2112 			 * deleting cols. Otherwise we #REF! before  we can shorten.
2113 			 * The -1 is safe, origin.start.col == 0 is handled above */
2114 			if (rinfo->reloc_type == GNM_EXPR_RELOCATE_COLS &&
2115 			    rinfo->col_offset >= gnm_sheet_get_max_cols (end_sheet))
2116 				rng->end.col  = rinfo->origin.start.col - 1;
2117 			else
2118 				rng->end.col += rinfo->col_offset;
2119 			return TRUE;
2120 		}
2121 	}
2122 
2123 	return FALSE;
2124 }
2125 
2126 static void
reloc_normalize_cellref(RelocInfoInternal const * rinfo,GnmCellRef const * ref,Sheet ** sheet,GnmCellPos * res)2127 reloc_normalize_cellref (RelocInfoInternal const *rinfo, GnmCellRef const *ref,
2128 			 Sheet **sheet, GnmCellPos *res)
2129 {
2130 	*sheet = eval_sheet (ref->sheet, rinfo->details->pos.sheet);
2131 	res->col = ref->col;
2132 	if (ref->col_relative) {
2133 		if (rinfo->check_rels)
2134 			res->col += rinfo->details->pos.eval.col;
2135 		else
2136 			res->col = 0;
2137 	}
2138 	res->row = ref->row;
2139 	if (ref->row_relative) {
2140 		if (rinfo->check_rels)
2141 			res->row += rinfo->details->pos.eval.row;
2142 		else
2143 			res->row = 0;
2144 	}
2145 }
2146 
2147 /* Return %TRUE if @pos is out of bounds */
2148 static gboolean
reloc_restore_cellref(RelocInfoInternal const * rinfo,GnmSheetSize const * ss,GnmCellPos const * pos,GnmCellRef * res)2149 reloc_restore_cellref (RelocInfoInternal const *rinfo,
2150 		       GnmSheetSize const *ss, GnmCellPos const *pos,
2151 		       GnmCellRef *res)
2152 {
2153 	if (res->sheet == rinfo->details->origin_sheet) {
2154 		res->sheet = rinfo->details->target_sheet;
2155 		if (res->sheet)
2156 			ss = gnm_sheet_get_size (res->sheet);
2157 	}
2158 
2159 	if (!res->col_relative || rinfo->check_rels) {
2160 		if (pos->col < 0 || ss->max_cols <= pos->col)
2161 			return TRUE;
2162 		res->col = pos->col;
2163 		if (res->col_relative) {
2164 			res->col -= rinfo->details->pos.eval.col;
2165 			if (rinfo->from_inside)
2166 				res->col -= rinfo->details->col_offset;
2167 		}
2168 	}
2169 
2170 	if (!res->row_relative || rinfo->check_rels) {
2171 		if (pos->row < 0 || ss->max_rows <= pos->row)
2172 			return TRUE;
2173 		res->row = pos->row;
2174 		if (res->row_relative) {
2175 			res->row -= rinfo->details->pos.eval.row;
2176 			if (rinfo->from_inside)
2177 				res->row -= rinfo->details->row_offset;
2178 		}
2179 	}
2180 
2181 	return FALSE;
2182 }
2183 
2184 
2185 static GnmExpr const *
reloc_cellrange(RelocInfoInternal const * rinfo,GnmValueRange const * v,gboolean sticky_end)2186 reloc_cellrange (RelocInfoInternal const *rinfo, GnmValueRange const *v,
2187 		 gboolean sticky_end)
2188 {
2189 	GnmRange r;
2190 	Sheet   *start_sheet, *end_sheet;
2191 	GnmSheetSize const *start_ss, *end_ss;
2192 	gboolean full_col, full_row;
2193 	gboolean full_col_begin, full_row_begin;
2194 
2195 	/* Normalize the rangeRef, and remember if we had a full col/row
2196 	 *  ref.  If relocating the result changes things, or if we're from
2197 	 *  inside the range that is moving map back to a RangeRef from the
2198 	 *  target position.  If the result is different that the original
2199 	 *  generate a new expression. */
2200 	reloc_normalize_cellref (rinfo, &v->cell.a, &start_sheet, &r.start);
2201 	reloc_normalize_cellref (rinfo, &v->cell.b, &end_sheet,   &r.end);
2202 	/* (Foo,NULL) in Bar will generate (Foo,Bar) in normalize */
2203 	if (NULL == v->cell.b.sheet)
2204 		end_sheet = start_sheet;
2205 	start_ss = gnm_sheet_get_size2 (start_sheet, rinfo->details->pos.wb);
2206 	end_ss = gnm_sheet_get_size2 (end_sheet, rinfo->details->pos.wb);
2207 
2208 	full_col = sticky_end && r.end.row >= start_ss->max_rows - 1;
2209 	full_col_begin = full_col && r.start.row == 0;
2210 
2211 	full_row = sticky_end && r.end.col >= start_ss->max_cols - 1;
2212 	full_row_begin = full_row && r.start.col == 0;
2213 
2214 	if (reloc_range (rinfo->details, start_sheet, end_sheet, &r) ||
2215 	    rinfo->from_inside) {
2216 		GnmRangeRef res = v->cell;
2217 
2218 		if (full_col)
2219 			r.end.row = start_ss->max_rows - 1;
2220 		if (full_col_begin)
2221 			r.start.row = 0;
2222 		if (full_row)
2223 			r.end.col = start_ss->max_cols - 1;
2224 		if (full_row_begin)
2225 			r.start.col = 0;
2226 
2227 		if (reloc_restore_cellref (rinfo, start_ss, &r.start, &res.a) ||
2228 		    reloc_restore_cellref (rinfo, end_ss,   &r.end,   &res.b))
2229 			return gnm_expr_new_constant (value_new_error_REF (NULL));
2230 		if (gnm_rangeref_equal (&res, &v->cell))
2231 			return NULL;
2232 		return gnm_expr_new_constant (value_new_cellrange_unsafe (&res.a, &res.b));
2233 	}
2234 
2235 	return NULL;
2236 }
2237 
2238 static GnmExpr const *
2239 gnm_expr_relocate (GnmExpr const *expr, RelocInfoInternal const *rinfo);
2240 
2241 static GnmExpr const *
cb_relocate(GnmExpr const * expr,GnmExprWalk * data)2242 cb_relocate (GnmExpr const *expr, GnmExprWalk *data)
2243 {
2244 	RelocInfoInternal const *rinfo = data->user;
2245 
2246 	switch (GNM_EXPR_GET_OPER (expr)) {
2247 	case GNM_EXPR_OP_NAME: {
2248 		GnmNamedExpr *nexpr = expr->name.name;
2249 
2250 		/* we cannot invalidate references to the name that are
2251 		 * sitting in the undo queue, or the clipboard.  So we just
2252 		 * flag the name as inactive and remove the reference here.
2253 		 */
2254 		if (!expr_name_is_active (nexpr))
2255 			return gnm_expr_new_constant (value_new_error_REF (NULL));
2256 
2257 		switch (rinfo->details->reloc_type) {
2258 		case GNM_EXPR_RELOCATE_INVALIDATE_SHEET:
2259 			if (nexpr->pos.sheet && nexpr->pos.sheet->being_invalidated)
2260 				return gnm_expr_new_constant (value_new_error_REF (NULL));
2261 			else
2262 				return NULL;
2263 
2264 		case GNM_EXPR_RELOCATE_MOVE_RANGE:
2265 			/*
2266 			 * If the name is not officially scoped, check
2267 			 * that it is available in the new scope
2268 			 */
2269 			if (expr->name.optional_scope == NULL &&
2270 			    rinfo->details->target_sheet != rinfo->details->origin_sheet) {
2271 				GnmNamedExpr *new_nexpr;
2272 				GnmParsePos pos;
2273 				parse_pos_init_sheet (&pos, rinfo->details->target_sheet);
2274 
2275 				/* If the name is not available in the new scope explicitly scope it */
2276 				new_nexpr = expr_name_lookup (&pos, expr_name_name (nexpr));
2277 				if (new_nexpr == NULL) {
2278 					if (nexpr->pos.sheet != NULL)
2279 						return gnm_expr_new_name (nexpr, nexpr->pos.sheet, NULL);
2280 					return gnm_expr_new_name (nexpr, NULL, nexpr->pos.wb);
2281 				}
2282 
2283 				/* replace it with the new name using qualified as
2284 				 * local to the target sheet
2285 				 */
2286 				return gnm_expr_new_name (new_nexpr, pos.sheet, NULL);
2287 			} else {
2288 				/*
2289 				 * Do NOT rewrite the name.
2290 				 *
2291 				 * Just invalidate the use of the name if the
2292 				 * name's expression, if relocated, would
2293 				 * become invalid.
2294 				 */
2295 				GnmExpr const *tmp =
2296 					gnm_expr_relocate (nexpr->texpr->expr,
2297 							   rinfo);
2298 				if (tmp && gnm_expr_is_err (tmp, GNM_ERROR_REF))
2299 					return tmp;
2300 
2301 				if (tmp)
2302 					gnm_expr_free (tmp);
2303 
2304 				return NULL;
2305 			}
2306 
2307 		case GNM_EXPR_RELOCATE_COLS:
2308 		case GNM_EXPR_RELOCATE_ROWS:
2309 			return NULL;
2310 
2311 		default:
2312 			g_assert_not_reached ();
2313 		}
2314 	}
2315 
2316 	case GNM_EXPR_OP_CELLREF: {
2317 		GnmCellRef const *ref = &expr->cellref.ref;
2318 		switch (rinfo->details->reloc_type) {
2319 		case GNM_EXPR_RELOCATE_INVALIDATE_SHEET:
2320 			if (ref->sheet &&
2321 			    ref->sheet->being_invalidated)
2322 				return gnm_expr_new_constant (value_new_error_REF (NULL));
2323 			return NULL;
2324 
2325 		case GNM_EXPR_RELOCATE_MOVE_RANGE:
2326 		case GNM_EXPR_RELOCATE_COLS:
2327 		case GNM_EXPR_RELOCATE_ROWS: {
2328 			GnmRange r;
2329 			Sheet *sheet;
2330 			GnmSheetSize const *ss;
2331 
2332 			reloc_normalize_cellref (rinfo, ref, &sheet, &r.start);
2333 			r.end = r.start;
2334 			ss = gnm_sheet_get_size2 (sheet, rinfo->details->pos.wb);
2335 
2336 			if (reloc_range (rinfo->details, sheet, sheet, &r) ||
2337 			    rinfo->from_inside) {
2338 				GnmCellRef res = *ref;
2339 				if (reloc_restore_cellref (rinfo, ss, &r.start, &res))
2340 					return gnm_expr_new_constant (value_new_error_REF (NULL));
2341 				if (gnm_cellref_equal (&res, ref))
2342 					return NULL;
2343 				return gnm_expr_new_cellref (&res);
2344 			}
2345 			return NULL;
2346 		}
2347 
2348 		default:
2349 			g_assert_not_reached ();
2350 		}
2351 
2352 		return NULL;
2353 	}
2354 
2355 	case GNM_EXPR_OP_CONSTANT:
2356 		if (VALUE_IS_CELLRANGE (expr->constant.value)) {
2357 			GnmValueRange const *vr = &expr->constant.value->v_range;
2358 			switch (rinfo->details->reloc_type) {
2359 			case GNM_EXPR_RELOCATE_INVALIDATE_SHEET:
2360 				return invalidate_sheet_cellrange (rinfo, vr);
2361 			case GNM_EXPR_RELOCATE_MOVE_RANGE:
2362 				return reloc_cellrange (rinfo, vr, TRUE);
2363 			case GNM_EXPR_RELOCATE_COLS:
2364 			case GNM_EXPR_RELOCATE_ROWS:
2365 				return reloc_cellrange (rinfo, vr, rinfo->details->sticky_end);
2366 			default:
2367 				g_assert_not_reached ();
2368 			}
2369 		}
2370 		return NULL;
2371 
2372 	default:
2373 		return NULL;
2374 	}
2375 }
2376 
2377 static GnmExpr const *
gnm_expr_relocate(GnmExpr const * expr,RelocInfoInternal const * rinfo)2378 gnm_expr_relocate (GnmExpr const *expr, RelocInfoInternal const *rinfo)
2379 {
2380 	g_return_val_if_fail (expr != NULL, NULL);
2381 	return gnm_expr_walk (expr, cb_relocate, (gpointer)rinfo);
2382 }
2383 
2384 /**
2385  * gnm_expr_get_func_def:
2386  * @expr: Function call expressions
2387  *
2388  * Returns: (transfer none): the called function.
2389  */
2390 GnmFunc *
gnm_expr_get_func_def(GnmExpr const * expr)2391 gnm_expr_get_func_def (GnmExpr const *expr)
2392 {
2393 	g_return_val_if_fail (expr != NULL, NULL);
2394 	g_return_val_if_fail (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_FUNCALL, NULL);
2395 
2396 	return expr->func.func;
2397 }
2398 
2399 /**
2400  * gnm_expr_get_func_arg:
2401  * @expr: Function call expressions
2402  * @i: argument index
2403  *
2404  * Returns: (transfer none): the @i'th argument of the function call @expr.
2405  */
2406 GnmExpr const *
gnm_expr_get_func_arg(GnmExpr const * expr,int i)2407 gnm_expr_get_func_arg (GnmExpr const *expr, int i)
2408 {
2409 	g_return_val_if_fail (expr != NULL, NULL);
2410 	g_return_val_if_fail (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_FUNCALL, NULL);
2411 	g_return_val_if_fail (i >= 0 && i < expr->func.argc, NULL);
2412 
2413 	return expr->func.argv[i];
2414 }
2415 
2416 
2417 static void
cellref_boundingbox(GnmCellRef const * cr,Sheet const * sheet,GnmRange * bound)2418 cellref_boundingbox (GnmCellRef const *cr, Sheet const *sheet, GnmRange *bound)
2419 {
2420 	GnmSheetSize const *ss;
2421 
2422 	if (cr->sheet)
2423 		sheet = cr->sheet;
2424 	ss = gnm_sheet_get_size (sheet);
2425 
2426 	if (cr->col_relative) {
2427 		if (cr->col >= 0) {
2428 			int const c = ss->max_cols - cr->col - 1;
2429 			if (bound->end.col > c)
2430 				bound->end.col = c;
2431 		} else {
2432 			int const c = -cr->col;
2433 			if (bound->start.col < c)
2434 				bound->start.col = c;
2435 		}
2436 	}
2437 	if (cr->row_relative) {
2438 		if (cr->row >= 0) {
2439 			int const r = ss->max_rows - cr->row - 1;
2440 			if (bound->end.row > r)
2441 				bound->end.row = r;
2442 		} else {
2443 			int const r = -cr->row;
2444 			if (bound->start.row < r)
2445 				bound->start.row = r;
2446 		}
2447 	}
2448 }
2449 
2450 static GnmExpr const *
cb_contains_subtotal(GnmExpr const * expr,GnmExprWalk * data)2451 cb_contains_subtotal (GnmExpr const *expr, GnmExprWalk *data)
2452 {
2453 	gboolean *res = data->user;
2454 	if (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_FUNCALL &&
2455 	    strcmp (expr->func.func->name, "subtotal") == 0) {
2456 		*res = TRUE;
2457 		data->stop = TRUE;
2458 	}
2459 	return NULL;
2460 }
2461 
2462 /**
2463  * gnm_expr_containts_subtotal:
2464  * @expr: #GnmExpr
2465  *
2466  * Returns: %TRUE if the expression calls the SUBTOTAL function
2467  **/
2468 gboolean
gnm_expr_contains_subtotal(GnmExpr const * expr)2469 gnm_expr_contains_subtotal (GnmExpr const *expr)
2470 {
2471 	gboolean res = FALSE;
2472 	gnm_expr_walk (expr, cb_contains_subtotal, &res);
2473 	return res;
2474 }
2475 
2476 /**
2477  * gnm_expr_get_range:
2478  * @expr: #GnmExpr
2479  *
2480  * Returns: (transfer full) (nullable): If this expression contains a
2481  * single range, return it.  Otherwise, %NULL.  A cell reference is
2482  * returned as a singleton range.
2483  */
2484 GnmValue *
gnm_expr_get_range(GnmExpr const * expr)2485 gnm_expr_get_range (GnmExpr const *expr)
2486 {
2487 	g_return_val_if_fail (expr != NULL, NULL);
2488 
2489 	switch (GNM_EXPR_GET_OPER (expr)) {
2490 	case GNM_EXPR_OP_CELLREF:
2491 		return value_new_cellrange_unsafe (
2492 			&expr->cellref.ref, &expr->cellref.ref);
2493 
2494 	case GNM_EXPR_OP_CONSTANT:
2495 		if (VALUE_IS_CELLRANGE (expr->constant.value))
2496 			return value_dup (expr->constant.value);
2497 		return NULL;
2498 
2499 	case GNM_EXPR_OP_NAME:
2500 		if (!expr_name_is_active (expr->name.name))
2501 			return NULL;
2502 		return gnm_expr_top_get_range (expr->name.name->texpr);
2503 
2504 	case GNM_EXPR_OP_PAREN:
2505 		return gnm_expr_get_range (expr->unary.value);
2506 
2507 	default:
2508 		return NULL;
2509 	}
2510 }
2511 
2512 static gint
gnm_insert_unique_value_cmp(gconstpointer a,gconstpointer b)2513 gnm_insert_unique_value_cmp (gconstpointer a, gconstpointer b)
2514 {
2515 	return (value_equal (a,b) ? 0 : 1);
2516 }
2517 
2518 
2519 
2520 static GSList *
gnm_insert_unique_value(GSList * list,GnmValue * data)2521 gnm_insert_unique_value (GSList *list, GnmValue *data)
2522 {
2523 	if (g_slist_find_custom (list, data,
2524 				 gnm_insert_unique_value_cmp)
2525 	    == NULL)
2526 		return g_slist_prepend (list, data);
2527 	value_release (data);
2528 	return list;
2529 }
2530 
2531 /**
2532  * gnm_expr_is_rangeref:
2533  * @expr: #GnmExpr
2534  *
2535  * Returns: %TRUE if the expression can generate a reference.
2536  * NOTE: in the future it would be nice to know if a function
2537  * can return a reference to tighten that up a bit.
2538  **/
2539 gboolean
gnm_expr_is_rangeref(GnmExpr const * expr)2540 gnm_expr_is_rangeref (GnmExpr const *expr)
2541 {
2542 	g_return_val_if_fail (expr != NULL, FALSE);
2543 
2544 	switch (GNM_EXPR_GET_OPER (expr)) {
2545 	/* would be better if we could differential which functions can return refs */
2546 	case GNM_EXPR_OP_FUNCALL:
2547 
2548 	/* a set in a set, do we need this ? */
2549 	case GNM_EXPR_OP_SET:
2550 
2551 	case GNM_EXPR_OP_RANGE_CTOR:
2552 	case GNM_EXPR_OP_INTERSECT:
2553 	case GNM_EXPR_OP_CELLREF:
2554 		return TRUE;
2555 
2556 	case GNM_EXPR_OP_CONSTANT:
2557 		if (VALUE_IS_CELLRANGE (expr->constant.value))
2558 			return TRUE;
2559 		return FALSE;
2560 
2561 	case GNM_EXPR_OP_NAME:
2562 		if (expr_name_is_active (expr->name.name))
2563 			return gnm_expr_is_rangeref (expr->name.name->texpr->expr);
2564 		return FALSE;
2565 
2566 	case GNM_EXPR_OP_ARRAY_CORNER: /* I don't think this is possible */
2567 	case GNM_EXPR_OP_ARRAY_ELEM:
2568 	default:
2569 		return FALSE;
2570 	}
2571 }
2572 
2573 gboolean
gnm_expr_is_data_table(GnmExpr const * expr,GnmCellPos * c_in,GnmCellPos * r_in)2574 gnm_expr_is_data_table (GnmExpr const *expr, GnmCellPos *c_in, GnmCellPos *r_in)
2575 {
2576 	if (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_FUNCALL) {
2577 		char const *name = gnm_func_get_name (expr->func.func, FALSE);
2578 		if (name && 0 == strcmp (name, "table")) {
2579 			if (NULL != r_in) {
2580 				GnmExpr const *r = (expr->func.argc <= 0)
2581 					? NULL
2582 					: expr->func.argv[0];
2583 
2584 				if (r != NULL && GNM_EXPR_GET_OPER (r) == GNM_EXPR_OP_CELLREF) {
2585 					r_in->col = r->cellref.ref.col;
2586 					r_in->row = r->cellref.ref.row;
2587 				} else
2588 					r_in->col = r_in->row = 0; /* impossible */
2589 			}
2590 			if (NULL != c_in) {
2591 				GnmExpr const *c = (expr->func.argc <= 1)
2592 					? NULL
2593 					: expr->func.argv[1];
2594 
2595 				if (c != NULL && GNM_EXPR_GET_OPER (c) == GNM_EXPR_OP_CELLREF) {
2596 					c_in->col = c->cellref.ref.col;
2597 					c_in->row = c->cellref.ref.row;
2598 				} else
2599 					c_in->col = c_in->row = 0; /* impossible */
2600 			}
2601 			return TRUE;
2602 		}
2603 	}
2604 
2605 	/* Do we need anything else here ? */
2606 	return FALSE;
2607 }
2608 
2609 
2610 static GnmExpr const *
do_expr_walk(GnmExpr const * expr,GnmExprWalkerFunc walker,GnmExprWalk * data)2611 do_expr_walk (GnmExpr const *expr, GnmExprWalkerFunc walker, GnmExprWalk *data)
2612 {
2613 	GnmExpr const *res;
2614 
2615 	res = walker (expr, data);
2616 	if (data->stop) {
2617 		if (res) gnm_expr_free (res);
2618 		return NULL;
2619 	}
2620 	if (res)
2621 		return res;
2622 
2623 	switch (GNM_EXPR_GET_OPER (expr)) {
2624 	case GNM_EXPR_OP_RANGE_CTOR:
2625 	case GNM_EXPR_OP_INTERSECT:
2626 	case GNM_EXPR_OP_ANY_BINARY: {
2627 		GnmExpr const *a, *b;
2628 
2629 		a = do_expr_walk (expr->binary.value_a, walker, data);
2630 		if (data->stop)
2631 			return NULL;
2632 
2633 		b = do_expr_walk (expr->binary.value_b, walker, data);
2634 		if (data->stop) {
2635 			if (a) gnm_expr_free (a);
2636 			return NULL;
2637 		}
2638 
2639 		if (!a && !b)
2640 			return NULL;
2641 
2642 		if (!a)
2643 			a = gnm_expr_copy (expr->binary.value_a);
2644 		else if (!b)
2645 			b = gnm_expr_copy (expr->binary.value_b);
2646 
2647 		return gnm_expr_new_binary (a, GNM_EXPR_GET_OPER (expr), b);
2648 	}
2649 
2650 	case GNM_EXPR_OP_ANY_UNARY: {
2651 		GnmExpr const *a = do_expr_walk (expr->unary.value, walker, data);
2652 		return a
2653 			? gnm_expr_new_unary (GNM_EXPR_GET_OPER (expr), a)
2654 			: NULL;
2655 	}
2656 
2657 	case GNM_EXPR_OP_FUNCALL: {
2658 		gboolean any = FALSE;
2659 		int i;
2660 		int argc = expr->func.argc;
2661 		GnmExprConstPtr *argv =
2662 			argc ? g_new (GnmExprConstPtr, argc) : NULL;
2663 
2664 		for (i = 0; i < argc; i++) {
2665 			argv[i] = do_expr_walk (expr->func.argv[i], walker, data);
2666 			if (data->stop) {
2667 				while (--i >= 0)
2668 					if (argv[i])
2669 						gnm_expr_free (argv[i]);
2670 				any = FALSE;
2671 				break;
2672 			}
2673 			if (argv[i])
2674 				any = TRUE;
2675 		}
2676 
2677 		if (any) {
2678 			int i;
2679 			for (i = 0; i < argc; i++)
2680 				if (!argv[i])
2681 					argv[i] = gnm_expr_copy (expr->func.argv[i]);
2682 			return gnm_expr_new_funcallv (expr->func.func,
2683 						      argc, argv);
2684 		} else {
2685 			g_free (argv);
2686 			return NULL;
2687 		}
2688 	}
2689 	case GNM_EXPR_OP_SET: {
2690 		gboolean any = FALSE;
2691 		int i;
2692 		int argc = expr->set.argc;
2693 		GnmExprConstPtr *argv =
2694 			argc ? g_new (GnmExprConstPtr, argc) : NULL;
2695 
2696 		for (i = 0; i < argc; i++) {
2697 			argv[i] = do_expr_walk (expr->set.argv[i], walker, data);
2698 			if (data->stop) {
2699 				while (--i >= 0)
2700 					if (argv[i])
2701 						gnm_expr_free (argv[i]);
2702 				any = FALSE;
2703 				break;
2704 			}
2705 			if (argv[i])
2706 				any = TRUE;
2707 		}
2708 
2709 		if (any) {
2710 			int i;
2711 			for (i = 0; i < argc; i++)
2712 				if (!argv[i])
2713 					argv[i] = gnm_expr_copy (expr->set.argv[i]);
2714 			return gnm_expr_new_setv (argc, argv);
2715 		} else {
2716 			g_free (argv);
2717 			return NULL;
2718 		}
2719 	}
2720 
2721 	case GNM_EXPR_OP_ARRAY_CORNER: {
2722 		GnmExpr const *e = do_expr_walk (expr->array_corner.expr, walker, data);
2723 		return e
2724 			? gnm_expr_new_array_corner (
2725 				expr->array_corner.cols,
2726 				expr->array_corner.rows, e)
2727 			: NULL;
2728 	}
2729 
2730 	default:
2731 		return NULL;
2732 	}
2733 }
2734 
2735 /**
2736  * gnm_expr_walk:
2737  * @expr: expression to walk
2738  * @walker: (scope call): callback for each sub-expression
2739  * @user: user data pointer
2740  *
2741  * Returns: (transfer full) (nullable): transformed expression.
2742  *
2743  * This function walks the expression and calls the walker function for
2744  * each subexpression.  If the walker returns a non-%NULL expression,
2745  * a new expression is built.
2746  *
2747  * The walker will be called for an expression before its subexpressions.
2748  * It will receive the expression as its first argument and a GnmExprWalk
2749  * pointer as its second.  It may set the stop flag to terminate the walk
2750  * in which case gnm_expr_walk will return %NULL.
2751  **/
2752 GnmExpr const *
gnm_expr_walk(GnmExpr const * expr,GnmExprWalkerFunc walker,gpointer user)2753 gnm_expr_walk (GnmExpr const *expr, GnmExprWalkerFunc walker, gpointer user)
2754 {
2755 	GnmExprWalk data;
2756 
2757 	g_return_val_if_fail (expr != NULL, NULL);
2758 
2759 	data.user = user;
2760 	data.stop = FALSE;
2761 	data.flags = 0;
2762 	return do_expr_walk (expr, walker, &data);
2763 }
2764 
2765 /**
2766  * gnm_expr_is_empty:
2767  * @expr: #GnmExpr
2768  *
2769  * Returns: %TRUE if @expr is a constant expression with the empty value.
2770  */
2771 gboolean
gnm_expr_is_empty(GnmExpr const * expr)2772 gnm_expr_is_empty (GnmExpr const *expr)
2773 {
2774 	g_return_val_if_fail (expr != NULL, FALSE);
2775 
2776 	return (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_CONSTANT &&
2777 		VALUE_IS_EMPTY (expr->constant.value));
2778 }
2779 
2780 /**
2781  * gnm_expr_list_unref:
2782  * @list: (transfer full): expression list
2783  *
2784  * This frees list and all the expressions in it.
2785  */
2786 void
gnm_expr_list_unref(GnmExprList * list)2787 gnm_expr_list_unref (GnmExprList *list)
2788 {
2789 	GnmExprList *l;
2790 	for (l = list; l; l = l->next)
2791 		gnm_expr_free (l->data);
2792 	gnm_expr_list_free (list);
2793 }
2794 
2795 /**
2796  * gnm_expr_list_copy:
2797  * @list: (transfer none): list of expressions
2798  *
2799  * Returns: (transfer full): a copy of the list and all the
2800  * expressions in it.
2801  */
2802 GnmExprList *
gnm_expr_list_copy(GnmExprList * list)2803 gnm_expr_list_copy (GnmExprList *list)
2804 {
2805 	GnmExprList *res = g_slist_copy (list); /* shallow */
2806 	GnmExprList *l;
2807 
2808 	for (l = res; l; l = l->next)
2809 		l->data = (GnmExpr *) gnm_expr_copy (l->data);
2810 
2811 	return res;
2812 }
2813 
2814 
2815 void
gnm_expr_list_as_string(int argc,GnmExprConstPtr const * argv,GnmConventionsOut * out)2816 gnm_expr_list_as_string (int argc,
2817 			 GnmExprConstPtr const *argv,
2818 			 GnmConventionsOut *out)
2819 {
2820 	int i;
2821 	gunichar arg_sep;
2822 	if (out->convs->arg_sep)
2823 		arg_sep = out->convs->arg_sep;
2824 	else
2825 		arg_sep = go_locale_get_arg_sep ();
2826 
2827 	g_string_append_c (out->accum, '(');
2828 	for (i = 0; i < argc; i++) {
2829 		if (i != 0)
2830 			g_string_append_unichar (out->accum, arg_sep);
2831 		do_expr_as_string (argv[i], 0, out);
2832 	}
2833 	g_string_append_c (out->accum, ')');
2834 }
2835 
2836 static guint
gnm_expr_hash(GnmExpr const * expr)2837 gnm_expr_hash (GnmExpr const *expr)
2838 {
2839 	guint h = (guint)(GNM_EXPR_GET_OPER (expr));
2840 
2841 	switch (GNM_EXPR_GET_OPER (expr)){
2842 	case GNM_EXPR_OP_INTERSECT:
2843 	case GNM_EXPR_OP_RANGE_CTOR:
2844 	case GNM_EXPR_OP_ANY_BINARY:
2845 		return ((gnm_expr_hash (expr->binary.value_a) * 7) ^
2846 			(gnm_expr_hash (expr->binary.value_b) * 3) ^
2847 			h);
2848 
2849 	case GNM_EXPR_OP_ANY_UNARY:
2850 		return ((gnm_expr_hash (expr->unary.value) * 7) ^
2851 			h);
2852 
2853 	case GNM_EXPR_OP_FUNCALL: {
2854 		int i;
2855 		for (i = 0; i < expr->func.argc; i++)
2856 			h = (h * 3) ^ gnm_expr_hash (expr->func.argv[i]);
2857 		return h;
2858 	}
2859 
2860 	case GNM_EXPR_OP_SET: {
2861 		int i;
2862 		for (i = 0; i < expr->set.argc; i++)
2863 			h = (h * 3) ^ gnm_expr_hash (expr->set.argv[i]);
2864 		return h;
2865 	}
2866 
2867 	case GNM_EXPR_OP_CONSTANT:
2868 		return value_hash (expr->constant.value);
2869 
2870 	case GNM_EXPR_OP_NAME:
2871 		/* all we need is a somewhat unique hash, ignore int != ptr */
2872 		return GPOINTER_TO_UINT (expr->name.name);
2873 
2874 	case GNM_EXPR_OP_CELLREF:
2875 		return gnm_cellref_hash (&expr->cellref.ref);
2876 
2877 	case GNM_EXPR_OP_ARRAY_CORNER:
2878 		return gnm_expr_hash (expr->array_corner.expr);
2879 
2880 	case GNM_EXPR_OP_ARRAY_ELEM:
2881 		return ((expr->array_elem.x << 16) ^
2882 			(expr->array_elem.y));
2883 	}
2884 
2885 	return h;
2886 }
2887 
2888 
2889 /***************************************************************************/
2890 
2891 GnmExprSharer *
gnm_expr_sharer_new(void)2892 gnm_expr_sharer_new (void)
2893 {
2894 	GnmExprSharer *es = g_new (GnmExprSharer, 1);
2895 	es->nodes_in = 0;
2896 	es->nodes_stored = 0;
2897 	es->nodes_killed = 0;
2898 	es->exprs = g_hash_table_new_full
2899 		((GHashFunc)gnm_expr_top_hash,
2900 		 (GEqualFunc)gnm_expr_top_equal,
2901 		 (GDestroyNotify)gnm_expr_top_unref,
2902 		 NULL);
2903 	es->ref_count = 1;
2904 	return es;
2905 }
2906 
2907 void
gnm_expr_sharer_unref(GnmExprSharer * es)2908 gnm_expr_sharer_unref (GnmExprSharer *es)
2909 {
2910 	if (!es || es->ref_count-- > 1)
2911 		return;
2912 	g_hash_table_destroy (es->exprs);
2913 	g_free (es);
2914 }
2915 
2916 static GnmExprSharer *
gnm_expr_sharer_ref(GnmExprSharer * es)2917 gnm_expr_sharer_ref (GnmExprSharer *es)
2918 {
2919 	es->ref_count++;
2920 	return es;
2921 }
2922 
2923 GType
gnm_expr_sharer_get_type(void)2924 gnm_expr_sharer_get_type (void)
2925 {
2926 	static GType t = 0;
2927 
2928 	if (t == 0) {
2929 		t = g_boxed_type_register_static ("GnmExprSharer",
2930 			 (GBoxedCopyFunc)gnm_expr_sharer_ref,
2931 			 (GBoxedFreeFunc)gnm_expr_sharer_unref);
2932 	}
2933 	return t;
2934 }
2935 
2936 GnmExprTop const *
gnm_expr_sharer_share(GnmExprSharer * es,GnmExprTop const * texpr)2937 gnm_expr_sharer_share (GnmExprSharer *es, GnmExprTop const *texpr)
2938 {
2939 	GnmExprTop const *shared;
2940 
2941         g_return_val_if_fail (es != NULL, texpr);
2942         g_return_val_if_fail (texpr != NULL, NULL);
2943 
2944 	es->nodes_in++;
2945 
2946 	/* Corners must not get shared.  */
2947 	if (GNM_EXPR_GET_OPER (texpr->expr) == GNM_EXPR_OP_ARRAY_CORNER)
2948 		return texpr;
2949 
2950 	shared = g_hash_table_lookup (es->exprs, texpr);
2951 	if (shared) {
2952 		gnm_expr_top_ref (shared);
2953 		if (texpr->refcount == 1)
2954 			es->nodes_killed++;
2955 		gnm_expr_top_unref (texpr);
2956 		return shared;
2957 	}
2958 
2959 	gnm_expr_top_ref (texpr);
2960 	g_hash_table_insert (es->exprs, (gpointer)texpr, (gpointer)texpr);
2961 	es->nodes_stored++;
2962 
2963 	return texpr;
2964 }
2965 
2966 void
gnm_expr_sharer_report(GnmExprSharer * es)2967 gnm_expr_sharer_report (GnmExprSharer *es)
2968 {
2969 	g_printerr ("Expressions in: %d\n", es->nodes_in);
2970 	g_printerr ("Expressions stored: %d\n", es->nodes_stored);
2971 	g_printerr ("Expressions killed: %d\n", es->nodes_killed);
2972 }
2973 
2974 /***************************************************************************/
2975 
2976 GnmExprTop const *
gnm_expr_top_new(GnmExpr const * expr)2977 gnm_expr_top_new (GnmExpr const *expr)
2978 {
2979 	GnmExprTop *res;
2980 
2981 	if (expr == NULL)
2982 		return NULL;
2983 
2984 	res = g_new (GnmExprTop, 1);
2985 	res->magic = GNM_EXPR_TOP_MAGIC;
2986 	res->hash = 0;
2987 	res->refcount = 1;
2988 	res->expr = expr;
2989 	return res;
2990 }
2991 
2992 GnmExprTop const *
gnm_expr_top_new_constant(GnmValue * v)2993 gnm_expr_top_new_constant (GnmValue *v)
2994 {
2995 	return gnm_expr_top_new (gnm_expr_new_constant (v));
2996 }
2997 
2998 GnmExprTop const *
gnm_expr_top_ref(GnmExprTop const * texpr)2999 gnm_expr_top_ref (GnmExprTop const *texpr)
3000 {
3001 	g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), NULL);
3002 	((GnmExprTop *)texpr)->refcount++;
3003 	return texpr;
3004 }
3005 
3006 void
gnm_expr_top_unref(GnmExprTop const * texpr)3007 gnm_expr_top_unref (GnmExprTop const *texpr)
3008 {
3009 	g_return_if_fail (GNM_IS_EXPR_TOP (texpr));
3010 
3011 	((GnmExprTop *)texpr)->refcount--;
3012 	if (texpr->refcount == 0) {
3013 		gnm_expr_free (texpr->expr);
3014 		((GnmExprTop *)texpr)->magic = 0;
3015 		g_free ((GnmExprTop *)texpr);
3016 	}
3017 }
3018 
3019 GType
gnm_expr_top_get_type(void)3020 gnm_expr_top_get_type (void)
3021 {
3022 	static GType t = 0;
3023 
3024 	if (t == 0) {
3025 		t = g_boxed_type_register_static ("GnmExprTop",
3026 			 (GBoxedCopyFunc)gnm_expr_top_ref,
3027 			 (GBoxedFreeFunc)gnm_expr_top_unref);
3028 	}
3029 	return t;
3030 }
3031 
3032 gboolean
gnm_expr_top_is_shared(GnmExprTop const * texpr)3033 gnm_expr_top_is_shared (GnmExprTop const *texpr)
3034 {
3035 	g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), FALSE);
3036 
3037 	return texpr->refcount > 1;
3038 }
3039 
3040 GnmExprTop const *
gnm_expr_top_new_array_corner(int cols,int rows,GnmExpr const * expr)3041 gnm_expr_top_new_array_corner (int cols, int rows, GnmExpr const *expr)
3042 {
3043 	return gnm_expr_top_new (gnm_expr_new_array_corner (cols, rows, expr));
3044 }
3045 
3046 GnmExprTop const *
gnm_expr_top_new_array_elem(int x,int y)3047 gnm_expr_top_new_array_elem  (int x, int y)
3048 {
3049 	return gnm_expr_top_new (gnm_expr_new_array_elem (x, y));
3050 }
3051 
3052 static GnmExpr const *
cb_get_ranges(GnmExpr const * expr,GnmExprWalk * data)3053 cb_get_ranges (GnmExpr const *expr, GnmExprWalk *data)
3054 {
3055 	GSList **pranges = data->user;
3056 
3057 	/* There's no real reason to exclude names here, except that
3058 	   we used to do so.  */
3059 	if (GNM_EXPR_GET_OPER (expr) != GNM_EXPR_OP_NAME) {
3060 		GnmValue *v = gnm_expr_get_range (expr);
3061 		if (v)
3062 			*pranges = gnm_insert_unique_value (*pranges, v);
3063 	}
3064 
3065 	return NULL;
3066 }
3067 
3068 /**
3069  * gnm_expr_top_get_ranges:
3070  * @texpr:
3071  *
3072  * A collect the set of GnmRanges in @expr.
3073  * Returns: (element-type GnmRange) (transfer full): a list of the unique
3074  * references Caller is responsible for releasing the list and the content.
3075  **/
3076 GSList *
gnm_expr_top_get_ranges(GnmExprTop const * texpr)3077 gnm_expr_top_get_ranges (GnmExprTop const *texpr)
3078 {
3079 	GSList *res = NULL;
3080 
3081 	g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), NULL);
3082 	gnm_expr_walk (texpr->expr, cb_get_ranges, &res);
3083 	return res;
3084 }
3085 
3086 GnmValue *
gnm_expr_top_get_range(GnmExprTop const * texpr)3087 gnm_expr_top_get_range (GnmExprTop const *texpr)
3088 {
3089 	g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), NULL);
3090 
3091 	return gnm_expr_get_range (texpr->expr);
3092 }
3093 
3094 char *
gnm_expr_top_as_string(GnmExprTop const * texpr,GnmParsePos const * pp,GnmConventions const * convs)3095 gnm_expr_top_as_string (GnmExprTop const *texpr,
3096 			GnmParsePos const *pp,
3097 			GnmConventions const *convs)
3098 {
3099 	g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), NULL);
3100 
3101 	return gnm_expr_as_string (texpr->expr, pp, convs);
3102 }
3103 
3104 // This differs from gnm_expr_as_string in that a top-level set
3105 // representing multiple expressions is rendered as a comma-separated
3106 // list of expressions with no outside parenthesis.
3107 char *
gnm_expr_top_multiple_as_string(GnmExprTop const * texpr,GnmParsePos const * pp,GnmConventions const * convs)3108 gnm_expr_top_multiple_as_string  (GnmExprTop const *texpr,
3109 				  GnmParsePos const *pp,
3110 				  GnmConventions const *convs)
3111 {
3112 	char *res;
3113 
3114 	g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), NULL);
3115 
3116 	res = gnm_expr_top_as_string (texpr, pp, convs);
3117 
3118 	if (GNM_EXPR_GET_OPER (texpr->expr) == GNM_EXPR_OP_SET) {
3119 		// Get rid of '(' and ')'.  This is crude and probably should
3120 		// have made it into convs, but it'll do.
3121 		size_t l = strlen (res);
3122 		if (l >= 2 && res[0] == '(' && res[l - 1] == ')') {
3123 			memmove (res, res + 1, l - 2);
3124 			res[l - 2] = 0;
3125 		}
3126 	}
3127 
3128 	return res;
3129 }
3130 
3131 void
gnm_expr_top_as_gstring(GnmExprTop const * texpr,GnmConventionsOut * out)3132 gnm_expr_top_as_gstring (GnmExprTop const *texpr,
3133 			 GnmConventionsOut *out)
3134 {
3135 	g_return_if_fail (GNM_IS_EXPR_TOP (texpr));
3136 	g_return_if_fail (out != NULL);
3137 
3138 	do_expr_as_string (texpr->expr, 0, out);
3139 }
3140 
3141 guint
gnm_expr_top_hash(GnmExprTop const * texpr)3142 gnm_expr_top_hash (GnmExprTop const *texpr)
3143 {
3144 	g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), 0);
3145 
3146 	if (texpr->hash == 0) {
3147 		((GnmExprTop *)texpr)->hash = gnm_expr_hash (texpr->expr);
3148 		/* The following line tests the truncated value.  */
3149 		if (texpr->hash == 0)
3150 			((GnmExprTop *)texpr)->hash = 1;
3151 	}
3152 	return texpr->hash;
3153 }
3154 
3155 gboolean
gnm_expr_top_equal(GnmExprTop const * te1,GnmExprTop const * te2)3156 gnm_expr_top_equal (GnmExprTop const *te1, GnmExprTop const *te2)
3157 {
3158 	if (te1 == te2)
3159 		return TRUE;
3160 	if (te1 == NULL || te2 == NULL)
3161 		return FALSE;
3162 
3163 	g_return_val_if_fail (GNM_IS_EXPR_TOP (te1), FALSE);
3164 	g_return_val_if_fail (GNM_IS_EXPR_TOP (te2), FALSE);
3165 
3166 	if (te1->hash && te2->hash && te1->hash != te2->hash)
3167 		return FALSE;
3168 
3169 	return gnm_expr_equal (te1->expr, te2->expr);
3170 }
3171 
3172 /*
3173  * gnm_expr_top_relocate:
3174  * @texpr: #GnmExprTop to fixup
3175  * @rinfo: #GnmExprRelocateInfo details of relocation
3176  * @ignore_rel: Do not adjust relative refs (for internal use when
3177  *		  relocating named expressions.   Most callers will want FALSE.
3178  *
3179  * GNM_EXPR_RELOCATE_INVALIDATE_SHEET:
3180  *	Convert any references to  sheets marked being_invalidated into #REF!
3181  * GNM_EXPR_RELOCATE_MOVE_RANGE,
3182  *	Find any references to the specified area and adjust them by the
3183  *	supplied deltas.  Check for out of bounds conditions.  Return %NULL if
3184  *	no change is required.
3185  *	If the expression is within the range to be moved, its relative
3186  *	references to cells outside the range are adjusted to reference the
3187  *	same cell after the move.
3188  * GNM_EXPR_RELOCATE_COLS
3189  * GNM_EXPR_RELOCATE_ROWS
3190  *
3191  */
3192 GnmExprTop const *
gnm_expr_top_relocate(GnmExprTop const * texpr,GnmExprRelocateInfo const * rinfo,gboolean ignore_rel)3193 gnm_expr_top_relocate (GnmExprTop const *texpr,
3194 		       GnmExprRelocateInfo const *rinfo,
3195 		       gboolean ignore_rel)
3196 {
3197 	RelocInfoInternal rinfo_tmp;
3198 
3199 	g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), NULL);
3200 	g_return_val_if_fail (NULL != rinfo, NULL);
3201 
3202 	rinfo_tmp.details = rinfo;
3203 	rinfo_tmp.check_rels = !ignore_rel;
3204 	if (rinfo->reloc_type != GNM_EXPR_RELOCATE_INVALIDATE_SHEET)
3205 		rinfo_tmp.from_inside = (rinfo->origin_sheet == rinfo->pos.sheet) &&
3206 			range_contains (&rinfo->origin, rinfo->pos.eval.col, rinfo->pos.eval.row);
3207 
3208 	return gnm_expr_top_new (gnm_expr_relocate (texpr->expr, &rinfo_tmp));
3209 }
3210 
3211 /*
3212  * Convenience function to change an expression from one sheet to another.
3213  */
3214 GnmExprTop const *
gnm_expr_top_relocate_sheet(GnmExprTop const * texpr,Sheet const * src,Sheet const * dst)3215 gnm_expr_top_relocate_sheet (GnmExprTop const *texpr,
3216 			     Sheet const *src,
3217 			     Sheet const *dst)
3218 {
3219 	GnmExprRelocateInfo rinfo;
3220 	GnmExprTop const *res;
3221 
3222 	g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), NULL);
3223 	g_return_val_if_fail (IS_SHEET (src), NULL);
3224 	g_return_val_if_fail (IS_SHEET (dst), NULL);
3225 
3226 	rinfo.reloc_type = GNM_EXPR_RELOCATE_MOVE_RANGE;
3227 	rinfo.origin_sheet = (Sheet *)src;
3228 	rinfo.target_sheet = (Sheet *)dst;
3229 	rinfo.col_offset = rinfo.row_offset = 0;
3230 	range_init_full_sheet (&rinfo.origin, src);
3231 	/* Not sure what sheet to use, but it doesn't seem to matter.  */
3232 	parse_pos_init_sheet (&rinfo.pos, rinfo.target_sheet);
3233 
3234 	res = gnm_expr_top_relocate (texpr, &rinfo, FALSE);
3235 	if (!res) {
3236 		if (gnm_expr_top_is_array_corner (texpr))
3237 			res = gnm_expr_top_new (gnm_expr_copy (texpr->expr));
3238 		else
3239 			gnm_expr_top_ref ((res = texpr));
3240 	}
3241 
3242 	return res;
3243 }
3244 
3245 gboolean
gnm_expr_top_contains_subtotal(GnmExprTop const * texpr)3246 gnm_expr_top_contains_subtotal (GnmExprTop const *texpr)
3247 {
3248 	g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), FALSE);
3249 
3250 	return gnm_expr_contains_subtotal (texpr->expr);
3251 }
3252 
3253 static GnmExpr const *
cb_is_volatile(GnmExpr const * expr,GnmExprWalk * data)3254 cb_is_volatile (GnmExpr const *expr, GnmExprWalk *data)
3255 {
3256 	gboolean *res = data->user;
3257 	if (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_FUNCALL &&
3258 	    (gnm_func_get_flags (expr->func.func) & GNM_FUNC_VOLATILE)) {
3259 		*res = TRUE;
3260 		data->stop = TRUE;
3261 	}
3262 	return NULL;
3263 }
3264 
3265 gboolean
gnm_expr_top_is_volatile(GnmExprTop const * texpr)3266 gnm_expr_top_is_volatile (GnmExprTop const *texpr)
3267 {
3268 	gboolean res = FALSE;
3269 
3270 	/*
3271 	 * An expression is volatile if it contains a call to a volatile
3272 	 * function, even in cases like IF(TRUE,12,RAND()) where the
3273 	 * volatile function won't even be reached.
3274 	 */
3275 
3276 	g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), FALSE);
3277 	gnm_expr_walk (texpr->expr, cb_is_volatile, &res);
3278 	return res;
3279 }
3280 
3281 
3282 static GnmValue *
gnm_expr_top_eval_array_corner(GnmExprTop const * texpr,GnmEvalPos const * pos,GnmExprEvalFlags flags)3283 gnm_expr_top_eval_array_corner (GnmExprTop const *texpr,
3284 				GnmEvalPos const *pos,
3285 				GnmExprEvalFlags flags)
3286 {
3287 	GnmExpr const *expr = texpr->expr;
3288 	GnmEvalPos pos2;
3289 	GnmValue *a;
3290 
3291 	pos2 = *pos;
3292 	pos2.array_texpr = texpr;
3293 	a = gnm_expr_eval (expr->array_corner.expr, &pos2,
3294 				     flags | GNM_EXPR_EVAL_PERMIT_NON_SCALAR);
3295 
3296 	value_release (expr->array_corner.value);
3297 
3298 	/* Store real result (cast away const)*/
3299 	((GnmExpr*)expr)->array_corner.value = a;
3300 
3301 	if (a != NULL &&
3302 	    (VALUE_IS_CELLRANGE (a) || VALUE_IS_ARRAY (a))) {
3303 		if (value_area_get_width (a, pos) <= 0 ||
3304 		    value_area_get_height (a, pos) <= 0)
3305 			return value_new_error_NA (pos);
3306 		a = (GnmValue *)value_area_get_x_y (a, 0, 0, pos);
3307 	}
3308 	return handle_empty ((a != NULL) ? value_dup (a) : NULL, flags);
3309 }
3310 
3311 static GnmValue *
gnm_expr_top_eval_array_elem(GnmExprTop const * texpr,GnmEvalPos const * pos,GnmExprEvalFlags flags)3312 gnm_expr_top_eval_array_elem (GnmExprTop const *texpr,
3313 			      GnmEvalPos const *pos,
3314 			      GnmExprEvalFlags flags)
3315 {
3316 	GnmExpr const *expr = texpr->expr;
3317 	/* The upper left corner manages the recalc of the expr */
3318 	GnmCell *corner = array_elem_get_corner (&expr->array_elem,
3319 						 pos->sheet, &pos->eval);
3320 	GnmValue *a;
3321 
3322 	if (!corner ||
3323 	    !gnm_expr_top_is_array_corner (corner->base.texpr)) {
3324 		g_warning ("Funky array setup.");
3325 		return handle_empty (NULL, flags);
3326 	}
3327 
3328 	gnm_cell_eval (corner);
3329 	a = gnm_expr_top_get_array_value (corner->base.texpr);
3330 	if (a == NULL)
3331 		return handle_empty (NULL, flags);
3332 
3333 	if ((VALUE_IS_CELLRANGE (a) || VALUE_IS_ARRAY (a))) {
3334 		int const num_x = value_area_get_width (a, pos);
3335 		int const num_y = value_area_get_height (a, pos);
3336 		int x = expr->array_elem.x;
3337 		int y = expr->array_elem.y;
3338 
3339 		/* Evaluate relative to the upper left corner */
3340 		GnmEvalPos tmp_ep = *pos;
3341 		tmp_ep.eval.col -= x;
3342 		tmp_ep.eval.row -= y;
3343 
3344 		/* If the src array is 1 element wide or tall we wrap */
3345 		if (x >= 1 && num_x == 1)
3346 			x = 0;
3347 		if (y >= 1 && num_y == 1)
3348 			y = 0;
3349 		if (x >= num_x || y >= num_y)
3350 			return value_new_error_NA (pos);
3351 
3352 		a = (GnmValue *)value_area_get_x_y (a, x, y, &tmp_ep);
3353 	}
3354 
3355 	return handle_empty ((a != NULL) ? value_dup (a) : NULL, flags);
3356 }
3357 
3358 GnmValue *
gnm_expr_top_eval(GnmExprTop const * texpr,GnmEvalPos const * pos,GnmExprEvalFlags flags)3359 gnm_expr_top_eval (GnmExprTop const *texpr,
3360 		   GnmEvalPos const *pos,
3361 		   GnmExprEvalFlags flags)
3362 {
3363 	GnmValue *res;
3364 
3365 	g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), NULL);
3366 
3367 	gnm_app_recalc_start ();
3368 
3369 	if (gnm_expr_top_is_array_corner (texpr))
3370 		res = gnm_expr_top_eval_array_corner (texpr, pos, flags);
3371 	else if (gnm_expr_top_is_array_elem (texpr, NULL, NULL))
3372 		res = gnm_expr_top_eval_array_elem (texpr, pos, flags);
3373 	else
3374 		res = gnm_expr_eval (texpr->expr, pos, flags);
3375 	gnm_app_recalc_finish ();
3376 
3377 	return res;
3378 }
3379 
3380 GnmValue *
gnm_expr_top_eval_fake_array(GnmExprTop const * texpr,GnmEvalPos const * pos,GnmExprEvalFlags flags)3381 gnm_expr_top_eval_fake_array (GnmExprTop const *texpr,
3382 			      GnmEvalPos const *pos,
3383 			      GnmExprEvalFlags flags)
3384 {
3385 	if (eval_pos_is_array_context (pos))
3386 		return gnm_expr_top_eval (texpr, pos, flags);
3387 	else {
3388 		GnmEvalPos pos2 = *pos;
3389 		GnmExprTop const *fake = gnm_expr_top_new_array_corner (1, 1, NULL);
3390 		GnmValue *res;
3391 		((GnmExpr *)(fake->expr))->array_corner.expr = texpr->expr; // Patch in our expr
3392 		pos2.array_texpr = fake;
3393 		res = gnm_expr_eval (texpr->expr, &pos2, flags);
3394 		((GnmExpr *)(fake->expr))->array_corner.expr = NULL;
3395 		gnm_expr_top_unref (fake);
3396 		return res;
3397 	}
3398 }
3399 
3400 
3401 static GSList *
gnm_insert_unique(GSList * list,gpointer data)3402 gnm_insert_unique (GSList *list, gpointer data)
3403 {
3404 	if (g_slist_find (list, data) == NULL)
3405 		return g_slist_prepend (list, data);
3406 	return list;
3407 }
3408 
3409 static GnmExpr const *
cb_referenced_sheets(GnmExpr const * expr,GnmExprWalk * data)3410 cb_referenced_sheets (GnmExpr const *expr, GnmExprWalk *data)
3411 {
3412 	GSList **psheets = data->user;
3413 
3414 	switch (GNM_EXPR_GET_OPER (expr)) {
3415 	case GNM_EXPR_OP_CELLREF:
3416 		*psheets = gnm_insert_unique (*psheets, expr->cellref.ref.sheet);
3417 		break;
3418 
3419 	case GNM_EXPR_OP_CONSTANT: {
3420 		GnmValue const *v = expr->constant.value;
3421 		if (!VALUE_IS_CELLRANGE (v))
3422 			break;
3423 		*psheets = gnm_insert_unique (*psheets, v->v_range.cell.a.sheet);
3424 		/* A NULL b sheet means a's sheet.  Do not insert that.  */
3425 		if (v->v_range.cell.b.sheet)
3426 			*psheets = gnm_insert_unique (*psheets, v->v_range.cell.b.sheet);
3427 		break;
3428 	}
3429 
3430 	default:
3431 		break;
3432 	}
3433 
3434 	return NULL;
3435 }
3436 
3437 /**
3438  * gnm_expr_top_referenced_sheets:
3439  * @texpr:
3440  *
3441  * Generates a list of the sheets referenced by the supplied expression.
3442  * Caller must free the list.  Note, that NULL may occur in the result
3443  * if the expression has a range or cellref without a sheet.
3444  * Returns: (element-type Sheet) (transfer container): the created list.
3445  */
3446 GSList *
gnm_expr_top_referenced_sheets(GnmExprTop const * texpr)3447 gnm_expr_top_referenced_sheets (GnmExprTop const *texpr)
3448 {
3449 	GSList *res = NULL;
3450 
3451 	g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), NULL);
3452 	gnm_expr_walk (texpr->expr, cb_referenced_sheets, &res);
3453 	return res;
3454 }
3455 
3456 gboolean
gnm_expr_top_is_err(GnmExprTop const * texpr,GnmStdError err)3457 gnm_expr_top_is_err (GnmExprTop const *texpr, GnmStdError err)
3458 {
3459 	g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), FALSE);
3460 	return gnm_expr_is_err (texpr->expr, err);
3461 }
3462 
3463 /**
3464  * gnm_expr_top_get_constant:
3465  * @texpr:
3466  *
3467  * If this expression consists of just a constant, return it.
3468  */
3469 GnmValue const *
gnm_expr_top_get_constant(GnmExprTop const * texpr)3470 gnm_expr_top_get_constant (GnmExprTop const *texpr)
3471 {
3472 	g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), NULL);
3473 
3474 	return gnm_expr_get_constant (texpr->expr);
3475 }
3476 
3477 GnmCellRef const *
gnm_expr_top_get_cellref(GnmExprTop const * texpr)3478 gnm_expr_top_get_cellref (GnmExprTop const *texpr)
3479 {
3480 	g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), NULL);
3481 	return gnm_expr_get_cellref (texpr->expr);
3482 }
3483 
3484 static GnmExpr const *
cb_first_funcall(GnmExpr const * expr,GnmExprWalk * data)3485 cb_first_funcall (GnmExpr const *expr, GnmExprWalk *data)
3486 {
3487 	GnmExprConstPtr *user = data->user;
3488 	if (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_FUNCALL) {
3489 		*user = expr;
3490 		data->stop = TRUE;
3491 	}
3492 	return NULL;
3493 }
3494 
3495 /**
3496  * gnm_expr_top_first_funcall:
3497  * @texpr:
3498  *
3499  */
3500 GnmExpr const *
gnm_expr_top_first_funcall(GnmExprTop const * texpr)3501 gnm_expr_top_first_funcall (GnmExprTop const *texpr)
3502 {
3503 	GnmExpr const *res = NULL;
3504 
3505 	g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), NULL);
3506 	gnm_expr_walk (texpr->expr, cb_first_funcall, &res);
3507 	return res;
3508 }
3509 
3510 struct cb_get_boundingbox {
3511 	Sheet const *sheet;
3512 	GnmRange *bound;
3513 };
3514 
3515 static GnmExpr const *
cb_get_boundingbox(GnmExpr const * expr,GnmExprWalk * data)3516 cb_get_boundingbox (GnmExpr const *expr, GnmExprWalk *data)
3517 {
3518 	struct cb_get_boundingbox *args = data->user;
3519 
3520 	switch (GNM_EXPR_GET_OPER (expr)) {
3521 	case GNM_EXPR_OP_CELLREF:
3522 		cellref_boundingbox (&expr->cellref.ref, args->sheet, args->bound);
3523 		break;
3524 
3525 	case GNM_EXPR_OP_CONSTANT: {
3526 		GnmValue const *v = expr->constant.value;
3527 
3528 		if (VALUE_IS_CELLRANGE (v)) {
3529 			cellref_boundingbox (&v->v_range.cell.a, args->sheet, args->bound);
3530 			cellref_boundingbox (&v->v_range.cell.b, args->sheet, args->bound);
3531 		}
3532 		break;
3533 	}
3534 
3535 	default:
3536 		break;
3537 	}
3538 
3539 	return NULL;
3540 }
3541 
3542 /**
3543  * gnm_expr_top_get_boundingbox:
3544  *
3545  * Returns the range of cells in which the expression can be used without going
3546  * out of bounds.
3547  **/
3548 void
gnm_expr_top_get_boundingbox(GnmExprTop const * texpr,Sheet const * sheet,GnmRange * bound)3549 gnm_expr_top_get_boundingbox (GnmExprTop const *texpr, Sheet const *sheet,
3550 			      GnmRange *bound)
3551 {
3552 	struct cb_get_boundingbox args;
3553 
3554 	g_return_if_fail (GNM_IS_EXPR_TOP (texpr));
3555 
3556 	range_init_full_sheet (bound, sheet);
3557 
3558 	args.sheet = sheet;
3559 	args.bound = bound;
3560 	gnm_expr_walk (texpr->expr, cb_get_boundingbox, &args);
3561 }
3562 
3563 gboolean
gnm_expr_top_is_rangeref(GnmExprTop const * texpr)3564 gnm_expr_top_is_rangeref (GnmExprTop const *texpr)
3565 {
3566 	g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), FALSE);
3567 
3568 	return gnm_expr_is_rangeref (texpr->expr);
3569 }
3570 
3571 gboolean
gnm_expr_top_is_array_corner(GnmExprTop const * texpr)3572 gnm_expr_top_is_array_corner (GnmExprTop const *texpr)
3573 {
3574 	g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), FALSE);
3575 	return GNM_EXPR_GET_OPER (texpr->expr) == GNM_EXPR_OP_ARRAY_CORNER;
3576 }
3577 
3578 void
gnm_expr_top_get_array_size(GnmExprTop const * texpr,int * cols,int * rows)3579 gnm_expr_top_get_array_size (GnmExprTop const *texpr, int *cols, int *rows)
3580 {
3581 	g_return_if_fail (GNM_IS_EXPR_TOP (texpr));
3582 	g_return_if_fail (GNM_EXPR_GET_OPER (texpr->expr) == GNM_EXPR_OP_ARRAY_CORNER);
3583 
3584 	if (cols)
3585 		*cols = texpr->expr->array_corner.cols;
3586 	if (rows)
3587 		*rows = texpr->expr->array_corner.rows;
3588 }
3589 
3590 GnmValue *
gnm_expr_top_get_array_value(GnmExprTop const * texpr)3591 gnm_expr_top_get_array_value (GnmExprTop const *texpr)
3592 {
3593 	g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), NULL);
3594 	g_return_val_if_fail (GNM_EXPR_GET_OPER (texpr->expr) == GNM_EXPR_OP_ARRAY_CORNER, NULL);
3595 	return texpr->expr->array_corner.value;
3596 }
3597 
3598 GnmExpr const *
gnm_expr_top_get_array_expr(GnmExprTop const * texpr)3599 gnm_expr_top_get_array_expr (GnmExprTop const *texpr)
3600 {
3601 	g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), NULL);
3602 	g_return_val_if_fail (GNM_EXPR_GET_OPER (texpr->expr) == GNM_EXPR_OP_ARRAY_CORNER, NULL);
3603 	return texpr->expr->array_corner.expr;
3604 }
3605 
3606 gboolean
gnm_expr_top_is_array_elem(GnmExprTop const * texpr,int * x,int * y)3607 gnm_expr_top_is_array_elem (GnmExprTop const *texpr, int *x, int *y)
3608 {
3609 	g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), FALSE);
3610 
3611 	if (GNM_EXPR_GET_OPER (texpr->expr) != GNM_EXPR_OP_ARRAY_ELEM)
3612 		return FALSE;
3613 
3614 	if (x) *x = texpr->expr->array_elem.x;
3615 	if (y) *y = texpr->expr->array_elem.y;
3616 	return TRUE;
3617 }
3618 
3619 gboolean
gnm_expr_top_is_array(GnmExprTop const * texpr)3620 gnm_expr_top_is_array (GnmExprTop const *texpr)
3621 {
3622 	g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), FALSE);
3623 	return gnm_expr_is_array (texpr->expr);
3624 }
3625 
3626 GnmExprTop const *
gnm_expr_top_transpose(GnmExprTop const * texpr)3627 gnm_expr_top_transpose (GnmExprTop const *texpr)
3628 {
3629 	g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), NULL);
3630 	switch (GNM_EXPR_GET_OPER (texpr->expr)) {
3631 	case GNM_EXPR_OP_ARRAY_CORNER:
3632 		/* Transpose size  */
3633 		return gnm_expr_top_new_array_corner
3634 			(texpr->expr->array_corner.rows,
3635 			 texpr->expr->array_corner.cols,
3636 			 gnm_expr_copy (texpr->expr));
3637 	case GNM_EXPR_OP_ARRAY_ELEM:
3638 		/* Transpose coordinates  */
3639 		return gnm_expr_top_new_array_elem
3640 			(texpr->expr->array_elem.y,
3641 			 texpr->expr->array_elem.x);
3642 	default:
3643 		return NULL;
3644 	}
3645 }
3646 
3647 /****************************************************************************/
3648 
3649 #if USE_EXPR_POOLS
3650 typedef union {
3651 	guint32                 oper_and_refcount;
3652 	GnmExprConstant		constant;
3653 	GnmExprFunction		func;
3654 	GnmExprUnary		unary;
3655 	GnmExprBinary		binary;
3656 	GnmExprArrayElem	array_elem;
3657 	GnmExprSet		set;
3658 } GnmExprSmall;
3659 typedef union {
3660 	guint32                 oper_and_refcount;
3661 	GnmExprName		name;
3662 	GnmExprCellRef		cellref;
3663 	GnmExprArrayCorner	array_corner;
3664 } GnmExprBig;
3665 #endif
3666 
3667 /**
3668  * gnm_expr_init_: (skip)
3669  */
3670 void
gnm_expr_init_(void)3671 gnm_expr_init_ (void)
3672 {
3673 #if 0
3674 	GnmExpr e;
3675 
3676 #if USE_EXPR_POOLS
3677 	/* 12 is an excellent size for a pool.  */
3678 	g_print ("sizeof(GnmExprSmall) = %d\n", (int)sizeof (GnmExprSmall));
3679 	g_print ("sizeof(GnmExprBig) = %d\n", (int)sizeof (GnmExprBig));
3680 #endif
3681 	g_print ("sizeof(e.func) = %d\n", (int)sizeof (e.func));
3682 	g_print ("sizeof(e.unary) = %d\n", (int)sizeof (e.unary));
3683 	g_print ("sizeof(e.binary) = %d\n", (int)sizeof (e.binary));
3684 	g_print ("sizeof(e.name) = %d\n", (int)sizeof (e.name));
3685 	g_print ("sizeof(e.cellref) = %d\n", (int)sizeof (e.cellref));
3686 	g_print ("sizeof(e.array_corner) = %d\n", (int)sizeof (e.array_corner));
3687 	g_print ("sizeof(e.array_elem) = %d\n", (int)sizeof (e.array_elem));
3688 	g_print ("sizeof(e.set) = %d\n", (int)sizeof (e.set));
3689 #endif
3690 #if USE_EXPR_POOLS
3691 	expression_pool_small =
3692 		go_mem_chunk_new ("expression pool for small nodes",
3693 				   sizeof (GnmExprSmall),
3694 				   16 * 1024 - 128);
3695 	expression_pool_big =
3696 		go_mem_chunk_new ("expression pool for big nodes",
3697 				   sizeof (GnmExprBig),
3698 				   16 * 1024 - 128);
3699 #endif
3700 }
3701 
3702 #if USE_EXPR_POOLS
3703 static void
cb_expression_pool_leak(gpointer data,G_GNUC_UNUSED gpointer user)3704 cb_expression_pool_leak (gpointer data, G_GNUC_UNUSED gpointer user)
3705 {
3706 	GnmExpr const *expr = data;
3707 	GnmParsePos pp;
3708 	char *s;
3709 
3710 	pp.eval.col = 0;
3711 	pp.eval.row = 0;
3712 	pp.sheet = NULL;
3713 	pp.wb = NULL;
3714 	s = gnm_expr_as_string (expr, &pp, NULL);
3715 	g_printerr ("Leaking expression at %p: %s.\n", (void *)expr, s);
3716 	g_free (s);
3717 }
3718 #endif
3719 
3720 /**
3721  * gnm_expr_shutdown_: (skip)
3722  */
3723 void
gnm_expr_shutdown_(void)3724 gnm_expr_shutdown_ (void)
3725 {
3726 #if USE_EXPR_POOLS
3727 	go_mem_chunk_foreach_leak (expression_pool_small, cb_expression_pool_leak, NULL);
3728 	go_mem_chunk_destroy (expression_pool_small, FALSE);
3729 	expression_pool_small = NULL;
3730 
3731 	go_mem_chunk_foreach_leak (expression_pool_big, cb_expression_pool_leak, NULL);
3732 	go_mem_chunk_destroy (expression_pool_big, FALSE);
3733 	expression_pool_big = NULL;
3734 #endif
3735 }
3736 
3737 /****************************************************************************/
3738