GnmFunc: make this a GObject.
[gnumeric.git] / src / func.c
blob0700471a0ceb044812091017094c784bd9464045
1 /*
2 * func.c: Function management and utility routines.
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 #include <gnumeric-config.h>
11 #include <glib/gi18n-lib.h>
12 #include <glib/gstdio.h>
13 #include <gnm-i18n.h>
14 #include <gnumeric.h>
15 #include <func.h>
17 #include <parse-util.h>
18 #include <dependent.h>
19 #include <expr.h>
20 #include <expr-impl.h>
21 #include <expr-name.h>
22 #include <cell.h>
23 #include <workbook-priv.h>
24 #include <sheet.h>
25 #include <value.h>
26 #include <number-match.h>
27 #include <func-builtin.h>
28 #include <command-context-stderr.h>
29 #include <gnm-plugin.h>
30 #include <gutils.h>
31 #include <gui-util.h>
32 #include <gnm-marshalers.h>
34 #include <goffice/goffice.h>
35 #include <glib.h>
36 #include <string.h>
37 #include <stdlib.h>
39 enum {
40 PROP_0,
41 PROP_NAME,
42 PROP_TRANSLATION_DOMAIN,
43 PROP_IN_USE,
46 enum {
47 SIG_LOAD_STUB,
48 SIG_LINK_DEP,
49 LAST_SIGNAL
51 static guint signals[LAST_SIGNAL] = { 0 };
54 #define F2(func,s) dgettext ((func)->tdomain->str, (s))
56 static GList *categories;
57 static GnmFuncGroup *unknown_cat;
59 static GHashTable *functions_by_name;
60 static GHashTable *functions_by_localized_name;
62 /**
63 * functions_init: (skip)
65 void
66 functions_init (void)
68 functions_by_name =
69 g_hash_table_new (go_ascii_strcase_hash, go_ascii_strcase_equal);
71 /* FIXME: ascii??? */
72 functions_by_localized_name =
73 g_hash_table_new (go_ascii_strcase_hash, go_ascii_strcase_equal);
75 func_builtin_init ();
78 /**
79 * functions_shutdown: (skip)
81 void
82 functions_shutdown (void)
84 while (unknown_cat != NULL && unknown_cat->functions != NULL) {
85 GnmFunc *func = unknown_cat->functions->data;
86 if (func->usage_count > 0) {
87 g_warning ("Function %s still has %d users.\n",
88 gnm_func_get_name (func, FALSE),
89 func->usage_count);
90 func->usage_count = 0;
92 g_object_unref (func);
94 func_builtin_shutdown ();
96 g_hash_table_destroy (functions_by_name);
97 functions_by_name = NULL;
99 g_hash_table_destroy (functions_by_localized_name);
100 functions_by_localized_name = NULL;
104 * gnm_func_enumerate:
106 * Return value: (element-type GnmFunc) (transfer container):
108 GPtrArray *
109 gnm_func_enumerate (void)
111 GPtrArray *res = g_ptr_array_new ();
112 GHashTableIter hiter;
113 gpointer value;
115 g_hash_table_iter_init (&hiter, functions_by_name);
116 while (g_hash_table_iter_next (&hiter, NULL, &value))
117 g_ptr_array_add (res, value);
119 return res;
122 inline void
123 gnm_func_load_if_stub (GnmFunc *func)
125 if (func->fn_type == GNM_FUNC_TYPE_STUB)
126 gnm_func_load_stub (func);
129 static char *
130 split_at_colon (char const *s, char **rest)
132 char *dup = g_strdup (s);
133 char *colon = strchr (dup, ':');
134 if (colon) {
135 *colon = 0;
136 if (rest) *rest = colon + 1;
137 } else {
138 if (rest) *rest = NULL;
140 return dup;
143 /* ------------------------------------------------------------------------- */
145 static void
146 gnm_func_group_free (GnmFuncGroup *fn_group)
148 g_return_if_fail (fn_group != NULL);
149 g_return_if_fail (fn_group->functions == NULL);
151 if (fn_group->ref_count-- > 1)
152 return;
154 go_string_unref (fn_group->internal_name);
155 go_string_unref (fn_group->display_name);
156 g_free (fn_group);
159 static GnmFuncGroup *
160 gnm_func_group_ref (GnmFuncGroup *fn_group)
162 fn_group->ref_count++;
163 return fn_group;
166 GType
167 gnm_func_group_get_type (void)
169 static GType t = 0;
171 if (t == 0) {
172 t = g_boxed_type_register_static ("GnmFuncGroup",
173 (GBoxedCopyFunc)gnm_func_group_ref,
174 (GBoxedFreeFunc)gnm_func_group_free);
176 return t;
179 static gint
180 function_category_compare (gconstpointer a, gconstpointer b)
182 GnmFuncGroup const *cat_a = a;
183 GnmFuncGroup const *cat_b = b;
185 return go_string_cmp (cat_a->display_name, cat_b->display_name);
188 GnmFuncGroup *
189 gnm_func_group_fetch (char const *name, char const *translation)
191 GnmFuncGroup *cat = NULL;
192 GList *l;
194 g_return_val_if_fail (name != NULL, NULL);
196 for (l = categories; l != NULL; l = l->next) {
197 cat = l->data;
198 if (strcmp (cat->internal_name->str, name) == 0) {
199 break;
203 if (l == NULL) {
204 cat = g_new (GnmFuncGroup, 1);
205 cat->internal_name = go_string_new (name);
206 cat->ref_count = 1;
207 if (translation != NULL) {
208 cat->display_name = go_string_new (translation);
209 cat->has_translation = TRUE;
210 } else {
211 cat->display_name = go_string_new (name);
212 cat->has_translation = FALSE;
214 cat->functions = NULL;
215 categories = g_list_insert_sorted (
216 categories, cat, &function_category_compare);
217 } else if (translation != NULL && translation != name &&
218 !cat->has_translation) {
219 go_string_unref (cat->display_name);
220 cat->display_name = go_string_new (translation);
221 cat->has_translation = TRUE;
222 categories = g_list_remove_link (categories, l);
223 g_list_free_1 (l);
224 categories = g_list_insert_sorted (
225 categories, cat, &function_category_compare);
228 return cat;
231 GnmFuncGroup *
232 gnm_func_group_get_nth (int n)
234 return g_list_nth_data (categories, n);
237 static void
238 gnm_func_group_add_func (GnmFuncGroup *fn_group, GnmFunc *fn_def)
240 g_return_if_fail (fn_group != NULL);
241 g_return_if_fail (fn_def != NULL);
243 fn_group->functions = g_slist_prepend (fn_group->functions, fn_def);
246 static void
247 gnm_func_group_remove_func (GnmFuncGroup *fn_group, GnmFunc *fn_def)
249 g_return_if_fail (fn_group != NULL);
250 g_return_if_fail (fn_def != NULL);
252 fn_group->functions = g_slist_remove (fn_group->functions, fn_def);
253 if (fn_group->functions == NULL) {
254 categories = g_list_remove (categories, fn_group);
255 if (unknown_cat == fn_group)
256 unknown_cat = NULL;
257 gnm_func_group_free (fn_group);
261 /******************************************************************************/
263 static void
264 extract_arg_types (GnmFunc *def)
266 int i;
268 gnm_func_count_args (def,
269 &def->fn.args.min_args,
270 &def->fn.args.max_args);
271 def->fn.args.arg_types = g_malloc (def->fn.args.max_args + 1);
272 for (i = 0; i < def->fn.args.max_args; i++)
273 def->fn.args.arg_types[i] = gnm_func_get_arg_type (def, i);
274 def->fn.args.arg_types[i] = 0;
277 static GnmValue *
278 error_function_no_full_info (GnmFuncEvalInfo *ei,
279 int argc,
280 GnmExprConstPtr const *argv)
282 return value_new_error (ei->pos, _("Function implementation not available."));
285 static void
286 gnm_func_clear_arg_names (GnmFunc *fd)
288 if (fd->arg_names_p) {
289 g_ptr_array_foreach (fd->arg_names_p, (GFunc) g_free, NULL);
290 g_ptr_array_free (fd->arg_names_p, TRUE);
291 fd->arg_names_p = NULL;
295 static void
296 gnm_func_create_arg_names (GnmFunc *fn_def)
298 int i;
299 GPtrArray *ptr;
301 g_return_if_fail (fn_def != NULL);
303 ptr = g_ptr_array_new ();
304 for (i = 0;
305 fn_def->help && fn_def->help[i].type != GNM_FUNC_HELP_END;
306 i++) {
307 if (fn_def->help[i].type != GNM_FUNC_HELP_ARG)
308 continue;
310 g_ptr_array_add
311 (ptr, split_at_colon
312 (F2(fn_def, fn_def->help[i].text), NULL));
315 gnm_func_clear_arg_names (fn_def);
316 fn_def->arg_names_p = ptr;
320 void
321 gnm_func_load_stub (GnmFunc *func)
323 g_return_if_fail (func->fn_type == GNM_FUNC_TYPE_STUB);
325 g_signal_emit (G_OBJECT (func), signals[SIG_LOAD_STUB], 0);
327 if (func->fn_type == GNM_FUNC_TYPE_STUB) {
328 static GnmFuncHelp const no_help[] = { { GNM_FUNC_HELP_END } };
330 func->help = no_help;
331 func->fn.nodes = &error_function_no_full_info;
332 gnm_func_set_function_type (func, GNM_FUNC_TYPE_NODES);
336 void
337 gnm_func_set_function_type (GnmFunc *func, GnmFuncType typ)
339 g_return_if_fail (GNM_IS_FUNC (func));
341 func->fn_type = typ;
342 switch (typ) {
343 case GNM_FUNC_TYPE_ARGS:
344 extract_arg_types (func);
345 gnm_func_create_arg_names (func);
346 break;
347 case GNM_FUNC_TYPE_NODES:
348 gnm_func_create_arg_names (func);
349 break;
350 case GNM_FUNC_TYPE_STUB:
351 break;
356 static void
357 gnm_func_set_localized_name (GnmFunc *fd, const char *lname)
359 gboolean in_hashes = !(fd->flags & GNM_FUNC_IS_WORKBOOK_LOCAL);
361 if (g_strcmp0 (fd->localized_name, lname) == 0)
362 return;
364 if (in_hashes && fd->localized_name)
365 g_hash_table_remove (functions_by_localized_name, fd->localized_name);
366 g_free (fd->localized_name);
368 fd->localized_name = g_strdup (lname);
369 if (in_hashes && lname)
370 g_hash_table_insert (functions_by_localized_name,
371 fd->localized_name, fd);
375 * gnm_func_inc_usage:
376 * @func: (transfer none): #GnmFunc
378 * This function increments the usage count of @func. A non-zero usage count
379 * prevents the unloading of the function.
381 * Returns: (transfer full): a new reference to @func.
383 GnmFunc *
384 gnm_func_inc_usage (GnmFunc *func)
386 g_return_val_if_fail (func != NULL, NULL);
388 func->usage_count++;
389 if (func->usage_count == 1)
390 g_object_notify (G_OBJECT (func), "in-use");
391 return func;
395 * gnm_func_dec_usage:
396 * @func: (transfer full): #GnmFunc
398 * This function decrements the usage count of @func. When the usage count
399 * reaches zero, the function may be unloaded, for example by unloading the
400 * plugin that defines it.
402 void
403 gnm_func_dec_usage (GnmFunc *func)
405 g_return_if_fail (func != NULL);
406 g_return_if_fail (func->usage_count > 0);
408 func->usage_count--;
409 if (func->usage_count == 0)
410 g_object_notify (G_OBJECT (func), "in-use");
413 gboolean
414 gnm_func_get_in_use (GnmFunc *func)
416 g_return_val_if_fail (func != NULL, FALSE);
418 return func->usage_count > 0;
423 * gnm_func_lookup:
424 * @name: name of function
425 * @scope: (nullable): scope of function, %NULL for global
427 * Returns: (nullable) (transfer none): the function of that name.
429 GnmFunc *
430 gnm_func_lookup (char const *name, Workbook *scope)
432 GnmFunc *fd = g_hash_table_lookup (functions_by_name, name);
433 if (fd != NULL)
434 return fd;
435 if (scope == NULL || scope->sheet_local_functions == NULL)
436 return NULL;
437 return g_hash_table_lookup (scope->sheet_local_functions, (gpointer)name);
441 * gnm_func_lookup_localized:
442 * @name: localized name of function
443 * @scope: (nullable): scope of function, %NULL for global
445 * Returns: (nullable) (transfer none): the function of that name.
447 GnmFunc *
448 gnm_func_lookup_localized (char const *name, Workbook *scope)
450 GnmFunc *fd;
451 GHashTableIter hiter;
452 gpointer value;
454 /* Must localize all function names. */
455 g_hash_table_iter_init (&hiter, functions_by_name);
456 while (g_hash_table_iter_next (&hiter, NULL, &value)) {
457 GnmFunc *fd = value;
458 (void)gnm_func_get_name (fd, TRUE);
461 fd = g_hash_table_lookup (functions_by_localized_name, name);
462 if (fd != NULL)
463 return fd;
464 if (scope == NULL || scope->sheet_local_functions == NULL)
465 return NULL;
466 return g_hash_table_lookup (scope->sheet_local_functions, (gpointer)name);
470 * gnm_func_lookup_prefix:
471 * @prefix: prefix to search for
472 * @scope:
473 * @trans: whether to search translated function names
475 * Returns: (element-type GnmFunc*) (transfer full):
477 GSList *
478 gnm_func_lookup_prefix (char const *prefix, Workbook *scope, gboolean trans)
480 GSList *res = NULL;
481 GHashTableIter hiter;
482 gpointer value;
485 * Always iterate over functions_by_name as the localized name
486 * might not be set yet.
488 g_hash_table_iter_init (&hiter, functions_by_name);
489 while (g_hash_table_iter_next (&hiter, NULL, &value)) {
490 GnmFunc *fd = value;
491 if (!(fd->flags & GNM_FUNC_IS_PLACEHOLDER)) {
492 const char *name = gnm_func_get_name (fd, trans);
493 if (g_str_has_prefix (name, prefix)) {
494 gnm_func_inc_usage (fd);
495 res = g_slist_prepend (res, fd);
500 return res;
504 * gnm_func_get_translation_domain:
505 * @func: #GnmFunc
507 * Returns: (transfer none): the translation domain for @func's help text.
509 char const *
510 gnm_func_get_translation_domain (GnmFunc *func)
512 g_return_val_if_fail (GNM_IS_FUNC (func), NULL);
513 return func->tdomain->str;
517 * gnm_func_set_translation_domain:
518 * @func: #GnmFunc
519 * @tdomain: (nullable): Translation domain, %NULL for Gnumeric's.
521 void
522 gnm_func_set_translation_domain (GnmFunc *func, const char *tdomain)
524 g_return_if_fail (GNM_IS_FUNC (func));
526 if (!tdomain)
527 tdomain = GETTEXT_PACKAGE;
529 if (g_strcmp0 (func->tdomain->str, tdomain) == 0)
530 return;
532 go_string_unref (func->tdomain);
533 func->tdomain = go_string_new (tdomain);
535 g_object_notify (G_OBJECT (func), "translation-domain");
538 void
539 gnm_func_set_function_group (GnmFunc *func, GnmFuncGroup *group)
541 g_return_if_fail (GNM_IS_FUNC (func));
542 g_return_if_fail (group != NULL);
544 if (func->fn_group == group)
545 return;
547 if (func->fn_group)
548 gnm_func_group_remove_func (func->fn_group, func);
549 func->fn_group = group;
550 gnm_func_group_add_func (group, func);
552 if (group == unknown_cat)
553 func->flags |= GNM_FUNC_IS_PLACEHOLDER;
554 else
555 func->flags &= ~GNM_FUNC_IS_PLACEHOLDER;
561 * gnm_func_add:
562 * @group:
563 * @descriptor:
564 * @tdomain: (nullable):
566 * Returns: (transfer full): a new #GnmFunc.
568 GnmFunc *
569 gnm_func_add (GnmFuncGroup *fn_group,
570 GnmFuncDescriptor const *desc,
571 const char *tdomain)
573 static char const valid_tokens[] = "fsbraAES?|";
574 GnmFunc *func;
575 char const *ptr;
577 g_return_val_if_fail (fn_group != NULL, NULL);
578 g_return_val_if_fail (desc != NULL, NULL);
580 func = g_object_new (GNM_FUNC_TYPE,
581 "name", desc->name,
582 NULL);
583 gnm_func_set_translation_domain (func, tdomain);
585 func->help = desc->help ? desc->help : NULL;
586 func->flags = desc->flags;
587 func->impl_status = desc->impl_status;
588 func->test_status = desc->test_status;
589 func->localized_name = NULL;
590 func->arg_names_p = NULL;
592 func->usage_count = 0;
594 if (desc->fn_args != NULL) {
595 /* Check those arguments */
596 for (ptr = desc->arg_spec ; *ptr ; ptr++) {
597 g_return_val_if_fail (strchr (valid_tokens, *ptr), NULL);
600 func->fn.args.func = desc->fn_args;
601 func->fn.args.arg_spec = desc->arg_spec;
602 gnm_func_set_function_type (func, GNM_FUNC_TYPE_ARGS);
603 } else if (desc->fn_nodes != NULL) {
605 if (desc->arg_spec && *desc->arg_spec) {
606 g_warning ("Arg spec for node function -- why?");
609 func->fn.nodes = desc->fn_nodes;
610 gnm_func_set_function_type (func, GNM_FUNC_TYPE_NODES);
611 } else {
612 g_warning ("Invalid function has neither args nor nodes handler");
613 g_object_unref (func);
614 return NULL;
617 func->fn_group = fn_group;
618 gnm_func_group_add_func (fn_group, func);
619 if (!(func->flags & GNM_FUNC_IS_WORKBOOK_LOCAL))
620 g_hash_table_insert (functions_by_name,
621 (gpointer)(func->name), func);
623 return func;
626 /* Handle unknown functions on import without losing their names */
627 static GnmValue *
628 unknownFunctionHandler (GnmFuncEvalInfo *ei,
629 G_GNUC_UNUSED int argc,
630 G_GNUC_UNUSED GnmExprConstPtr const *argv)
632 return value_new_error_NAME (ei->pos);
635 static char *
636 invent_name (const char *pref, GHashTable *h, const char *template)
638 static int count = 0;
639 char *name = g_utf8_strdown (pref, -1);
641 while (g_hash_table_lookup (h, name)) {
642 count++;
643 g_free (name);
644 name = g_strdup_printf (template, count);
647 return name;
650 static GnmFunc *
651 gnm_func_add_placeholder_full (Workbook *scope,
652 char const *gname, char const *lname,
653 char const *type)
655 GnmFuncDescriptor desc;
656 GnmFunc *func;
657 char const *unknown_cat_name = N_("Unknown Function");
658 gboolean copy_gname = TRUE;
659 gboolean copy_lname = TRUE;
661 g_return_val_if_fail (gname || lname, NULL);
662 g_return_val_if_fail (gname == NULL || gnm_func_lookup (gname, scope) == NULL, NULL);
663 g_return_val_if_fail (lname == NULL || gnm_func_lookup_localized (lname, scope) == NULL, NULL);
665 if (!unknown_cat)
666 unknown_cat = gnm_func_group_fetch
667 (unknown_cat_name, _(unknown_cat_name));
669 if (!gname) {
671 * This is actually a bit of a problem if we don't end up
672 * with a copy of lname (because there already is a function
673 * with that name). We're likely to save a template name,
674 * but I don't see what else to do.
676 gname = invent_name (lname, functions_by_name, "unknown%d");
677 copy_gname = FALSE;
679 if (!lname) {
680 /* xgettext: This represents a made-up translated function name. */
681 lname = invent_name (gname, functions_by_localized_name, _("unknown%d"));
682 copy_lname = FALSE;
685 if (gnm_debug_flag ("func"))
686 g_printerr ("Adding placeholder for %s (aka %s)\n", gname, lname);
688 memset (&desc, 0, sizeof (GnmFuncDescriptor));
689 desc.name = gname;
690 desc.arg_spec = NULL;
691 desc.help = NULL;
692 desc.fn_args = NULL;
693 desc.fn_nodes = &unknownFunctionHandler;
694 desc.flags = GNM_FUNC_IS_PLACEHOLDER;
695 desc.impl_status = GNM_FUNC_IMPL_STATUS_EXISTS;
696 desc.test_status = GNM_FUNC_TEST_STATUS_UNKNOWN;
698 if (scope != NULL)
699 desc.flags |= GNM_FUNC_IS_WORKBOOK_LOCAL;
700 else {
701 #if 0
702 /* WISHLIST : it would be nice to have a log if these. */
703 g_warning ("Unknown %s function : %s", type, desc.name);
704 #endif
707 func = gnm_func_add (unknown_cat, &desc, NULL);
709 if (lname) {
710 gnm_func_set_localized_name (func, lname);
711 if (!copy_lname)
712 g_free ((char *)lname);
715 if (!copy_gname)
716 g_free ((char *)gname);
718 if (scope != NULL) {
719 if (scope->sheet_local_functions == NULL)
720 scope->sheet_local_functions = g_hash_table_new_full (
721 g_str_hash, g_str_equal,
722 NULL, g_object_unref);
723 g_hash_table_insert (scope->sheet_local_functions,
724 (gpointer)func->name, func);
727 return func;
731 * gnm_func_add_placeholder:
732 * @scope: (nullable): scope to defined placeholder, %NULL for global
733 * @name: (nullable): function name
734 * @type:
736 * Returns: (transfer none): a placeholder with the given name.
738 GnmFunc *
739 gnm_func_add_placeholder (Workbook *scope,
740 char const *name, char const *type)
742 return gnm_func_add_placeholder_full (scope, name, NULL, type);
746 * gnm_func_add_placeholder_localized:
747 * @gname: (nullable): function name
748 * @lname: localized function name
750 * Returns: (transfer none): a placeholder with the given localized name.
752 GnmFunc *
753 gnm_func_add_placeholder_localized (char const *gname, char const *lname)
755 return gnm_func_add_placeholder_full (NULL, gname, lname, "?");
759 * gnm_func_lookup_or_add_placeholder:
760 * @name: function name
762 * Returns: (transfer none): a #GnmFunc named @name, either an existing
763 * one or a placeholder.
765 GnmFunc *
766 gnm_func_lookup_or_add_placeholder (char const *name)
768 GnmFunc * f = gnm_func_lookup (name, NULL);
769 if (f == NULL)
770 f = gnm_func_add_placeholder (NULL, name, "");
771 return f;
775 * gnm_func_get_name:
776 * @func: #GnmFunc to query
777 * @localized: if %TRUE, use localized name
779 * Returns: (transfer none): @func's name
781 char const *
782 gnm_func_get_name (GnmFunc const *func, gboolean localized)
784 int i;
785 GnmFunc *fd = (GnmFunc *)func;
787 g_return_val_if_fail (func != NULL, NULL);
789 if (!localized)
790 return func->name;
792 if (func->localized_name)
793 return func->localized_name;
796 * Deduce the translated names from the help texts. This
797 * code doesn't currently check for clashes in translated
798 * names.
801 gnm_func_load_if_stub (fd);
803 for (i = 0;
804 (func->localized_name == NULL &&
805 func->help &&
806 func->help[i].type != GNM_FUNC_HELP_END);
807 i++) {
808 const char *s, *sl;
809 char *U;
810 if (func->help[i].type != GNM_FUNC_HELP_NAME)
811 continue;
813 s = func->help[i].text;
814 sl = F2 (func, s);
815 if (s == sl) /* String not actually translated. */
816 continue;
818 U = split_at_colon (F2 (func, s), NULL);
819 if (U) {
820 char *lname = g_utf8_strdown (U, -1);
821 gnm_func_set_localized_name (fd, lname);
822 g_free (lname);
824 g_free (U);
827 if (!func->localized_name)
828 gnm_func_set_localized_name (fd, fd->name);
830 return func->localized_name;
834 * gnm_func_get_description:
835 * @fn_def: the fn defintion
837 * Returns: (transfer none): the description of the function
839 char const*
840 gnm_func_get_description (GnmFunc const *fn_def)
842 gint i;
843 g_return_val_if_fail (fn_def != NULL, NULL);
845 gnm_func_load_if_stub ((GnmFunc *)fn_def);
847 for (i = 0;
848 fn_def->help && fn_def->help[i].type != GNM_FUNC_HELP_END;
849 i++) {
850 const char *desc;
852 if (fn_def->help[i].type != GNM_FUNC_HELP_NAME)
853 continue;
855 desc = strchr (F2 (fn_def, fn_def->help[i].text), ':');
856 return desc ? (desc + 1) : "";
858 return "";
862 * gnm_func_count_args:
863 * @fn_def: pointer to function definition
864 * @min: (out): location for mininum args
865 * @max: (out): location for mininum args
867 * This calculates the maximum and minimum number of args that can be passed.
868 * For a vararg function, the maximum will be set to G_MAXINT.
870 void
871 gnm_func_count_args (GnmFunc const *fn_def, int *min, int *max)
873 g_return_if_fail (min != NULL);
874 g_return_if_fail (max != NULL);
875 g_return_if_fail (fn_def != NULL);
877 gnm_func_load_if_stub ((GnmFunc *)fn_def);
879 switch (fn_def->fn_type) {
880 case GNM_FUNC_TYPE_NODES:
881 *min = 0;
882 // Really?
883 if (g_ascii_strcasecmp ("INDEX",fn_def->name) == 0)
884 *max = 4;
885 else
886 *max = G_MAXINT;
887 return;
889 case GNM_FUNC_TYPE_ARGS: {
890 const char *ptr = fn_def->fn.args.arg_spec;
891 int i, vararg;
893 for (i = vararg = 0; ptr && *ptr; ptr++) {
894 if (*ptr == '|') {
895 vararg = 1;
896 *min = i;
897 } else
898 i++;
900 *max = i;
901 if (!vararg)
902 *min = i;
903 return;
906 default:
907 *min = 0;
908 *max = G_MAXINT;
909 return;
914 * gnm_func_get_arg_type:
915 * @fn_def: the fn defintion
916 * @arg_idx: zero based argument offset
918 * Returns: the type of the argument
920 char
921 gnm_func_get_arg_type (GnmFunc const *fn_def, int arg_idx)
923 char const *ptr;
925 g_return_val_if_fail (arg_idx >= 0, '?');
926 g_return_val_if_fail (fn_def != NULL, '?');
928 gnm_func_load_if_stub ((GnmFunc *)fn_def);
930 switch (fn_def->fn_type) {
931 case GNM_FUNC_TYPE_ARGS:
932 for (ptr = fn_def->fn.args.arg_spec; ptr && *ptr; ptr++) {
933 if (*ptr == '|')
934 continue;
935 if (arg_idx-- == 0)
936 return *ptr;
938 return '?';
940 case GNM_FUNC_TYPE_NODES:
941 return '?'; /* Close enough for now. */
943 case GNM_FUNC_TYPE_STUB:
944 #ifndef DEBUG_SWITCH_ENUM
945 default:
946 #endif
947 g_assert_not_reached ();
948 return '?';
953 * gnm_func_get_arg_type_string:
954 * @fn_def: the fn defintion
955 * @arg_idx: zero based argument offset
957 * Return value: (transfer none): the type of the argument as a string
959 char const *
960 gnm_func_get_arg_type_string (GnmFunc const *fn_def,
961 int arg_idx)
963 switch (gnm_func_get_arg_type (fn_def, arg_idx)) {
964 case 'f':
965 return _("Number");
966 case 's':
967 return _("String");
968 case 'b':
969 return _("Boolean");
970 case 'r':
971 return _("Cell Range");
972 case 'A':
973 return _("Area");
974 case 'E':
975 return _("Scalar, Blank, or Error");
976 case 'S':
977 return _("Scalar");
978 case '?':
979 /* Missing values will be NULL. */
980 return _("Any");
982 default:
983 g_warning ("Unknown arg type");
984 return "Broken";
989 * gnm_func_get_arg_name:
990 * @fn_def: the fn defintion
991 * @arg_idx: zero based argument offset
993 * Returns: (transfer full): the name of the argument
995 char *
996 gnm_func_get_arg_name (GnmFunc const *fn_def, guint arg_idx)
998 g_return_val_if_fail (fn_def != NULL, NULL);
1000 gnm_func_load_if_stub ((GnmFunc *)fn_def);
1002 if ((fn_def->arg_names_p != NULL)
1003 && (arg_idx < fn_def->arg_names_p->len))
1004 return g_strdup (g_ptr_array_index (fn_def->arg_names_p,
1005 arg_idx));
1006 return NULL;
1010 * gnm_func_get_arg_description:
1011 * @fn_def: the fn defintion
1012 * @arg_idx: zero based argument offset
1014 * Returns: (transfer none): the description of the argument
1016 char const*
1017 gnm_func_get_arg_description (GnmFunc const *fn_def, guint arg_idx)
1019 gint i;
1020 g_return_val_if_fail (fn_def != NULL, NULL);
1022 gnm_func_load_if_stub ((GnmFunc *)fn_def);
1024 for (i = 0;
1025 fn_def->help && fn_def->help[i].type != GNM_FUNC_HELP_END;
1026 i++) {
1027 gchar const *desc;
1029 if (fn_def->help[i].type != GNM_FUNC_HELP_ARG)
1030 continue;
1031 if (arg_idx--)
1032 continue;
1034 desc = strchr (F2 (fn_def, fn_def->help[i].text), ':');
1035 if (!desc)
1036 return "";
1038 desc++;
1039 while (g_unichar_isspace (g_utf8_get_char (desc)))
1040 desc = g_utf8_next_char (desc);
1041 return desc;
1044 return "";
1048 * gnm_func_convert_markup_to_pango:
1049 * @desc: the fn or arg description string
1050 * @target: target widget for the markup.
1052 * Return value: the escaped string with @{} markup converted to
1053 * pango markup
1055 char *
1056 gnm_func_convert_markup_to_pango (char const *desc, GtkWidget *target)
1058 GString *str;
1059 gchar *markup, *at;
1060 GdkRGBA link_color;
1061 PangoColor pg;
1062 char *link_color_text, *span_text;
1063 size_t span_text_len;
1065 gnm_get_link_color (target, &link_color);
1066 pg.red = 65535 * link_color.red;
1067 pg.green = 65535 * link_color.green;
1068 pg.blue = 65535 * link_color.blue;
1069 link_color_text = pango_color_to_string (&pg);
1070 span_text = g_strdup_printf ("<span foreground=\"%s\">",
1071 link_color_text);
1072 span_text_len = strlen (span_text);
1073 g_free (link_color_text);
1075 markup = g_markup_escape_text (desc, -1);
1076 str = g_string_new (markup);
1077 g_free (markup);
1079 while ((at = strstr (str->str, "@{"))) {
1080 gint len = at - str->str;
1081 go_string_replace (str, len, 2, span_text, -1);
1082 if ((at = strstr
1083 (str->str + len + span_text_len, "}"))) {
1084 len = at - str->str;
1085 go_string_replace (str, len, 1, "</span>", -1);
1086 } else
1087 g_string_append (str, "</span>");
1089 g_free (span_text);
1091 return g_string_free (str, FALSE);
1095 /* ------------------------------------------------------------------------- */
1097 static inline void
1098 free_values (GnmValue **values, int top)
1100 int i;
1102 for (i = 0; i < top; i++)
1103 if (values [i])
1104 value_release (values [i]);
1107 /* ------------------------------------------------------------------------- */
1110 * function_call_with_exprs:
1111 * @ei: EvalInfo containing valid fn_def!
1113 * Do the guts of calling a function.
1115 * Returns the result.
1117 GnmValue *
1118 function_call_with_exprs (GnmFuncEvalInfo *ei)
1120 GnmFunc const *fn_def;
1121 int i, iter_count, iter_width = 0, iter_height = 0;
1122 char arg_type;
1123 GnmValue **args, *tmp = NULL;
1124 int *iter_item = NULL;
1125 int argc;
1126 GnmExprConstPtr *argv;
1127 GnmExprEvalFlags flags, pass_flags;
1129 g_return_val_if_fail (ei != NULL, NULL);
1130 g_return_val_if_fail (ei->func_call != NULL, NULL);
1132 flags = ei->flags;
1134 argc = ei->func_call->argc;
1135 argv = ei->func_call->argv;
1136 fn_def = ei->func_call->func;
1138 gnm_func_load_if_stub ((GnmFunc *)fn_def);
1140 /* Functions that deal with ExprNodes */
1141 if (fn_def->fn_type == GNM_FUNC_TYPE_NODES)
1142 return fn_def->fn.nodes (ei, argc, argv);
1144 /* Functions that take pre-computed Values */
1145 if (argc > fn_def->fn.args.max_args ||
1146 argc < fn_def->fn.args.min_args)
1147 return value_new_error_NA (ei->pos);
1149 args = g_alloca (sizeof (GnmValue *) * fn_def->fn.args.max_args);
1150 iter_count = (eval_pos_is_array_context (ei->pos) &&
1151 (flags & GNM_EXPR_EVAL_PERMIT_NON_SCALAR))
1152 ? 0 : -1;
1154 /* Optimization for IF when implicit iteration is not used. */
1155 if (ei->func_call->func->fn.args.func == gnumeric_if &&
1156 iter_count == -1)
1157 return gnumeric_if2 (ei, argc, argv, flags);
1159 pass_flags = (flags &
1160 (GNM_EXPR_EVAL_ARRAY_CONTEXT));
1162 for (i = 0; i < argc; i++) {
1163 char arg_type = fn_def->fn.args.arg_types[i];
1164 /* expr is always non-null, missing args are encoded as
1165 * const = empty */
1166 GnmExpr const *expr = argv[i];
1168 if (arg_type == 'A' || arg_type == 'r') {
1169 tmp = args[i] = gnm_expr_eval
1170 (expr, ei->pos,
1171 pass_flags |
1172 GNM_EXPR_EVAL_PERMIT_NON_SCALAR |
1173 GNM_EXPR_EVAL_WANT_REF);
1174 if (VALUE_IS_ERROR (tmp)) {
1175 free_values (args, i);
1176 return tmp;
1179 if (VALUE_IS_CELLRANGE (tmp)) {
1180 gnm_cellref_make_abs (&tmp->v_range.cell.a,
1181 &tmp->v_range.cell.a,
1182 ei->pos);
1183 gnm_cellref_make_abs (&tmp->v_range.cell.b,
1184 &tmp->v_range.cell.b,
1185 ei->pos);
1186 /* Array args accept scalars */
1187 } else if (arg_type != 'A' && !VALUE_IS_ARRAY (tmp)) {
1188 free_values (args, i + 1);
1189 return value_new_error_VALUE (ei->pos);
1191 continue;
1194 /* force scalars whenever we are certain */
1195 tmp = args[i] = gnm_expr_eval
1196 (expr, ei->pos,
1197 pass_flags |
1198 GNM_EXPR_EVAL_PERMIT_EMPTY |
1199 (iter_count >= 0 || arg_type == '?'
1200 ? GNM_EXPR_EVAL_PERMIT_NON_SCALAR
1201 : 0));
1203 if (arg_type == '?') /* '?' arguments are unrestriced */
1204 continue;
1206 /* optional arguments can be blank */
1207 if (i >= fn_def->fn.args.min_args && VALUE_IS_EMPTY (tmp)) {
1208 if (arg_type == 'E' && !gnm_expr_is_empty (expr)) {
1209 /* An actual argument produced empty. Make
1210 sure function sees that. */
1211 args[i] = value_new_empty ();
1214 continue;
1217 if (tmp == NULL)
1218 tmp = args[i] = value_new_empty ();
1220 /* Handle implicit intersection or iteration depending on flags */
1221 if (VALUE_IS_CELLRANGE (tmp) || VALUE_IS_ARRAY (tmp)) {
1222 if (iter_count > 0) {
1223 if (iter_width != value_area_get_width (tmp, ei->pos) ||
1224 iter_height != value_area_get_height (tmp, ei->pos)) {
1225 free_values (args, i + 1);
1226 return value_new_error_VALUE (ei->pos);
1228 } else {
1229 if (iter_count < 0) {
1230 g_warning ("Damn I thought this was impossible");
1231 iter_count = 0;
1233 iter_item = g_alloca (sizeof (int) * argc);
1234 iter_width = value_area_get_width (tmp, ei->pos);
1235 iter_height = value_area_get_height (tmp, ei->pos);
1237 iter_item [iter_count++] = i;
1239 /* no need to check type, we would fail comparing a range against a "b, f, or s" */
1240 continue;
1243 /* All of these argument types must be scalars */
1244 switch (arg_type) {
1245 case 'b':
1246 if (VALUE_IS_STRING (tmp)) {
1247 gboolean err;
1248 gboolean b = value_get_as_bool (tmp, &err);
1249 if (err) {
1250 free_values (args, i + 1);
1251 return value_new_error_VALUE (ei->pos);
1253 value_release (args[i]);
1254 tmp = args[i] = value_new_bool (b);
1255 break;
1257 /* Fall through. */
1258 case 'f':
1259 if (VALUE_IS_STRING (tmp)) {
1260 tmp = format_match_number (value_peek_string (tmp), NULL,
1261 sheet_date_conv (ei->pos->sheet));
1262 if (tmp == NULL) {
1263 free_values (args, i + 1);
1264 return value_new_error_VALUE (ei->pos);
1266 value_release (args [i]);
1267 args[i] = tmp;
1268 } else if (VALUE_IS_ERROR (tmp)) {
1269 free_values (args, i);
1270 return tmp;
1271 } else if (VALUE_IS_EMPTY (tmp)) {
1272 value_release (args [i]);
1273 tmp = args[i] = value_new_int (0);
1276 if (!VALUE_IS_NUMBER (tmp))
1277 return value_new_error_VALUE (ei->pos);
1278 break;
1280 case 's':
1281 case 'S':
1282 if (VALUE_IS_ERROR (tmp)) {
1283 free_values (args, i);
1284 return tmp;
1286 break;
1288 case 'E': /* nothing necessary */
1289 break;
1291 /* case '?': handled above */
1292 default:
1293 g_warning ("Unknown argument type '%c'", arg_type);
1294 break;
1298 while (i < fn_def->fn.args.max_args)
1299 args [i++] = NULL;
1301 if (iter_item != NULL) {
1302 int x, y;
1303 GnmValue *res = value_new_array_empty (iter_width, iter_height);
1304 GnmValue const *elem, *err;
1305 GnmValue **iter_vals = g_alloca (sizeof (GnmValue *) * iter_count);
1306 GnmValue **iter_args = g_alloca (sizeof (GnmValue *) * iter_count);
1308 /* collect the args we will iterate on */
1309 for (i = 0 ; i < iter_count; i++)
1310 iter_vals[i] = args[iter_item[i]];
1312 for (x = iter_width; x-- > 0 ; )
1313 for (y = iter_height; y-- > 0 ; ) {
1314 /* marshal the args */
1315 err = NULL;
1316 for (i = 0 ; i < iter_count; i++) {
1317 elem = value_area_get_x_y (iter_vals[i], x, y, ei->pos);
1318 arg_type = fn_def->fn.args.arg_types[iter_item[i]];
1319 if (arg_type == 'b' || arg_type == 'f') {
1320 if (VALUE_IS_EMPTY (elem))
1321 elem = value_zero;
1322 else if (VALUE_IS_STRING (elem)) {
1323 tmp = format_match_number (value_peek_string (elem), NULL,
1324 sheet_date_conv (ei->pos->sheet));
1325 if (tmp != NULL) {
1326 args [iter_item[i]] = iter_args [i] = tmp;
1327 continue;
1328 } else
1329 break;
1330 } else if (VALUE_IS_ERROR (elem)) {
1331 err = elem;
1332 break;
1333 } else if (!VALUE_IS_NUMBER (elem))
1334 break;
1335 } else if (arg_type == 's') {
1336 if (VALUE_IS_EMPTY (elem)) {
1337 args [iter_item[i]] = iter_args [i] = value_new_string ("");
1338 continue;
1339 } else if (VALUE_IS_ERROR (elem)) {
1340 err = elem;
1341 break;
1342 } else if (!VALUE_IS_STRING (elem))
1343 break;
1344 } else if (elem == NULL) {
1345 args [iter_item[i]] = iter_args [i] = value_new_empty ();
1346 continue;
1348 args [iter_item[i]] = iter_args [i] = value_dup (elem);
1351 res->v_array.vals[x][y] = (i == iter_count)
1352 ? fn_def->fn.args.func (ei, (GnmValue const * const *)args)
1353 : ((err != NULL) ? value_dup (err)
1354 : value_new_error_VALUE (ei->pos));
1355 free_values (iter_args, i);
1358 /* free the primaries, not the already freed iteration */
1359 for (i = 0 ; i < iter_count; i++)
1360 args[iter_item[i]] = iter_vals[i];
1361 tmp = res;
1362 i = fn_def->fn.args.max_args;
1363 } else
1364 tmp = fn_def->fn.args.func (ei, (GnmValue const * const *)args);
1366 free_values (args, i);
1367 return tmp;
1371 * Use this to invoke a register function: the only drawback is that
1372 * you have to compute/expand all of the values to use this
1374 GnmValue *
1375 function_call_with_values (GnmEvalPos const *ep, char const *fn_name,
1376 int argc, GnmValue const * const *values)
1378 GnmFunc *fn_def;
1380 g_return_val_if_fail (ep != NULL, NULL);
1381 g_return_val_if_fail (fn_name != NULL, NULL);
1382 g_return_val_if_fail (ep->sheet != NULL, NULL);
1384 /* FIXME : support workbook local functions */
1385 fn_def = gnm_func_lookup (fn_name, NULL);
1386 if (fn_def == NULL)
1387 return value_new_error_NAME (ep);
1388 return function_def_call_with_values (ep, fn_def, argc, values);
1391 GnmValue *
1392 function_def_call_with_values (GnmEvalPos const *ep, GnmFunc const *fn_def,
1393 int argc, GnmValue const * const *values)
1395 GnmValue *retval;
1396 GnmExprFunction ef;
1397 GnmFuncEvalInfo fs;
1399 fs.pos = ep;
1400 fs.func_call = &ef;
1401 ef.func = (GnmFunc *)fn_def;
1403 gnm_func_load_if_stub ((GnmFunc *)fn_def);
1405 if (fn_def->fn_type == GNM_FUNC_TYPE_NODES) {
1407 * If function deals with ExprNodes, create some
1408 * temporary ExprNodes with constants.
1410 GnmExprConstant *expr = g_new (GnmExprConstant, argc);
1411 GnmExprConstPtr *argv = g_new (GnmExprConstPtr, argc);
1412 int i;
1414 for (i = 0; i < argc; i++) {
1415 gnm_expr_constant_init (expr + i, values[i]);
1416 argv[i] = (GnmExprConstPtr)(expr + i);
1418 retval = fn_def->fn.nodes (&fs, argc, argv);
1419 g_free (argv);
1420 g_free (expr);
1421 } else
1422 retval = fn_def->fn.args.func (&fs, values);
1424 return retval;
1427 /* ------------------------------------------------------------------------- */
1429 typedef struct {
1430 FunctionIterateCB callback;
1431 void *closure;
1432 gboolean strict;
1433 gboolean ignore_subtotal;
1434 } IterateCallbackClosure;
1437 * cb_iterate_cellrange:
1439 * Helper routine used by the function_iterate_do_value routine.
1440 * Invoked by the sheet cell range iterator.
1442 static GnmValue *
1443 cb_iterate_cellrange (GnmCellIter const *iter, gpointer user)
1446 IterateCallbackClosure *data = user;
1447 GnmCell *cell;
1448 GnmValue *res;
1449 GnmEvalPos ep;
1451 if (NULL == (cell = iter->cell)) {
1452 ep.sheet = iter->pp.sheet;
1453 ep.dep = NULL;
1454 ep.eval.col = iter->pp.eval.col;
1455 ep.eval.row = iter->pp.eval.row;
1456 return (*data->callback)(&ep, NULL, data->closure);
1459 if (data->ignore_subtotal && gnm_cell_has_expr (cell) &&
1460 gnm_expr_top_contains_subtotal (cell->base.texpr))
1461 return NULL;
1463 gnm_cell_eval (cell);
1464 eval_pos_init_cell (&ep, cell);
1466 /* If we encounter an error for the strict case, short-circuit here. */
1467 if (data->strict && (NULL != (res = gnm_cell_is_error (cell))))
1468 return value_new_error_str (&ep, res->v_err.mesg);
1470 /* All other cases -- including error -- just call the handler. */
1471 return (*data->callback)(&ep, cell->value, data->closure);
1475 * function_iterate_do_value:
1477 * Helper routine for function_iterate_argument_values.
1479 static GnmValue *
1480 function_iterate_do_value (GnmEvalPos const *ep,
1481 FunctionIterateCB callback,
1482 gpointer closure,
1483 GnmValue const *value,
1484 gboolean strict,
1485 CellIterFlags iter_flags)
1487 GnmValue *res = NULL;
1489 switch (value->v_any.type){
1490 case VALUE_ERROR:
1491 if (strict) {
1492 res = value_dup (value);
1493 break;
1495 /* Fall through. */
1497 case VALUE_EMPTY:
1498 case VALUE_BOOLEAN:
1499 case VALUE_FLOAT:
1500 case VALUE_STRING:
1501 res = (*callback)(ep, value, closure);
1502 break;
1504 case VALUE_ARRAY: {
1505 int x, y;
1507 /* Note the order here. */
1508 for (y = 0; y < value->v_array.y; y++) {
1509 for (x = 0; x < value->v_array.x; x++) {
1510 res = function_iterate_do_value (
1511 ep, callback, closure,
1512 value->v_array.vals [x][y],
1513 strict, CELL_ITER_IGNORE_BLANK);
1514 if (res != NULL)
1515 return res;
1518 break;
1520 case VALUE_CELLRANGE: {
1521 IterateCallbackClosure data;
1523 data.callback = callback;
1524 data.closure = closure;
1525 data.strict = strict;
1526 data.ignore_subtotal = (iter_flags & CELL_ITER_IGNORE_SUBTOTAL) != 0;
1528 res = workbook_foreach_cell_in_range (ep, value, iter_flags,
1529 cb_iterate_cellrange,
1530 &data);
1533 return res;
1537 * function_iterate_argument_values:
1538 * @ep: The position in a workbook at which to evaluate
1539 * @callback: (scope call): The routine to be invoked for every value computed
1540 * @callback_closure: Closure for the callback.
1541 * @argc:
1542 * @argv:
1543 * @strict: If TRUE, the function is considered "strict". This means
1544 * that if an error value occurs as an argument, the iteration
1545 * will stop and that error will be returned. If FALSE, an
1546 * error will be passed on to the callback (as a GnmValue *
1547 * of type VALUE_ERROR).
1548 * @iter_flags:
1550 * Return value:
1551 * NULL : if no errors were reported.
1552 * GnmValue * : if an error was found during strict evaluation
1553 * VALUE_TERMINATE : if the callback requested termination of the iteration.
1555 * This routine provides a simple way for internal functions with variable
1556 * number of arguments to be written: this would iterate over a list of
1557 * expressions (expr_node_list) and will invoke the callback for every
1558 * GnmValue found on the list (this means that ranges get properly expaned).
1560 GnmValue *
1561 function_iterate_argument_values (GnmEvalPos const *ep,
1562 FunctionIterateCB callback,
1563 void *callback_closure,
1564 int argc,
1565 GnmExprConstPtr const *argv,
1566 gboolean strict,
1567 CellIterFlags iter_flags)
1569 GnmValue *result = NULL;
1570 int a;
1572 for (a = 0; result == NULL && a < argc; a++) {
1573 GnmExpr const *expr = argv[a];
1574 GnmValue *val;
1576 if (iter_flags & CELL_ITER_IGNORE_SUBTOTAL &&
1577 gnm_expr_contains_subtotal (expr))
1578 continue;
1580 /* need to drill down into names to handle things like
1581 * sum(name) with name := (A:A,B:B) */
1582 while (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_NAME) {
1583 GnmExprTop const *texpr = expr->name.name->texpr;
1584 expr = texpr ? texpr->expr : NULL;
1585 if (expr == NULL) {
1586 if (strict)
1587 return value_new_error_REF (ep);
1588 break;
1591 if (!expr)
1592 continue;
1594 /* Handle sets as a special case */
1595 if (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_SET) {
1596 result = function_iterate_argument_values
1597 (ep, callback, callback_closure,
1598 expr->set.argc, expr->set.argv,
1599 strict, iter_flags);
1600 continue;
1603 /* We need a cleaner model of what to do here.
1604 * In non-array mode
1605 * SUM(Range)
1606 * will obviously return Range
1608 * SUM(INDIRECT(Range))
1609 * SUM(INDIRECT(Range):....)
1610 * will do implicit intersection on Range (in non-array mode),
1611 * but allow non-scalar results from indirect (no intersection)
1613 * SUM(Range=3)
1614 * will do implicit intersection in non-array mode */
1615 if (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_CONSTANT)
1616 val = value_dup (expr->constant.value);
1617 else if (eval_pos_is_array_context (ep) ||
1618 GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_FUNCALL ||
1619 GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_RANGE_CTOR ||
1620 GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_INTERSECT)
1621 val = gnm_expr_eval (expr, ep,
1622 GNM_EXPR_EVAL_PERMIT_EMPTY | GNM_EXPR_EVAL_PERMIT_NON_SCALAR);
1623 else
1624 val = gnm_expr_eval (expr, ep, GNM_EXPR_EVAL_PERMIT_EMPTY);
1626 if (val == NULL)
1627 continue;
1629 if (strict && VALUE_IS_ERROR (val)) {
1630 /* Be careful not to make VALUE_TERMINATE into a real value */
1631 return val;
1634 result = function_iterate_do_value (ep, callback, callback_closure,
1635 val, strict, iter_flags);
1636 value_release (val);
1638 return result;
1643 * gnm_eval_info_get_func:
1644 * @ei: #GnmFuncEvalInfo
1646 * Returns: (transfer none): the called function.
1648 GnmFunc const *
1649 gnm_eval_info_get_func (GnmFuncEvalInfo const *ei)
1651 return ei->func_call->func;
1655 gnm_eval_info_get_arg_count (GnmFuncEvalInfo const *ei)
1657 return ei->func_call->argc;
1660 GnmDependentFlags
1661 gnm_func_link_dep (GnmFunc *func, GnmFuncEvalInfo *ei, gboolean qlink)
1663 int res = DEPENDENT_NO_FLAG;
1664 g_signal_emit (func, signals[SIG_LINK_DEP], 0, ei, qlink, &res);
1665 return (GnmDependentFlags)res;
1668 /* ------------------------------------------------------------------------- */
1670 static GObjectClass *parent_class;
1672 typedef struct {
1673 GObjectClass parent;
1675 void (*load_stub) (GnmFunc *func);
1676 int (*link_dep) (GnmFunc *func, GnmFuncEvalInfo *ei, gboolean qlink);
1677 } GnmFuncClass;
1679 static void
1680 gnm_func_finalize (GObject *obj)
1682 GnmFunc *func = GNM_FUNC (obj);
1684 if (func->usage_count != 0) {
1685 g_printerr ("Function %s still has a usage count of %d\n",
1686 func->name, func->usage_count);
1689 if (func->fn_group) {
1690 gnm_func_group_remove_func (func->fn_group, func);
1691 func->fn_group = NULL;
1694 gnm_func_set_localized_name (func, NULL);
1696 if (!(func->flags & GNM_FUNC_IS_WORKBOOK_LOCAL)) {
1697 g_hash_table_remove (functions_by_name, func->name);
1700 if (func->fn_type == GNM_FUNC_TYPE_ARGS)
1701 g_free (func->fn.args.arg_types);
1703 g_free ((char *)func->name);
1705 go_string_unref (func->tdomain);
1707 gnm_func_clear_arg_names (func);
1709 parent_class->finalize (obj);
1712 static void
1713 gnm_func_get_property (GObject *object, guint property_id,
1714 GValue *value, GParamSpec *pspec)
1716 GnmFunc *func = (GnmFunc *)object;
1718 switch (property_id) {
1719 case PROP_NAME:
1720 g_value_set_string (value, func->name);
1721 break;
1722 case PROP_TRANSLATION_DOMAIN:
1723 g_value_set_string (value, func->tdomain->str);
1724 break;
1725 case PROP_IN_USE:
1726 g_value_set_boolean (value, func->usage_count > 0);
1727 break;
1728 default:
1729 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1730 break;
1734 static void
1735 gnm_func_set_property (GObject *object, guint property_id,
1736 GValue const *value, GParamSpec *pspec)
1738 GnmFunc *func = (GnmFunc *)object;
1740 switch (property_id) {
1741 case PROP_NAME:
1742 func->name = g_value_dup_string (value);
1743 break;
1744 case PROP_TRANSLATION_DOMAIN:
1745 gnm_func_set_translation_domain (func,
1746 g_value_get_string (value));
1747 break;
1748 default:
1749 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1750 break;
1754 static void
1755 gnm_func_init (GnmFunc *func)
1757 func->tdomain = go_string_new (GETTEXT_PACKAGE);
1760 static void
1761 gnm_func_class_init (GObjectClass *gobject_class)
1763 parent_class = g_type_class_peek_parent (gobject_class);
1765 gobject_class->finalize = gnm_func_finalize;
1766 gobject_class->get_property = gnm_func_get_property;
1767 gobject_class->set_property = gnm_func_set_property;
1769 g_object_class_install_property (gobject_class, PROP_NAME,
1770 g_param_spec_string ("name",
1771 P_("Name"),
1772 P_("The name of the function."),
1773 NULL,
1774 GSF_PARAM_STATIC |
1775 G_PARAM_READWRITE |
1776 G_PARAM_CONSTRUCT_ONLY));
1778 g_object_class_install_property (gobject_class, PROP_TRANSLATION_DOMAIN,
1779 g_param_spec_string ("translation-domain",
1780 P_("Translation Domain"),
1781 P_("The translation domain for help texts"),
1782 NULL,
1783 GSF_PARAM_STATIC |
1784 G_PARAM_READWRITE));
1786 g_object_class_install_property (gobject_class, PROP_IN_USE,
1787 g_param_spec_boolean ("in-use",
1788 P_("In use"),
1789 P_("Is function being used?"),
1790 FALSE,
1791 GSF_PARAM_STATIC |
1792 G_PARAM_READABLE));
1794 signals[SIG_LOAD_STUB] = g_signal_new
1795 ("load-stub",
1796 GNM_FUNC_TYPE,
1797 G_SIGNAL_RUN_LAST,
1798 G_STRUCT_OFFSET (GnmFuncClass, load_stub),
1799 NULL, NULL,
1800 g_cclosure_marshal_VOID__VOID,
1801 G_TYPE_NONE, 0);
1804 signals[SIG_LINK_DEP] = g_signal_new
1805 ("link-dep",
1806 GNM_FUNC_TYPE,
1807 G_SIGNAL_RUN_LAST,
1808 G_STRUCT_OFFSET (GnmFuncClass, link_dep),
1809 NULL, NULL,
1810 gnm__INT__POINTER_BOOLEAN,
1811 // GnmDependentFlags ... GnmFuncEvalInfo
1812 G_TYPE_INT, 2, G_TYPE_POINTER, G_TYPE_BOOLEAN);
1815 GSF_CLASS (GnmFunc, gnm_func,
1816 gnm_func_class_init, gnm_func_init, G_TYPE_OBJECT)