1 /*
2  * func.c: Function management and utility routines.
3  *
4  * Author:
5  *  Miguel de Icaza (miguel@gnu.org)
6  *  Michael Meeks   (mmeeks@gnu.org)
7  *  Morten Welinder (terra@gnome.org)
8  *  Jody Goldberg   (jody@gnome.org)
9  */
10 
11 #include <gnumeric-config.h>
12 #include <glib/gi18n-lib.h>
13 #include <glib/gstdio.h>
14 #include <gnm-i18n.h>
15 #include <gnumeric.h>
16 #include <func.h>
17 
18 #include <parse-util.h>
19 #include <dependent.h>
20 #include <expr.h>
21 #include <expr-impl.h>
22 #include <expr-name.h>
23 #include <cell.h>
24 #include <workbook-priv.h>
25 #include <sheet.h>
26 #include <value.h>
27 #include <number-match.h>
28 #include <func-builtin.h>
29 #include <command-context-stderr.h>
30 #include <gnm-plugin.h>
31 #include <gutils.h>
32 #include <gui-util.h>
33 #include <expr-deriv.h>
34 #include <gnm-marshalers.h>
35 
36 #include <goffice/goffice.h>
37 #include <glib.h>
38 #include <string.h>
39 #include <stdlib.h>
40 
41 enum {
42 	PROP_0,
43 	PROP_NAME,
44 	PROP_TRANSLATION_DOMAIN,
45 	PROP_IN_USE,
46 };
47 
48 enum {
49 	SIG_LOAD_STUB,
50 	SIG_LINK_DEP,
51 	SIG_DERIVATIVE,
52 	LAST_SIGNAL
53 };
54 static guint signals[LAST_SIGNAL] = { 0 };
55 
56 
57 static GList	    *categories;
58 static GnmFuncGroup *unknown_cat;
59 
60 static GHashTable *functions_by_name;
61 static GHashTable *functions_by_localized_name;
62 
63 static GnmFunc    *fn_if;
64 
65 /**
66  * gnm_func_init_: (skip)
67  */
68 void
gnm_func_init_(void)69 gnm_func_init_ (void)
70 {
71 	functions_by_name =
72 		g_hash_table_new (go_ascii_strcase_hash, go_ascii_strcase_equal);
73 
74 	/* FIXME: ascii???  */
75 	functions_by_localized_name =
76 		g_hash_table_new (go_ascii_strcase_hash, go_ascii_strcase_equal);
77 
78 	gnm_func_builtin_init ();
79 
80 	fn_if = gnm_func_lookup ("if", NULL);
81 }
82 
83 /**
84  * gnm_func_shutdown_: (skip)
85  */
86 void
gnm_func_shutdown_(void)87 gnm_func_shutdown_ (void)
88 {
89 	fn_if = NULL;
90 
91 	while (unknown_cat != NULL && unknown_cat->functions != NULL) {
92 		GnmFunc *func = unknown_cat->functions->data;
93 		if (func->usage_count > 0) {
94 			g_warning ("Function %s still has %d users.\n",
95 				   gnm_func_get_name (func, FALSE),
96 				   func->usage_count);
97 			func->usage_count = 0;
98 		}
99 		g_object_unref (func);
100 	}
101 	gnm_func_builtin_shutdown ();
102 
103 	g_hash_table_destroy (functions_by_name);
104 	functions_by_name = NULL;
105 
106 	g_hash_table_destroy (functions_by_localized_name);
107 	functions_by_localized_name = NULL;
108 }
109 
110 /**
111  * gnm_func_enumerate:
112  *
113  * Return value: (element-type GnmFunc) (transfer container):
114  */
115 GPtrArray *
gnm_func_enumerate(void)116 gnm_func_enumerate (void)
117 {
118 	GPtrArray *res = g_ptr_array_new ();
119 	GHashTableIter hiter;
120 	gpointer value;
121 
122 	g_hash_table_iter_init (&hiter, functions_by_name);
123 	while (g_hash_table_iter_next (&hiter, NULL, &value))
124 		g_ptr_array_add (res, value);
125 
126 	return res;
127 }
128 
129 static GnmValue *
error_function_no_full_info(GnmFuncEvalInfo * ei,int argc,GnmExprConstPtr const * argv)130 error_function_no_full_info (GnmFuncEvalInfo *ei,
131 			     int argc,
132 			     GnmExprConstPtr const *argv)
133 {
134 	return value_new_error (ei->pos, _("Function implementation not available."));
135 }
136 
137 static void
gnm_func_load_stub(GnmFunc * func)138 gnm_func_load_stub (GnmFunc *func)
139 {
140 	g_return_if_fail (func->fn_type == GNM_FUNC_TYPE_STUB);
141 
142 	g_signal_emit (G_OBJECT (func), signals[SIG_LOAD_STUB], 0);
143 
144 	if (func->fn_type == GNM_FUNC_TYPE_STUB) {
145 		g_printerr ("Failed to load %s\n", func->name);
146 		gnm_func_set_varargs (func, error_function_no_full_info, NULL);
147 		gnm_func_set_help (func, NULL, 0);
148 	}
149 }
150 
151 inline void
gnm_func_load_if_stub(GnmFunc * func)152 gnm_func_load_if_stub (GnmFunc *func)
153 {
154 	if (func->fn_type == GNM_FUNC_TYPE_STUB)
155 		gnm_func_load_stub (func);
156 }
157 
158 static char *
split_at_colon(char const * s,char ** rest)159 split_at_colon (char const *s, char **rest)
160 {
161 	char *dup = g_strdup (s);
162 	char *colon = strchr (dup, ':');
163 	if (colon) {
164 		*colon = 0;
165 		if (rest) *rest = colon + 1;
166 	} else {
167 		if (rest) *rest = NULL;
168 	}
169 	return dup;
170 }
171 
172 /* ------------------------------------------------------------------------- */
173 
174 static void
gnm_func_group_unref(GnmFuncGroup * fn_group)175 gnm_func_group_unref (GnmFuncGroup *fn_group)
176 {
177 	g_return_if_fail (fn_group != NULL);
178 	g_return_if_fail (fn_group->functions == NULL);
179 
180 	if (fn_group->ref_count-- > 1)
181 		return;
182 
183 	go_string_unref (fn_group->internal_name);
184 	go_string_unref (fn_group->display_name);
185 	g_free (fn_group);
186 }
187 
188 static GnmFuncGroup *
gnm_func_group_ref(GnmFuncGroup * fn_group)189 gnm_func_group_ref (GnmFuncGroup *fn_group)
190 {
191 	fn_group->ref_count++;
192 	return fn_group;
193 }
194 
195 GType
gnm_func_group_get_type(void)196 gnm_func_group_get_type (void)
197 {
198 	static GType t = 0;
199 
200 	if (t == 0) {
201 		t = g_boxed_type_register_static ("GnmFuncGroup",
202 			 (GBoxedCopyFunc)gnm_func_group_ref,
203 			 (GBoxedFreeFunc)gnm_func_group_unref);
204 	}
205 	return t;
206 }
207 
208 static gint
function_category_compare(gconstpointer a,gconstpointer b)209 function_category_compare (gconstpointer a, gconstpointer b)
210 {
211 	GnmFuncGroup const *cat_a = a;
212 	GnmFuncGroup const *cat_b = b;
213 
214 	return go_string_cmp (cat_a->display_name, cat_b->display_name);
215 }
216 
217 GnmFuncGroup *
gnm_func_group_fetch(char const * name,char const * translation)218 gnm_func_group_fetch (char const *name, char const *translation)
219 {
220 	GnmFuncGroup *cat = NULL;
221 	GList *l;
222 
223 	g_return_val_if_fail (name != NULL, NULL);
224 
225 	for (l = categories; l != NULL; l = l->next) {
226 		cat = l->data;
227 		if (strcmp (cat->internal_name->str, name) == 0) {
228 			break;
229 		}
230 	}
231 
232 	if (l == NULL) {
233 		cat = g_new (GnmFuncGroup, 1);
234 		cat->internal_name = go_string_new (name);
235 		cat->ref_count = 1;
236 		if (translation != NULL) {
237 			cat->display_name = go_string_new (translation);
238 			cat->has_translation = TRUE;
239 		} else {
240 			cat->display_name = go_string_new (name);
241 			cat->has_translation = FALSE;
242 		}
243 		cat->functions = NULL;
244 		categories = g_list_insert_sorted (
245 			     categories, cat, &function_category_compare);
246 	} else if (translation != NULL && translation != name &&
247 		   !cat->has_translation) {
248 		go_string_unref (cat->display_name);
249 		cat->display_name = go_string_new (translation);
250 		cat->has_translation = TRUE;
251 		categories = g_list_remove_link (categories, l);
252 		g_list_free_1 (l);
253 		categories = g_list_insert_sorted (
254 			     categories, cat, &function_category_compare);
255 	}
256 
257 	return cat;
258 }
259 
260 GnmFuncGroup *
gnm_func_group_get_nth(int n)261 gnm_func_group_get_nth (int n)
262 {
263 	return g_list_nth_data (categories, n);
264 }
265 
266 static void
gnm_func_group_add_func(GnmFuncGroup * fn_group,GnmFunc * func)267 gnm_func_group_add_func (GnmFuncGroup *fn_group, GnmFunc *func)
268 {
269 	g_return_if_fail (fn_group != NULL);
270 	g_return_if_fail (func != NULL);
271 
272 	fn_group->functions = g_slist_prepend (fn_group->functions, func);
273 }
274 
275 static void
gnm_func_group_remove_func(GnmFuncGroup * fn_group,GnmFunc * func)276 gnm_func_group_remove_func (GnmFuncGroup *fn_group, GnmFunc *func)
277 {
278 	g_return_if_fail (fn_group != NULL);
279 	g_return_if_fail (func != NULL);
280 
281 	fn_group->functions = g_slist_remove (fn_group->functions, func);
282 	if (fn_group->functions == NULL) {
283 		categories = g_list_remove (categories, fn_group);
284 		if (unknown_cat == fn_group)
285 			unknown_cat = NULL;
286 		gnm_func_group_unref (fn_group);
287 	}
288 }
289 
290 /******************************************************************************/
291 
292 static void
gnm_func_create_arg_names(GnmFunc * func)293 gnm_func_create_arg_names (GnmFunc *func)
294 {
295 	int i;
296 	GPtrArray *ptr;
297 
298 	g_return_if_fail (func != NULL);
299 
300 	ptr = g_ptr_array_new ();
301 	for (i = 0; i < func->help_count; i++) {
302 		const char *s;
303 		if (func->help[i].type != GNM_FUNC_HELP_ARG)
304 			continue;
305 
306 		s = gnm_func_gettext (func, func->help[i].text);
307 		g_ptr_array_add (ptr, split_at_colon (s, NULL));
308 	}
309 
310 	func->arg_names = ptr;
311 }
312 
313 gboolean
gnm_func_is_varargs(GnmFunc const * func)314 gnm_func_is_varargs (GnmFunc const *func)
315 {
316 	gnm_func_load_if_stub ((GnmFunc *)func);
317 	return func->fn_type == GNM_FUNC_TYPE_NODES;
318 }
319 
320 gboolean
gnm_func_is_fixargs(GnmFunc const * func)321 gnm_func_is_fixargs (GnmFunc const *func)
322 {
323 	gnm_func_load_if_stub ((GnmFunc *)func);
324 	return func->fn_type == GNM_FUNC_TYPE_ARGS;
325 }
326 
327 void
gnm_func_set_stub(GnmFunc * func)328 gnm_func_set_stub (GnmFunc *func)
329 {
330 	func->fn_type = GNM_FUNC_TYPE_STUB;
331 
332 	g_free (func->arg_spec);
333 	func->arg_spec = NULL;
334 
335 	g_free (func->arg_types);
336 	func->arg_types = NULL;
337 
338 	func->min_args = func->max_args = 0;
339 
340 	func->nodes_func = NULL;
341 	func->args_func = NULL;
342 
343 	gnm_func_set_help (func, NULL, 0);
344 }
345 
346 /**
347  * gnm_func_set_varargs: (skip)
348  * @func: #GnmFunc
349  * @fn: evaluation function
350  * @spec: (nullable): argument type specification
351  */
352 void
gnm_func_set_varargs(GnmFunc * func,GnmFuncNodes fn,const char * spec)353 gnm_func_set_varargs (GnmFunc *func, GnmFuncNodes fn, const char *spec)
354 {
355 	g_return_if_fail (GNM_IS_FUNC (func));
356 	g_return_if_fail (fn != NULL);
357 
358 	gnm_func_set_stub (func); // Clear out stuff
359 
360 	func->fn_type = GNM_FUNC_TYPE_NODES;
361 	func->nodes_func = fn;
362 	func->arg_spec = g_strdup (spec);
363 	func->min_args = 0;
364 	func->max_args = G_MAXINT;
365 
366 	if (spec) {
367 		const char *p = strchr (spec, '|');
368 		const char *q = strchr (spec, '.'); // "..."
369 		if (p) func->min_args = p - spec;
370 		if (!q) func->min_args = strlen (spec) - (p != NULL);
371 	}
372 }
373 
374 /**
375  * gnm_func_set_fixargs: (skip)
376  * @func: #GnmFunc
377  * @fn: evaluation function
378  * @spec: argument type specification
379  */
380 void
gnm_func_set_fixargs(GnmFunc * func,GnmFuncArgs fn,const char * spec)381 gnm_func_set_fixargs (GnmFunc *func, GnmFuncArgs fn, const char *spec)
382 {
383 	char *p;
384 
385 	g_return_if_fail (GNM_IS_FUNC (func));
386 	g_return_if_fail (fn != NULL);
387 	g_return_if_fail (spec != NULL);
388 
389 	gnm_func_set_stub (func); // Clear out stuff
390 
391 	func->fn_type = GNM_FUNC_TYPE_ARGS;
392 	func->args_func = fn;
393 	func->arg_spec = g_strdup (spec);
394 
395 	func->arg_types = g_strdup (func->arg_spec);
396 	p = strchr (func->arg_types, '|');
397 	if (p) {
398 		func->min_args = p - func->arg_types;
399 		memmove (p, p + 1, strlen (p));
400 	} else
401 		func->min_args = strlen (func->arg_types);
402 	func->max_args = strlen (func->arg_types);
403 }
404 
405 /**
406  * gnm_func_get_help:
407  * @func: #GnmFunc
408  * @n: (out) (optional): number of help items, not counting the end item
409  *
410  * Returns: (transfer none) (array length=n) (nullable): @func's help items.
411  */
412 GnmFuncHelp const *
gnm_func_get_help(GnmFunc const * func,int * n)413 gnm_func_get_help (GnmFunc const *func, int *n)
414 {
415 	if (n) *n = 0;
416 
417 	g_return_val_if_fail (GNM_IS_FUNC (func), NULL);
418 	g_return_val_if_fail (func->help, NULL);
419 
420 	if (n) *n = func->help_count;
421 	return func->help;
422 }
423 
424 
425 void
gnm_func_set_help(GnmFunc * func,GnmFuncHelp const * help,int n)426 gnm_func_set_help (GnmFunc *func, GnmFuncHelp const *help, int n)
427 {
428 	g_return_if_fail (GNM_IS_FUNC (func));
429 	g_return_if_fail (n <= 0 || help != NULL);
430 
431 	if (n < 0) {
432 		for (n = 0; help && help[n].type != GNM_FUNC_HELP_END; )
433 			n++;
434 	}
435 
436 	if (func->help) {
437 		int i;
438 		for (i = 0; i <= func->help_count; i++)
439 			g_free ((char *)(func->help[i].text));
440 		g_free (func->help);
441 		func->help = NULL;
442 	}
443 
444 	if (func->arg_names) {
445 		g_ptr_array_foreach (func->arg_names, (GFunc)g_free, NULL);
446 		g_ptr_array_free (func->arg_names, TRUE);
447 		func->arg_names = NULL;
448 	}
449 
450 	if (help) {
451 		int i;
452 
453 		func->help = g_new (GnmFuncHelp, n + 1);
454 		for (i = 0; i < n; i++) {
455 			func->help[i].type = help[i].type;
456 			func->help[i].text = g_strdup (help[i].text);
457 		}
458 		func->help[n].type = GNM_FUNC_HELP_END;
459 		func->help[n].text = NULL;
460 
461 		func->help_count = n;
462 		gnm_func_create_arg_names (func);
463 	} else {
464 		func->help_count = 0;
465 	}
466 }
467 
468 
469 static void
gnm_func_set_localized_name(GnmFunc * fd,const char * lname)470 gnm_func_set_localized_name (GnmFunc *fd, const char *lname)
471 {
472 	gboolean in_hashes = !(fd->flags & GNM_FUNC_IS_WORKBOOK_LOCAL);
473 
474 	if (g_strcmp0 (fd->localized_name, lname) == 0)
475 		return;
476 
477 	if (in_hashes && fd->localized_name)
478 		g_hash_table_remove (functions_by_localized_name, fd->localized_name);
479 	g_free (fd->localized_name);
480 
481 	fd->localized_name = g_strdup (lname);
482 	if (in_hashes && lname)
483 		g_hash_table_insert (functions_by_localized_name,
484 				     fd->localized_name, fd);
485 }
486 
487 /**
488  * gnm_func_inc_usage:
489  * @func: #GnmFunc
490  *
491  * This function increments the usage count of @func.  A non-zero usage count
492  * prevents the unloading of the function.
493  *
494  * Returns: (transfer full): a new reference to @func.
495  */
496 GnmFunc *
gnm_func_inc_usage(GnmFunc * func)497 gnm_func_inc_usage (GnmFunc *func)
498 {
499 	g_return_val_if_fail (func != NULL, NULL);
500 
501 	func->usage_count++;
502 	if (func->usage_count == 1)
503 		g_object_notify (G_OBJECT (func), "in-use");
504 	return func;
505 }
506 
507 /**
508  * gnm_func_dec_usage:
509  * @func: (transfer full): #GnmFunc
510  *
511  * This function decrements the usage count of @func.  When the usage count
512  * reaches zero, the function may be unloaded, for example by unloading the
513  * plugin that defines it.
514  */
515 void
gnm_func_dec_usage(GnmFunc * func)516 gnm_func_dec_usage (GnmFunc *func)
517 {
518 	g_return_if_fail (func != NULL);
519 	g_return_if_fail (func->usage_count > 0);
520 
521 	func->usage_count--;
522 	if (func->usage_count == 0)
523 		g_object_notify (G_OBJECT (func), "in-use");
524 }
525 
526 gboolean
gnm_func_get_in_use(GnmFunc * func)527 gnm_func_get_in_use (GnmFunc *func)
528 {
529 	g_return_val_if_fail (func != NULL, FALSE);
530 
531 	return func->usage_count > 0;
532 }
533 
534 
535 /**
536  * gnm_func_lookup:
537  * @name: name of function
538  * @scope: (nullable): scope of function, %NULL for global
539  *
540  * Returns: (nullable) (transfer none): the function of that name.
541  */
542 GnmFunc *
gnm_func_lookup(char const * name,Workbook * scope)543 gnm_func_lookup (char const *name, Workbook *scope)
544 {
545 	GnmFunc *fd = g_hash_table_lookup (functions_by_name, name);
546 	if (fd != NULL)
547 		return fd;
548 	if (scope == NULL || scope->sheet_local_functions == NULL)
549 		return NULL;
550 	return g_hash_table_lookup (scope->sheet_local_functions, (gpointer)name);
551 }
552 
553 /**
554  * gnm_func_lookup_localized:
555  * @name: localized name of function
556  * @scope: (nullable): scope of function, %NULL for global
557  *
558  * Returns: (nullable) (transfer none): the function of that name.
559  */
560 GnmFunc *
gnm_func_lookup_localized(char const * name,Workbook * scope)561 gnm_func_lookup_localized (char const *name, Workbook *scope)
562 {
563 	GnmFunc *fd;
564 	GHashTableIter hiter;
565 	gpointer value;
566 
567 	/* Must localize all function names.  */
568 	g_hash_table_iter_init (&hiter, functions_by_name);
569 	while (g_hash_table_iter_next (&hiter, NULL, &value)) {
570 		GnmFunc *fd = value;
571 		(void)gnm_func_get_name (fd, TRUE);
572 	}
573 
574 	fd = g_hash_table_lookup (functions_by_localized_name, name);
575 	if (fd != NULL)
576 		return fd;
577 	if (scope == NULL || scope->sheet_local_functions == NULL)
578 		return NULL;
579 	return g_hash_table_lookup (scope->sheet_local_functions, (gpointer)name);
580 }
581 
582 /**
583  * gnm_func_lookup_prefix:
584  * @prefix: prefix to search for
585  * @scope:
586  * @trans: whether to search translated function names
587  *
588  * Returns: (element-type GnmFunc*) (transfer full): A list of functions
589  * whose names start with @prefix.
590  **/
591 GSList *
gnm_func_lookup_prefix(char const * prefix,Workbook * scope,gboolean trans)592 gnm_func_lookup_prefix (char const *prefix, Workbook *scope, gboolean trans)
593 {
594 	GSList *res = NULL;
595 	GHashTableIter hiter;
596 	gpointer value;
597 
598 	/*
599 	 * Always iterate over functions_by_name as the localized name
600 	 * might not be set yet.
601 	 */
602 	g_hash_table_iter_init (&hiter, functions_by_name);
603 	while (g_hash_table_iter_next (&hiter, NULL, &value)) {
604 		GnmFunc *fd = value;
605 		if (!(fd->flags & (GNM_FUNC_IS_PLACEHOLDER | GNM_FUNC_INTERNAL))) {
606 			const char *name = gnm_func_get_name (fd, trans);
607 			if (g_str_has_prefix (name, prefix)) {
608 				gnm_func_inc_usage (fd);
609 				res = g_slist_prepend (res, fd);
610 			}
611 		}
612 	}
613 
614 	return res;
615 }
616 
617 /**
618  * gnm_func_get_translation_domain:
619  * @func: #GnmFunc
620  *
621  * Returns: (transfer none): the translation domain for @func's help text.
622  */
623 char const *
gnm_func_get_translation_domain(GnmFunc const * func)624 gnm_func_get_translation_domain (GnmFunc const *func)
625 {
626 	g_return_val_if_fail (GNM_IS_FUNC (func), NULL);
627 	return func->tdomain->str;
628 }
629 
630 /**
631  * gnm_func_set_translation_domain:
632  * @func: #GnmFunc
633  * @tdomain: (nullable): Translation domain, %NULL for Gnumeric's.
634  */
635 void
gnm_func_set_translation_domain(GnmFunc * func,const char * tdomain)636 gnm_func_set_translation_domain (GnmFunc *func, const char *tdomain)
637 {
638 	g_return_if_fail (GNM_IS_FUNC (func));
639 
640 	if (!tdomain)
641 		tdomain = GETTEXT_PACKAGE;
642 
643 	if (g_strcmp0 (func->tdomain->str, tdomain) == 0)
644 		return;
645 
646 	go_string_unref (func->tdomain);
647 	func->tdomain = go_string_new (tdomain);
648 
649 	g_object_notify (G_OBJECT (func), "translation-domain");
650 }
651 
652 /**
653  * gnm_func_gettext:
654  * @func: #GnmFunc
655  * @str: string to translate
656  *
657  * Returns: (transfer none): @str translated in @func's translation
658  * domain.
659  */
660 char const *
gnm_func_gettext(GnmFunc const * func,const char * str)661 gnm_func_gettext (GnmFunc const *func, const char *str)
662 {
663 	g_return_val_if_fail (GNM_IS_FUNC (func), NULL);
664 	g_return_val_if_fail (str != NULL, NULL);
665 
666 	return dgettext (func->tdomain->str, str);
667 }
668 
669 
670 GnmFuncFlags
gnm_func_get_flags(GnmFunc const * func)671 gnm_func_get_flags (GnmFunc const *func)
672 {
673 	g_return_val_if_fail (GNM_IS_FUNC (func), GNM_FUNC_SIMPLE);
674 	return func->flags;
675 }
676 
677 void
gnm_func_set_flags(GnmFunc * func,GnmFuncFlags f)678 gnm_func_set_flags (GnmFunc *func, GnmFuncFlags f)
679 {
680 	g_return_if_fail (GNM_IS_FUNC (func));
681 	func->flags = f;
682 }
683 
684 GnmFuncImplStatus
gnm_func_get_impl_status(GnmFunc const * func)685 gnm_func_get_impl_status (GnmFunc const *func)
686 {
687 	g_return_val_if_fail (GNM_IS_FUNC (func), GNM_FUNC_IMPL_STATUS_UNIMPLEMENTED);
688 	return func->impl_status;
689 }
690 
691 void
gnm_func_set_impl_status(GnmFunc * func,GnmFuncImplStatus st)692 gnm_func_set_impl_status (GnmFunc *func, GnmFuncImplStatus st)
693 {
694 	g_return_if_fail (GNM_IS_FUNC (func));
695 	func->impl_status = st;
696 }
697 
698 
699 GnmFuncTestStatus
gnm_func_get_test_status(GnmFunc const * func)700 gnm_func_get_test_status (GnmFunc const *func)
701 {
702 	g_return_val_if_fail (GNM_IS_FUNC (func), GNM_FUNC_TEST_STATUS_UNKNOWN);
703 	return func->test_status;
704 }
705 
706 void
gnm_func_set_test_status(GnmFunc * func,GnmFuncTestStatus st)707 gnm_func_set_test_status (GnmFunc *func, GnmFuncTestStatus st)
708 {
709 	g_return_if_fail (GNM_IS_FUNC (func));
710 	func->test_status = st;
711 }
712 
713 
714 /**
715  * gnm_func_get_function_group:
716  * @func: #GnmFunc
717  *
718  * Returns: (transfer none): the function group to which @func belongs.
719  */
720 GnmFuncGroup *
gnm_func_get_function_group(GnmFunc * func)721 gnm_func_get_function_group (GnmFunc *func)
722 {
723 	g_return_val_if_fail (GNM_IS_FUNC (func), NULL);
724 	return func->fn_group;
725 }
726 
727 
728 void
gnm_func_set_function_group(GnmFunc * func,GnmFuncGroup * group)729 gnm_func_set_function_group (GnmFunc *func, GnmFuncGroup *group)
730 {
731 	g_return_if_fail (GNM_IS_FUNC (func));
732 	g_return_if_fail (group != NULL);
733 
734 	if (func->fn_group == group)
735 		return;
736 
737 	if (func->fn_group)
738 		gnm_func_group_remove_func (func->fn_group, func);
739 	func->fn_group = group;
740 	gnm_func_group_add_func (group, func);
741 
742 	if (group == unknown_cat)
743 		func->flags |= GNM_FUNC_IS_PLACEHOLDER;
744 	else
745 		func->flags &= ~GNM_FUNC_IS_PLACEHOLDER;
746 }
747 
748 void
gnm_func_set_from_desc(GnmFunc * func,GnmFuncDescriptor const * desc)749 gnm_func_set_from_desc (GnmFunc *func, GnmFuncDescriptor const *desc)
750 {
751 	//static char const valid_tokens[] = "fsbraAES?|";
752 
753 	g_return_if_fail (GNM_IS_FUNC (func));
754 	g_return_if_fail (desc != NULL);
755 
756 	// Not setting name, localized_name.  Also not setting things not present
757 	// in desc, such as translation domain.
758 
759 	if (desc->fn_args != NULL) {
760 		gnm_func_set_fixargs (func, desc->fn_args, desc->arg_spec);
761 	} else if (desc->fn_nodes != NULL) {
762 		gnm_func_set_varargs (func, desc->fn_nodes, desc->arg_spec);
763 	} else {
764 		gnm_func_set_stub (func);
765 		return;
766 	}
767 
768 	gnm_func_set_help (func, desc->help, -1);
769 	func->flags		= desc->flags;
770 	func->impl_status	= desc->impl_status;
771 	func->test_status	= desc->test_status;
772 }
773 
774 
775 /**
776  * gnm_func_add:
777  * @group:
778  * @descriptor:
779  * @tdomain: (nullable):
780  *
781  * Returns: (transfer full): a new #GnmFunc.
782  */
783 GnmFunc *
gnm_func_add(GnmFuncGroup * fn_group,GnmFuncDescriptor const * desc,const char * tdomain)784 gnm_func_add (GnmFuncGroup *fn_group,
785 	      GnmFuncDescriptor const *desc,
786 	      const char *tdomain)
787 {
788 	GnmFunc *func;
789 
790 	g_return_val_if_fail (fn_group != NULL, NULL);
791 	g_return_val_if_fail (desc != NULL, NULL);
792 
793 	func = g_object_new (GNM_FUNC_TYPE,
794 			     "name", desc->name,
795 			     NULL);
796 	gnm_func_set_translation_domain (func, tdomain);
797 
798 	gnm_func_set_from_desc (func, desc);
799 
800 	if (func->fn_type == GNM_FUNC_TYPE_STUB) {
801 		g_warning ("Invalid function has neither args nor nodes handler");
802 		g_object_unref (func);
803 		return NULL;
804 	}
805 
806 	gnm_func_set_function_group (func, fn_group);
807 
808 	if (!(func->flags & GNM_FUNC_IS_WORKBOOK_LOCAL))
809 		g_hash_table_insert (functions_by_name,
810 				     (gpointer)(func->name), func);
811 
812 	return func;
813 }
814 
815 /* Handle unknown functions on import without losing their names */
816 static GnmValue *
unknownFunctionHandler(GnmFuncEvalInfo * ei,G_GNUC_UNUSED int argc,G_GNUC_UNUSED GnmExprConstPtr const * argv)817 unknownFunctionHandler (GnmFuncEvalInfo *ei,
818 			G_GNUC_UNUSED int argc,
819 			G_GNUC_UNUSED GnmExprConstPtr const *argv)
820 {
821 	return value_new_error_NAME (ei->pos);
822 }
823 
824 static char *
invent_name(const char * pref,GHashTable * h,const char * template)825 invent_name (const char *pref, GHashTable *h, const char *template)
826 {
827 	static int count = 0;
828 	char *name = g_utf8_strdown (pref, -1);
829 
830 	while (g_hash_table_lookup (h, name)) {
831 		count++;
832 		g_free (name);
833 		name = g_strdup_printf (template, count);
834 	}
835 
836 	return name;
837 }
838 
839 static GnmFunc *
gnm_func_add_placeholder_full(Workbook * scope,char const * gname,char const * lname,char const * type)840 gnm_func_add_placeholder_full (Workbook *scope,
841 			       char const *gname, char const *lname,
842 			       char const *type)
843 {
844 	GnmFuncDescriptor desc;
845 	GnmFunc *func;
846 	char const *unknown_cat_name = N_("Unknown Function");
847 	gboolean copy_gname = TRUE;
848 	gboolean copy_lname = TRUE;
849 
850 	g_return_val_if_fail (gname || lname, NULL);
851 	g_return_val_if_fail (gname == NULL || gnm_func_lookup (gname, scope) == NULL, NULL);
852 	g_return_val_if_fail (lname == NULL || gnm_func_lookup_localized (lname, scope) == NULL, NULL);
853 
854 	if (!unknown_cat)
855 		unknown_cat = gnm_func_group_fetch
856 			(unknown_cat_name, _(unknown_cat_name));
857 
858 	if (!gname) {
859 		/*
860 		 * This is actually a bit of a problem if we don't end up
861 		 * with a copy of lname (because there already is a function
862 		 * with that name).  We're likely to save a template name,
863 		 * but I don't see what else to do.
864 		 */
865 		gname = invent_name (lname, functions_by_name, "unknown%d");
866 		copy_gname = FALSE;
867 	}
868 	if (!lname) {
869 		/* xgettext: This represents a made-up translated function name.  */
870 		lname = invent_name (gname, functions_by_localized_name, _("unknown%d"));
871 		copy_lname = FALSE;
872 	}
873 
874 	if (gnm_debug_flag ("func"))
875 		g_printerr ("Adding placeholder for %s (aka %s)\n", gname, lname);
876 
877 	memset (&desc, 0, sizeof (GnmFuncDescriptor));
878 	desc.name	  = gname;
879 	desc.arg_spec	  = NULL;
880 	desc.help	  = NULL;
881 	desc.fn_args	  = NULL;
882 	desc.fn_nodes	  = &unknownFunctionHandler;
883 	desc.flags	  = GNM_FUNC_IS_PLACEHOLDER;
884 	desc.impl_status  = GNM_FUNC_IMPL_STATUS_EXISTS;
885 	desc.test_status  = GNM_FUNC_TEST_STATUS_UNKNOWN;
886 
887 	if (scope != NULL)
888 		desc.flags |= GNM_FUNC_IS_WORKBOOK_LOCAL;
889 	else {
890 #if 0
891 		/* WISHLIST : it would be nice to have a log if these. */
892 		g_warning ("Unknown %s function : %s", type, desc.name);
893 #endif
894 	}
895 
896 	func = gnm_func_add (unknown_cat, &desc, NULL);
897 
898 	if (lname) {
899 		gnm_func_set_localized_name (func, lname);
900 		if (!copy_lname)
901 			g_free ((char *)lname);
902 	}
903 
904 	if (!copy_gname)
905 		g_free ((char *)gname);
906 
907 	if (scope != NULL) {
908 		if (scope->sheet_local_functions == NULL)
909 			scope->sheet_local_functions = g_hash_table_new_full (
910 				g_str_hash, g_str_equal,
911 				NULL, g_object_unref);
912 		g_hash_table_insert (scope->sheet_local_functions,
913 			(gpointer)func->name, func);
914 	}
915 
916 	return func;
917 }
918 
919 /**
920  * gnm_func_add_placeholder:
921  * @scope: (nullable): scope to defined placeholder, %NULL for global
922  * @name: (nullable): function name
923  * @type:
924  *
925  * Returns: (transfer none): a placeholder with the given name.
926  */
927 GnmFunc *
gnm_func_add_placeholder(Workbook * scope,char const * name,char const * type)928 gnm_func_add_placeholder (Workbook *scope,
929 			  char const *name, char const *type)
930 {
931 	return gnm_func_add_placeholder_full (scope, name, NULL, type);
932 }
933 
934 /**
935  * gnm_func_add_placeholder_localized:
936  * @gname: (nullable): function name
937  * @lname: localized function name
938  *
939  * Returns: (transfer none): a placeholder with the given localized name.
940  */
941 GnmFunc *
gnm_func_add_placeholder_localized(char const * gname,char const * lname)942 gnm_func_add_placeholder_localized (char const *gname, char const *lname)
943 {
944 	return gnm_func_add_placeholder_full (NULL, gname, lname, "?");
945 }
946 
947 /**
948  * gnm_func_lookup_or_add_placeholder:
949  * @name: function name
950  *
951  * Returns: (transfer none): a #GnmFunc named @name, either an existing
952  * one or a placeholder.
953  */
954 GnmFunc	*
gnm_func_lookup_or_add_placeholder(char const * name)955 gnm_func_lookup_or_add_placeholder (char const *name)
956 {
957 	GnmFunc	* f = gnm_func_lookup (name, NULL);
958 	if (f == NULL)
959 		f = gnm_func_add_placeholder (NULL, name, "");
960 	return f;
961 }
962 
963 /**
964  * gnm_func_get_name:
965  * @func: #GnmFunc to query
966  * @localized: if %TRUE, use localized name
967  *
968  * Returns: (transfer none): @func's name
969  */
970 char const *
gnm_func_get_name(GnmFunc const * func,gboolean localized)971 gnm_func_get_name (GnmFunc const *func, gboolean localized)
972 {
973 	int i;
974 	GnmFunc *fd = (GnmFunc *)func;
975 
976 	g_return_val_if_fail (func != NULL, NULL);
977 
978 	if (!localized)
979 		return func->name;
980 
981 	if (func->localized_name)
982 		return func->localized_name;
983 
984 	/*
985 	 * Deduce the translated names from the help texts.  This
986 	 * code doesn't currently check for clashes in translated
987 	 * names.
988 	 */
989 
990 	gnm_func_load_if_stub (fd);
991 
992 	for (i = 0; func->localized_name == NULL && i < func->help_count; i++) {
993 		const char *s, *sl;
994 		char *U;
995 		if (func->help[i].type != GNM_FUNC_HELP_NAME)
996 			continue;
997 
998 		s = func->help[i].text;
999 		sl = gnm_func_gettext (fd, s);
1000 		if (s == sl) /* String not actually translated. */
1001 			continue;
1002 
1003 		U = split_at_colon (sl, NULL);
1004 		if (U) {
1005 			char *lname = g_utf8_strdown (U, -1);
1006 			gnm_func_set_localized_name (fd, lname);
1007 			g_free (lname);
1008 		}
1009 		g_free (U);
1010 	}
1011 
1012 	if (!func->localized_name)
1013 		gnm_func_set_localized_name (fd, fd->name);
1014 
1015 	return func->localized_name;
1016 }
1017 
1018 /**
1019  * gnm_func_get_description:
1020  * @func: #GnmFunc
1021  *
1022  * Returns: (transfer none): the description of the function
1023  **/
1024 char const *
gnm_func_get_description(GnmFunc const * func)1025 gnm_func_get_description (GnmFunc const *func)
1026 {
1027 	gint i;
1028 	g_return_val_if_fail (func != NULL, NULL);
1029 
1030 	gnm_func_load_if_stub ((GnmFunc *)func);
1031 
1032 	for (i = 0; i < func->help_count; i++) {
1033 		const char *desc;
1034 
1035 		if (func->help[i].type != GNM_FUNC_HELP_NAME)
1036 			continue;
1037 
1038 		desc = strchr (gnm_func_gettext (func, func->help[i].text), ':');
1039 		return desc ? (desc + 1) : "";
1040 	}
1041 	return "";
1042 }
1043 
1044 /**
1045  * gnm_func_count_args:
1046  * @func: pointer to function definition
1047  * @min: (out): location for minimum args
1048  * @max: (out): location for maximum args
1049  *
1050  * This calculates the maximum and minimum number of args that can be passed.
1051  * For a vararg function, the maximum will be set to G_MAXINT.
1052  **/
1053 void
gnm_func_count_args(GnmFunc const * func,int * min,int * max)1054 gnm_func_count_args (GnmFunc const *func, int *min, int *max)
1055 {
1056 	g_return_if_fail (min != NULL);
1057 	g_return_if_fail (max != NULL);
1058 	g_return_if_fail (func != NULL);
1059 
1060 	gnm_func_load_if_stub ((GnmFunc *)func);
1061 
1062 	*min = func->min_args;
1063 	*max = func->max_args;
1064 }
1065 
1066 /**
1067  * gnm_func_get_arg_type:
1068  * @func: the fn defintion
1069  * @arg_idx: zero-based argument offset
1070  *
1071  * Returns: the type of the argument
1072  **/
1073 char
gnm_func_get_arg_type(GnmFunc const * func,int arg_idx)1074 gnm_func_get_arg_type (GnmFunc const *func, int arg_idx)
1075 {
1076 	g_return_val_if_fail (func != NULL, '?');
1077 
1078 	gnm_func_load_if_stub ((GnmFunc *)func);
1079 
1080 	g_return_val_if_fail (arg_idx >= 0 && arg_idx < func->max_args, '?');
1081 
1082 	return func->arg_types ? func->arg_types[arg_idx] : '?';
1083 }
1084 
1085 /**
1086  * gnm_func_get_arg_type_string:
1087  * @func: the fn defintion
1088  * @arg_idx: zero-based argument offset
1089  *
1090  * Return value: (transfer none): the type of the argument as a string
1091  **/
1092 char const *
gnm_func_get_arg_type_string(GnmFunc const * func,int arg_idx)1093 gnm_func_get_arg_type_string (GnmFunc const *func, int arg_idx)
1094 {
1095 	switch (gnm_func_get_arg_type (func, arg_idx)) {
1096 	case 'f':
1097 		return _("Number");
1098 	case 's':
1099 		return _("String");
1100 	case 'b':
1101 		return _("Boolean");
1102 	case 'r':
1103 		return _("Cell Range");
1104 	case 'A':
1105 		return _("Area");
1106 	case 'E':
1107 		return _("Scalar, Blank, or Error");
1108 	case 'S':
1109 		return _("Scalar");
1110 	case '?':
1111 		/* Missing values will be NULL.  */
1112 		return _("Any");
1113 
1114 	default:
1115 		g_warning ("Unknown arg type");
1116 		return "Broken";
1117 	}
1118 }
1119 
1120 /**
1121  * gnm_func_get_arg_name:
1122  * @func: #GnmFunc
1123  * @arg_idx: zero-based argument offset
1124  *
1125  * Returns: (transfer full) (nullable): the name of the argument
1126  **/
1127 char *
gnm_func_get_arg_name(GnmFunc const * func,guint arg_idx)1128 gnm_func_get_arg_name (GnmFunc const *func, guint arg_idx)
1129 {
1130 	g_return_val_if_fail (func != NULL, NULL);
1131 
1132 	gnm_func_load_if_stub ((GnmFunc *)func);
1133 
1134 	if (func->arg_names && arg_idx < func->arg_names->len)
1135 		return g_strdup (g_ptr_array_index (func->arg_names, arg_idx));
1136 	return NULL;
1137 }
1138 
1139 /**
1140  * gnm_func_get_arg_description:
1141  * @func: the fn defintion
1142  * @arg_idx: zero-based argument offset
1143  *
1144  * Returns: (transfer none): the description of the argument
1145  **/
1146 char const *
gnm_func_get_arg_description(GnmFunc const * func,guint arg_idx)1147 gnm_func_get_arg_description (GnmFunc const *func, guint arg_idx)
1148 {
1149 	gint i;
1150 	g_return_val_if_fail (func != NULL, NULL);
1151 
1152 	gnm_func_load_if_stub ((GnmFunc *)func);
1153 
1154 	for (i = 0; i < func->help_count; i++) {
1155 		gchar const *desc;
1156 
1157 		if (func->help[i].type != GNM_FUNC_HELP_ARG)
1158 			continue;
1159 		if (arg_idx--)
1160 			continue;
1161 
1162 		desc = strchr (gnm_func_gettext (func, func->help[i].text), ':');
1163 		if (!desc)
1164 			return "";
1165 
1166 		desc++;
1167 		while (g_unichar_isspace (g_utf8_get_char (desc)))
1168 			desc = g_utf8_next_char (desc);
1169 		return desc;
1170 	}
1171 
1172 	return "";
1173 }
1174 
1175 /**
1176  * gnm_func_convert_markup_to_pango:
1177  * @desc: the fn or arg description string
1178  * @target: target widget for the markup.
1179  *
1180  * Return value: the escaped string with @{} markup converted to
1181  *               pango markup
1182  **/
1183 char *
gnm_func_convert_markup_to_pango(char const * desc,GtkWidget * target)1184 gnm_func_convert_markup_to_pango (char const *desc, GtkWidget *target)
1185 {
1186 	GString *str;
1187 	gchar *markup, *at;
1188 	GdkRGBA link_color;
1189 	PangoColor pg;
1190 	char *link_color_text, *span_text;
1191 	size_t span_text_len;
1192 
1193 	gnm_get_link_color (target, &link_color);
1194 	pg.red = 65535 * link_color.red;
1195 	pg.green = 65535 * link_color.green;
1196 	pg.blue = 65535 * link_color.blue;
1197 	link_color_text = pango_color_to_string (&pg);
1198 	span_text = g_strdup_printf ("<span foreground=\"%s\">",
1199 				     link_color_text);
1200 	span_text_len = strlen (span_text);
1201 	g_free (link_color_text);
1202 
1203 	markup = g_markup_escape_text (desc, -1);
1204 	str = g_string_new (markup);
1205 	g_free (markup);
1206 
1207 	while ((at = strstr (str->str, "@{"))) {
1208 		gint len = at - str->str;
1209 		go_string_replace (str, len, 2, span_text, -1);
1210 		if ((at = strstr
1211 		     (str->str + len + span_text_len, "}"))) {
1212 			len = at - str->str;
1213 			go_string_replace (str, len, 1, "</span>", -1);
1214 		} else
1215 			g_string_append (str, "</span>");
1216 	}
1217 	g_free (span_text);
1218 
1219 	return g_string_free (str, FALSE);
1220 }
1221 
1222 
1223 /* ------------------------------------------------------------------------- */
1224 
1225 static inline void
free_values(GnmValue ** values,int top)1226 free_values (GnmValue **values, int top)
1227 {
1228 	int i;
1229 
1230 	for (i = 0; i < top; i++)
1231 		if (values [i])
1232 			value_release (values [i]);
1233 }
1234 
1235 /* ------------------------------------------------------------------------- */
1236 
1237 /**
1238  * function_call_with_exprs:
1239  * @ei: EvalInfo containing valid fn_def!
1240  *
1241  * Do the guts of calling a function.
1242  *
1243  * Returns the result.
1244  **/
1245 GnmValue *
function_call_with_exprs(GnmFuncEvalInfo * ei)1246 function_call_with_exprs (GnmFuncEvalInfo *ei)
1247 {
1248 	GnmFunc const *fn_def;
1249 	int	  i, iter_count, iter_width = 0, iter_height = 0;
1250 	char	  arg_type;
1251 	GnmValue	 **args, *tmp = NULL;
1252 	int	 *iter_item = NULL;
1253 	int argc;
1254 	GnmExprConstPtr *argv;
1255 	GnmExprEvalFlags flags, pass_flags;
1256 
1257 	g_return_val_if_fail (ei != NULL, NULL);
1258 	g_return_val_if_fail (ei->func_call != NULL, NULL);
1259 
1260 	flags = ei->flags;
1261 
1262 	argc = ei->func_call->argc;
1263 	argv = ei->func_call->argv;
1264 	fn_def = ei->func_call->func;
1265 
1266 	gnm_func_load_if_stub ((GnmFunc *)fn_def);
1267 
1268 	/* Functions that deal with ExprNodes */
1269 	if (fn_def->fn_type == GNM_FUNC_TYPE_NODES)
1270 		return fn_def->nodes_func (ei, argc, argv);
1271 
1272 	/* Functions that take pre-computed Values */
1273 	if (argc > fn_def->max_args ||
1274 	    argc < fn_def->min_args)
1275 		return value_new_error_NA (ei->pos);
1276 
1277 	args = g_alloca (sizeof (GnmValue *) * fn_def->max_args);
1278 	iter_count = (eval_pos_is_array_context (ei->pos) &&
1279 		      (flags & GNM_EXPR_EVAL_PERMIT_NON_SCALAR))
1280 		? 0 : -1;
1281 
1282 	/* Optimization for IF when implicit iteration is not used.  */
1283 	if (ei->func_call->func == fn_if && iter_count == -1)
1284 		return gnumeric_if2 (ei, argc, argv, flags);
1285 
1286 	pass_flags = (flags & 0); // Nothing right now.
1287 
1288 	for (i = 0; i < argc; i++) {
1289 		char arg_type = fn_def->arg_types[i];
1290 		/* expr is always non-null, missing args are encoded as
1291 		 * const = empty */
1292 		GnmExpr const *expr = argv[i];
1293 
1294 		if (arg_type == 'A' || arg_type == 'r') {
1295 			tmp = args[i] = gnm_expr_eval
1296 				(expr, ei->pos,
1297 				 pass_flags |
1298 				 GNM_EXPR_EVAL_PERMIT_NON_SCALAR |
1299 				 GNM_EXPR_EVAL_WANT_REF);
1300 			if (VALUE_IS_ERROR (tmp)) {
1301 				free_values (args, i);
1302 				return tmp;
1303 			}
1304 
1305 			if (VALUE_IS_CELLRANGE (tmp)) {
1306 				gnm_cellref_make_abs (&tmp->v_range.cell.a,
1307 						      &tmp->v_range.cell.a,
1308 						      ei->pos);
1309 				gnm_cellref_make_abs (&tmp->v_range.cell.b,
1310 						      &tmp->v_range.cell.b,
1311 						      ei->pos);
1312 				/* Array args accept scalars */
1313 			} else if (arg_type != 'A' && !VALUE_IS_ARRAY (tmp)) {
1314 				free_values (args, i + 1);
1315 				return value_new_error_VALUE (ei->pos);
1316 			}
1317 			continue;
1318 		}
1319 
1320 		/* force scalars whenever we are certain */
1321 		tmp = args[i] = gnm_expr_eval
1322 			(expr, ei->pos,
1323 			 pass_flags |
1324 			 GNM_EXPR_EVAL_PERMIT_EMPTY |
1325 			 (iter_count >= 0 || arg_type == '?'
1326 			  ? GNM_EXPR_EVAL_PERMIT_NON_SCALAR
1327 			  : 0));
1328 
1329 		if (arg_type == '?')	/* '?' arguments are unrestriced */
1330 			continue;
1331 
1332 		/* optional arguments can be blank */
1333 		if (i >= fn_def->min_args && VALUE_IS_EMPTY (tmp)) {
1334 			if (arg_type == 'E' && !gnm_expr_is_empty (expr)) {
1335 				/* An actual argument produced empty.  Make
1336 				   sure function sees that.  */
1337 				args[i] = value_new_empty ();
1338 			}
1339 
1340 			continue;
1341 		}
1342 
1343 		if (tmp == NULL)
1344 			tmp = args[i] = value_new_empty ();
1345 
1346 		/* Handle implicit intersection or iteration depending on flags */
1347 		if (VALUE_IS_CELLRANGE (tmp) || VALUE_IS_ARRAY (tmp)) {
1348 			if (iter_count > 0) {
1349 				if (iter_width != value_area_get_width (tmp, ei->pos) ||
1350 				    iter_height != value_area_get_height (tmp, ei->pos)) {
1351 					free_values (args, i + 1);
1352 					return value_new_error_VALUE (ei->pos);
1353 				}
1354 			} else {
1355 				if (iter_count < 0) {
1356 					g_warning ("Damn I thought this was impossible");
1357 					iter_count = 0;
1358 				}
1359 				iter_item = g_alloca (sizeof (int) * argc);
1360 				iter_width = value_area_get_width (tmp, ei->pos);
1361 				iter_height = value_area_get_height (tmp, ei->pos);
1362 			}
1363 			iter_item [iter_count++] = i;
1364 
1365 			/* no need to check type, we would fail comparing a range against a "b, f, or s" */
1366 			continue;
1367 		}
1368 
1369 		/* All of these argument types must be scalars */
1370 		switch (arg_type) {
1371 		case 'b':
1372 			if (VALUE_IS_STRING (tmp)) {
1373 				gboolean err;
1374 				gboolean b = value_get_as_bool (tmp, &err);
1375 				if (err) {
1376 					free_values (args, i + 1);
1377 					return value_new_error_VALUE (ei->pos);
1378 				}
1379 				value_release (args[i]);
1380 				tmp = args[i] = value_new_bool (b);
1381 				break;
1382 			}
1383 			/* Fall through.  */
1384 		case 'f':
1385 			if (VALUE_IS_STRING (tmp)) {
1386 				tmp = format_match_number (value_peek_string (tmp), NULL,
1387 					sheet_date_conv (ei->pos->sheet));
1388 				if (tmp == NULL) {
1389 					free_values (args, i + 1);
1390 					return value_new_error_VALUE (ei->pos);
1391 				}
1392 				value_release (args [i]);
1393 				args[i] = tmp;
1394 			} else if (VALUE_IS_ERROR (tmp)) {
1395 				free_values (args, i);
1396 				return tmp;
1397 			} else if (VALUE_IS_EMPTY (tmp)) {
1398 				value_release (args [i]);
1399 				tmp = args[i] = value_new_int (0);
1400 			}
1401 
1402 			if (!VALUE_IS_NUMBER (tmp))
1403 				return value_new_error_VALUE (ei->pos);
1404 			break;
1405 
1406 		case 's':
1407 		case 'S':
1408 			if (VALUE_IS_ERROR (tmp)) {
1409 				free_values (args, i);
1410 				return tmp;
1411 			}
1412 			break;
1413 
1414 		case 'E': /* nothing necessary */
1415 			break;
1416 
1417 		/* case '?': handled above */
1418 		default:
1419 			g_warning ("Unknown argument type '%c'", arg_type);
1420 			break;
1421 		}
1422 	}
1423 
1424 	while (i < fn_def->max_args)
1425 		args [i++] = NULL;
1426 
1427 	if (iter_item != NULL) {
1428 		int x, y;
1429 		GnmValue *res = value_new_array_empty (iter_width, iter_height);
1430 		GnmValue const *elem, *err;
1431 		GnmValue **iter_vals = g_alloca (sizeof (GnmValue *) * iter_count);
1432 		GnmValue **iter_args = g_alloca (sizeof (GnmValue *) * iter_count);
1433 
1434 		/* collect the args we will iterate on */
1435 		for (i = 0 ; i < iter_count; i++)
1436 			iter_vals[i] = args[iter_item[i]];
1437 
1438 		for (x = iter_width; x-- > 0 ; )
1439 			for (y = iter_height; y-- > 0 ; ) {
1440 				/* marshal the args */
1441 				err = NULL;
1442 				for (i = 0 ; i < iter_count; i++) {
1443 					elem = value_area_get_x_y (iter_vals[i], x, y, ei->pos);
1444 					arg_type = fn_def->arg_types[iter_item[i]];
1445 					if  (arg_type == 'b' || arg_type == 'f') {
1446 						if (VALUE_IS_EMPTY (elem))
1447 							elem = value_zero;
1448 						else if (VALUE_IS_STRING (elem)) {
1449 							tmp = format_match_number (value_peek_string (elem), NULL,
1450 								sheet_date_conv (ei->pos->sheet));
1451 							if (tmp != NULL) {
1452 								args [iter_item[i]] = iter_args [i] = tmp;
1453 								continue;
1454 							} else
1455 								break;
1456 						} else if (VALUE_IS_ERROR (elem)) {
1457 							err = elem;
1458 							break;
1459 						} else if (!VALUE_IS_NUMBER (elem))
1460 							break;
1461 					} else if (arg_type == 's') {
1462 						if (VALUE_IS_EMPTY (elem)) {
1463 							args [iter_item[i]] = iter_args [i] = value_new_string ("");
1464 							continue;
1465 						} else if (VALUE_IS_ERROR (elem)) {
1466 							err = elem;
1467 							break;
1468 						} else if (!VALUE_IS_STRING (elem))
1469 							break;
1470 					} else if (elem == NULL) {
1471 						args [iter_item[i]] = iter_args [i] = value_new_empty ();
1472 						continue;
1473 					}
1474 					args [iter_item[i]] = iter_args [i] = value_dup (elem);
1475 				}
1476 
1477 				res->v_array.vals[x][y] = (i == iter_count)
1478 					? fn_def->args_func (ei, (GnmValue const * const *)args)
1479 					: ((err != NULL) ? value_dup (err)
1480 							 : value_new_error_VALUE (ei->pos));
1481 				free_values (iter_args, i);
1482 			}
1483 
1484 		/* free the primaries, not the already freed iteration */
1485 		for (i = 0 ; i < iter_count; i++)
1486 			args[iter_item[i]] = iter_vals[i];
1487 		tmp = res;
1488 		i = fn_def->max_args;
1489 	} else
1490 		tmp = fn_def->args_func (ei, (GnmValue const * const *)args);
1491 
1492 	free_values (args, i);
1493 	return tmp;
1494 }
1495 
1496 /*
1497  * Use this to invoke a register function: the only drawback is that
1498  * you have to compute/expand all of the values to use this
1499  */
1500 GnmValue *
function_call_with_values(GnmEvalPos const * ep,char const * fn_name,int argc,GnmValue const * const * values)1501 function_call_with_values (GnmEvalPos const *ep, char const *fn_name,
1502 			   int argc, GnmValue const * const *values)
1503 {
1504 	GnmFunc *fn_def;
1505 
1506 	g_return_val_if_fail (ep != NULL, NULL);
1507 	g_return_val_if_fail (fn_name != NULL, NULL);
1508 	g_return_val_if_fail (ep->sheet != NULL, NULL);
1509 
1510 	/* FIXME : support workbook local functions */
1511 	fn_def = gnm_func_lookup (fn_name, NULL);
1512 	if (fn_def == NULL)
1513 		return value_new_error_NAME (ep);
1514 	return function_def_call_with_values (ep, fn_def, argc, values);
1515 }
1516 
1517 GnmValue *
function_def_call_with_values(GnmEvalPos const * ep,GnmFunc const * fn_def,int argc,GnmValue const * const * values)1518 function_def_call_with_values (GnmEvalPos const *ep, GnmFunc const *fn_def,
1519                                int argc, GnmValue const * const *values)
1520 {
1521 	GnmValue *retval;
1522 	GnmExprFunction	ef;
1523 	GnmFuncEvalInfo fs;
1524 
1525 	fs.pos = ep;
1526 	fs.func_call = &ef;
1527 	ef.func = (GnmFunc *)fn_def;
1528 
1529 	gnm_func_load_if_stub (ef.func);
1530 
1531 	if (fn_def->fn_type == GNM_FUNC_TYPE_NODES) {
1532 		/*
1533 		 * If function deals with ExprNodes, create some
1534 		 * temporary ExprNodes with constants.
1535 		 */
1536 		GnmExprConstant *expr = g_new (GnmExprConstant, argc);
1537 		GnmExprConstPtr *argv = g_new (GnmExprConstPtr, argc);
1538 		int i;
1539 
1540 		for (i = 0; i < argc; i++) {
1541 			gnm_expr_constant_init (expr + i, values[i]);
1542 			argv[i] = (GnmExprConstPtr)(expr + i);
1543 		}
1544 		retval = fn_def->nodes_func (&fs, argc, argv);
1545 		g_free (argv);
1546 		g_free (expr);
1547 	} else
1548 		retval = fn_def->args_func (&fs, values);
1549 
1550 	return retval;
1551 }
1552 
1553 /* ------------------------------------------------------------------------- */
1554 
1555 typedef struct {
1556 	FunctionIterateCB  callback;
1557 	void              *closure;
1558 	gboolean           strict;
1559 	gboolean           ignore_subtotal;
1560 } IterateCallbackClosure;
1561 
1562 /**
1563  * cb_iterate_cellrange:
1564  *
1565  * Helper routine used by the function_iterate_do_value routine.
1566  * Invoked by the sheet cell range iterator.
1567  **/
1568 static GnmValue *
cb_iterate_cellrange(GnmCellIter const * iter,gpointer user)1569 cb_iterate_cellrange (GnmCellIter const *iter, gpointer user)
1570 
1571 {
1572 	IterateCallbackClosure *data = user;
1573 	GnmCell  *cell;
1574 	GnmValue *res;
1575 	GnmEvalPos ep;
1576 
1577 	if (NULL == (cell = iter->cell)) {
1578 		ep.sheet = iter->pp.sheet;
1579 		ep.dep = NULL;
1580 		ep.eval.col = iter->pp.eval.col;
1581 		ep.eval.row = iter->pp.eval.row;
1582 		return (*data->callback)(&ep, NULL, data->closure);
1583 	}
1584 
1585 	if (data->ignore_subtotal && gnm_cell_has_expr (cell) &&
1586 	    gnm_expr_top_contains_subtotal (cell->base.texpr))
1587 		return NULL;
1588 
1589 	gnm_cell_eval (cell);
1590 	eval_pos_init_cell (&ep, cell);
1591 
1592 	/* If we encounter an error for the strict case, short-circuit here.  */
1593 	if (data->strict && (NULL != (res = gnm_cell_is_error (cell))))
1594 		return value_new_error_str (&ep, res->v_err.mesg);
1595 
1596 	/* All other cases -- including error -- just call the handler.  */
1597 	return (*data->callback)(&ep, cell->value, data->closure);
1598 }
1599 
1600 /*
1601  * function_iterate_do_value:
1602  *
1603  * Helper routine for function_iterate_argument_values.
1604  */
1605 static GnmValue *
function_iterate_do_value(GnmEvalPos const * ep,FunctionIterateCB callback,gpointer closure,GnmValue const * value,gboolean strict,CellIterFlags iter_flags)1606 function_iterate_do_value (GnmEvalPos const  *ep,
1607 			   FunctionIterateCB  callback,
1608 			   gpointer	      closure,
1609 			   GnmValue const    *value,
1610 			   gboolean           strict,
1611 			   CellIterFlags      iter_flags)
1612 {
1613 	GnmValue *res = NULL;
1614 
1615 	switch (value->v_any.type){
1616 	case VALUE_ERROR:
1617 		if (strict) {
1618 			res = value_dup (value);
1619 			break;
1620 		}
1621 		/* Fall through.  */
1622 
1623 	case VALUE_EMPTY:
1624 	case VALUE_BOOLEAN:
1625 	case VALUE_FLOAT:
1626 	case VALUE_STRING:
1627 		res = (*callback)(ep, value, closure);
1628 		break;
1629 
1630 	case VALUE_ARRAY: {
1631 		int x, y;
1632 
1633 		/* Note the order here.  */
1634 		for (y = 0; y < value->v_array.y; y++) {
1635 			  for (x = 0; x < value->v_array.x; x++) {
1636 				res = function_iterate_do_value (
1637 					ep, callback, closure,
1638 					value->v_array.vals [x][y],
1639 					strict, CELL_ITER_IGNORE_BLANK);
1640 				if (res != NULL)
1641 					return res;
1642 			}
1643 		}
1644 		break;
1645 	}
1646 	case VALUE_CELLRANGE: {
1647 		IterateCallbackClosure data;
1648 
1649 		data.callback = callback;
1650 		data.closure  = closure;
1651 		data.strict   = strict;
1652 		data.ignore_subtotal = (iter_flags & CELL_ITER_IGNORE_SUBTOTAL) != 0;
1653 
1654 		res = workbook_foreach_cell_in_range (ep, value, iter_flags,
1655 						      cb_iterate_cellrange,
1656 						      &data);
1657 	}
1658 	}
1659 	return res;
1660 }
1661 
1662 /**
1663  * function_iterate_argument_values:
1664  * @ep:               The position in a workbook at which to evaluate
1665  * @callback: (scope call): The routine to be invoked for every value computed
1666  * @callback_closure: Closure for the callback.
1667  * @argc:
1668  * @argv:
1669  * @strict:           If TRUE, the function is considered "strict".  This means
1670  *                   that if an error value occurs as an argument, the iteration
1671  *                   will stop and that error will be returned.  If FALSE, an
1672  *                   error will be passed on to the callback (as a GnmValue *
1673  *                   of type VALUE_ERROR).
1674  * @iter_flags:
1675  *
1676  * Return value:
1677  *    NULL            : if no errors were reported.
1678  *    GnmValue *         : if an error was found during strict evaluation
1679  *    VALUE_TERMINATE : if the callback requested termination of the iteration.
1680  *
1681  * This routine provides a simple way for internal functions with variable
1682  * number of arguments to be written: this would iterate over a list of
1683  * expressions (expr_node_list) and will invoke the callback for every
1684  * GnmValue found on the list (this means that ranges get properly expanded).
1685  **/
1686 GnmValue *
function_iterate_argument_values(GnmEvalPos const * ep,FunctionIterateCB callback,void * callback_closure,int argc,GnmExprConstPtr const * argv,gboolean strict,CellIterFlags iter_flags)1687 function_iterate_argument_values (GnmEvalPos const	*ep,
1688 				  FunctionIterateCB	 callback,
1689 				  void			*callback_closure,
1690 				  int                    argc,
1691 				  GnmExprConstPtr const *argv,
1692 				  gboolean		 strict,
1693 				  CellIterFlags		 iter_flags)
1694 {
1695 	GnmValue *result = NULL;
1696 	int a;
1697 
1698 	for (a = 0; result == NULL && a < argc; a++) {
1699 		GnmExpr const *expr = argv[a];
1700 		GnmValue *val;
1701 
1702 		if (iter_flags & CELL_ITER_IGNORE_SUBTOTAL &&
1703 		    gnm_expr_contains_subtotal (expr))
1704 			continue;
1705 
1706 		/* need to drill down into names to handle things like
1707 		 * sum(name)  with name := (A:A,B:B) */
1708 		while (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_NAME) {
1709 			GnmExprTop const *texpr = expr->name.name->texpr;
1710 			expr = texpr ? texpr->expr : NULL;
1711 			if (expr == NULL) {
1712 				if (strict)
1713 					return value_new_error_REF (ep);
1714 				break;
1715 			}
1716 		}
1717 		if (!expr)
1718 			continue;
1719 
1720 		/* Handle sets as a special case */
1721 		if (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_SET) {
1722 			result = function_iterate_argument_values
1723 				(ep, callback, callback_closure,
1724 				 expr->set.argc, expr->set.argv,
1725 				 strict, iter_flags);
1726 			continue;
1727 		}
1728 
1729 		/* We need a cleaner model of what to do here.
1730 		 * In non-array mode
1731 		 *	SUM(Range)
1732 		 * will obviously return Range
1733 		 *
1734 		 *	SUM(INDIRECT(Range))
1735 		 *	SUM(INDIRECT(Range):....)
1736 		 * will do implicit intersection on Range (in non-array mode),
1737 		 * but allow non-scalar results from indirect (no intersection)
1738 		 *
1739 		 *	SUM(Range=3)
1740 		 * will do implicit intersection in non-array mode */
1741 		if (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_CONSTANT)
1742 			val = value_dup (expr->constant.value);
1743 		else if (eval_pos_is_array_context (ep) ||
1744 			 GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_FUNCALL ||
1745 			 GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_RANGE_CTOR ||
1746 			 GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_INTERSECT)
1747 			val = gnm_expr_eval (expr, ep,
1748 				GNM_EXPR_EVAL_PERMIT_EMPTY | GNM_EXPR_EVAL_PERMIT_NON_SCALAR);
1749 		else
1750 			val = gnm_expr_eval (expr, ep, GNM_EXPR_EVAL_PERMIT_EMPTY);
1751 
1752 		if (val == NULL)
1753 			continue;
1754 
1755 		if (strict && VALUE_IS_ERROR (val)) {
1756 			/* Be careful not to make VALUE_TERMINATE into a real value */
1757 			return val;
1758 		}
1759 
1760 		result = function_iterate_do_value (ep, callback, callback_closure,
1761 						    val, strict, iter_flags);
1762 		value_release (val);
1763 	}
1764 	return result;
1765 }
1766 
1767 
1768 /**
1769  * gnm_eval_info_get_func:
1770  * @ei: #GnmFuncEvalInfo
1771  *
1772  * Returns: (transfer none): the called function.
1773  */
1774 GnmFunc const *
gnm_eval_info_get_func(GnmFuncEvalInfo const * ei)1775 gnm_eval_info_get_func (GnmFuncEvalInfo const *ei)
1776 {
1777 	return ei->func_call->func;
1778 }
1779 
1780 int
gnm_eval_info_get_arg_count(GnmFuncEvalInfo const * ei)1781 gnm_eval_info_get_arg_count (GnmFuncEvalInfo const *ei)
1782 {
1783 	return ei->func_call->argc;
1784 }
1785 
1786 GnmDependentFlags
gnm_func_link_dep(GnmFunc * func,GnmFuncEvalInfo * ei,gboolean qlink)1787 gnm_func_link_dep (GnmFunc *func, GnmFuncEvalInfo *ei, gboolean qlink)
1788 {
1789 	int res = DEPENDENT_NO_FLAG;
1790 	g_signal_emit (func, signals[SIG_LINK_DEP], 0, ei, qlink, &res);
1791 	return (GnmDependentFlags)res;
1792 }
1793 
1794 /**
1795  * gnm_func_derivative:
1796  * @func: #GnmFunc
1797  * @expr: expression that calls @func
1798  * @ep: position of @expr
1799  * @info: #GnmExprDeriv
1800  *
1801  * Returns: (transfer full) (nullable): the derivative of @expr with respect to
1802  * @info.
1803  */
1804 GnmExpr const *
gnm_func_derivative(GnmFunc * func,GnmExpr const * expr,GnmEvalPos const * ep,GnmExprDeriv * info)1805 gnm_func_derivative (GnmFunc *func, GnmExpr const *expr, GnmEvalPos const *ep,
1806 		     GnmExprDeriv *info)
1807 {
1808 	GnmExpr *res = NULL;
1809 
1810 	g_return_val_if_fail (GNM_IS_FUNC (func), NULL);
1811 	g_signal_emit (func, signals[SIG_DERIVATIVE], 0, expr, ep, info, &res);
1812 	return res;
1813 }
1814 
1815 /* ------------------------------------------------------------------------- */
1816 
1817 static GObjectClass *parent_class;
1818 
1819 typedef struct {
1820 	GObjectClass parent;
1821 
1822 	void (*load_stub) (GnmFunc *func);
1823 	int (*link_dep) (GnmFunc *func, GnmFuncEvalInfo *ei, gboolean qlink);
1824 	GnmExpr* (*derivative) (GnmFunc *func, GnmExpr const *expr, GnmEvalPos *ep, GnmExprDeriv *info);
1825 } GnmFuncClass;
1826 
1827 static void
gnm_func_finalize(GObject * obj)1828 gnm_func_finalize (GObject *obj)
1829 {
1830 	GnmFunc *func = GNM_FUNC (obj);
1831 
1832 	g_free (func->arg_types);
1833 
1834 	g_free ((char *)func->name);
1835 
1836 	go_string_unref (func->tdomain);
1837 
1838 	parent_class->finalize (obj);
1839 }
1840 
1841 static void
gnm_func_real_dispose(GObject * obj)1842 gnm_func_real_dispose (GObject *obj)
1843 {
1844 	GnmFunc *func = GNM_FUNC (obj);
1845 
1846 	if (func->usage_count != 0) {
1847 		g_printerr ("Function %s still has a usage count of %d\n",
1848 			    func->name, func->usage_count);
1849 	}
1850 
1851 	gnm_func_set_stub (func);
1852 
1853 	if (func->fn_group) {
1854 		gnm_func_group_remove_func (func->fn_group, func);
1855 		func->fn_group = NULL;
1856 	}
1857 
1858 	gnm_func_set_localized_name (func, NULL);
1859 
1860 	if (!(func->flags & GNM_FUNC_IS_WORKBOOK_LOCAL)) {
1861 		g_hash_table_remove (functions_by_name, func->name);
1862 	}
1863 
1864 	parent_class->dispose (obj);
1865 }
1866 
1867 void
gnm_func_dispose(GnmFunc * func)1868 gnm_func_dispose (GnmFunc *func)
1869 {
1870 	g_object_run_dispose (G_OBJECT (func));
1871 }
1872 
1873 static void
gnm_func_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)1874 gnm_func_get_property (GObject *object, guint property_id,
1875 		       GValue *value, GParamSpec *pspec)
1876 {
1877 	GnmFunc *func = (GnmFunc *)object;
1878 
1879 	switch (property_id) {
1880 	case PROP_NAME:
1881 		g_value_set_string (value, func->name);
1882 		break;
1883 	case PROP_TRANSLATION_DOMAIN:
1884 		g_value_set_string (value, func->tdomain->str);
1885 		break;
1886 	case PROP_IN_USE:
1887 		g_value_set_boolean (value, func->usage_count > 0);
1888 		break;
1889 	default:
1890 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1891 		break;
1892 	}
1893 }
1894 
1895 static void
gnm_func_set_property(GObject * object,guint property_id,GValue const * value,GParamSpec * pspec)1896 gnm_func_set_property (GObject *object, guint property_id,
1897 		       GValue const *value, GParamSpec *pspec)
1898 {
1899 	GnmFunc *func = (GnmFunc *)object;
1900 
1901 	switch (property_id) {
1902 	case PROP_NAME:
1903 		func->name = g_value_dup_string (value);
1904 		break;
1905 	case PROP_TRANSLATION_DOMAIN:
1906 		gnm_func_set_translation_domain (func,
1907 						 g_value_get_string (value));
1908 		break;
1909 	default:
1910 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1911 		break;
1912 	}
1913 }
1914 
1915 static void
gnm_func_init(GnmFunc * func)1916 gnm_func_init (GnmFunc *func)
1917 {
1918 	func->tdomain = go_string_new (GETTEXT_PACKAGE);
1919 	func->flags = GNM_FUNC_SIMPLE;
1920 	func->impl_status = GNM_FUNC_IMPL_STATUS_UNIMPLEMENTED;
1921 	func->test_status = GNM_FUNC_TEST_STATUS_UNKNOWN;
1922 }
1923 
1924 static void
gnm_func_class_init(GObjectClass * gobject_class)1925 gnm_func_class_init (GObjectClass *gobject_class)
1926 {
1927 	parent_class = g_type_class_peek_parent (gobject_class);
1928 
1929 	gobject_class->finalize         = gnm_func_finalize;
1930 	gobject_class->dispose          = gnm_func_real_dispose;
1931 	gobject_class->get_property	= gnm_func_get_property;
1932 	gobject_class->set_property	= gnm_func_set_property;
1933 
1934         g_object_class_install_property (gobject_class, PROP_NAME,
1935 		 g_param_spec_string ("name",
1936 				      P_("Name"),
1937 				      P_("The name of the function."),
1938 				      NULL,
1939 				      GSF_PARAM_STATIC |
1940 				      G_PARAM_READWRITE |
1941 				      G_PARAM_CONSTRUCT_ONLY));
1942 
1943         g_object_class_install_property (gobject_class, PROP_TRANSLATION_DOMAIN,
1944 		 g_param_spec_string ("translation-domain",
1945 				      P_("Translation Domain"),
1946 				      P_("The translation domain for help texts"),
1947 				      NULL,
1948 				      GSF_PARAM_STATIC |
1949 				      G_PARAM_READWRITE));
1950 
1951         g_object_class_install_property (gobject_class, PROP_IN_USE,
1952 		 g_param_spec_boolean ("in-use",
1953 				       P_("In use"),
1954 				       P_("Is function being used?"),
1955 				       FALSE,
1956 				       GSF_PARAM_STATIC |
1957 				       G_PARAM_READABLE));
1958 
1959 	/**
1960 	 * GnmFunc::load-stub:
1961 	 * @func: the #GnmFunc that needs to be loaded
1962 	 *
1963 	 * Signals that @func, which is a stub, needs to be loaded now.  Anyone
1964 	 * creating a stub function should arrange for this signal to be caught
1965 	 * and the function to be properly instantiated.
1966 	 */
1967 	signals[SIG_LOAD_STUB] = g_signal_new
1968 		("load-stub",
1969 		 GNM_FUNC_TYPE,
1970 		 G_SIGNAL_RUN_LAST,
1971 		 G_STRUCT_OFFSET (GnmFuncClass, load_stub),
1972 		 NULL, NULL,
1973 		 g_cclosure_marshal_VOID__VOID,
1974 		 G_TYPE_NONE, 0);
1975 
1976 	/**
1977 	 * GnmFunc::link-dep:
1978 	 * @func: the #GnmFunc that is being linked or unlinked
1979 	 * @ei: #GnmFuncEvalInfo for the call initiating the link or unlink.
1980 	 * @qlink: %TRUE for link, %FALSE for unlink
1981 	 *
1982 	 * Signals that an expressions that is a call to @func is being linked
1983 	 * or unlinked.  Most functions do not need this.
1984 	 *
1985 	 * Returns: A #GnmDependentFlags allowing arguments not be be linked if
1986 	 * that is appropriate.
1987 	 */
1988 	signals[SIG_LINK_DEP] = g_signal_new
1989 		("link-dep",
1990 		 GNM_FUNC_TYPE,
1991 		 G_SIGNAL_RUN_LAST,
1992 		 G_STRUCT_OFFSET (GnmFuncClass, link_dep),
1993 		 NULL, NULL,
1994 		 gnm__INT__POINTER_BOOLEAN,
1995 		 // GnmDependentFlags ... GnmFuncEvalInfo
1996 		 G_TYPE_INT, 2, G_TYPE_POINTER, G_TYPE_BOOLEAN);
1997 
1998 	/**
1999 	 * GnmFunc::derivative:
2000 	 * @func: #GnmFunc
2001 	 * @expr: #GnmExpr for the call for which the derivative is sought
2002 	 * @ep: position f @expr
2003 	 * @info: #GnmExprDeriv telling which derivative is sought
2004 	 *
2005 	 * Signals that a function call's derivative should be calculated
2006 	 *
2007 	 * Returns: (transfer full) (nullable): #GnmExpr representing the
2008 	 * derivative, %NULL for error.
2009 	 */
2010 	signals[SIG_DERIVATIVE] = g_signal_new
2011 		("derivative",
2012 		 GNM_FUNC_TYPE,
2013 		 G_SIGNAL_RUN_LAST,
2014 		 G_STRUCT_OFFSET (GnmFuncClass, derivative),
2015 		 NULL, NULL,
2016 		 gnm__BOXED__BOXED_BOXED_BOXED,
2017 		 gnm_expr_get_type(),
2018 		 3, gnm_expr_get_type(), gnm_eval_pos_get_type(), gnm_expr_deriv_info_get_type());
2019 }
2020 
2021 GSF_CLASS (GnmFunc, gnm_func,
2022 	   gnm_func_class_init, gnm_func_init, G_TYPE_OBJECT)
2023