GnmFunc: fix python loader and function defintion
[gnumeric.git] / src / func.c
blob5eea7afa9a25563db41ea0df930057f02d08e760
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 */
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>
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 <gnm-marshalers.h>
35 #include <goffice/goffice.h>
36 #include <glib.h>
37 #include <string.h>
38 #include <stdlib.h>
40 enum {
41 PROP_0,
42 PROP_NAME,
43 PROP_TRANSLATION_DOMAIN,
44 PROP_IN_USE,
47 enum {
48 SIG_LOAD_STUB,
49 SIG_LINK_DEP,
50 LAST_SIGNAL
52 static guint signals[LAST_SIGNAL] = { 0 };
55 #define F2(func,s) dgettext ((func)->tdomain->str, (s))
57 static GList *categories;
58 static GnmFuncGroup *unknown_cat;
60 static GHashTable *functions_by_name;
61 static GHashTable *functions_by_localized_name;
63 /**
64 * functions_init: (skip)
66 void
67 functions_init (void)
69 functions_by_name =
70 g_hash_table_new (go_ascii_strcase_hash, go_ascii_strcase_equal);
72 /* FIXME: ascii??? */
73 functions_by_localized_name =
74 g_hash_table_new (go_ascii_strcase_hash, go_ascii_strcase_equal);
76 func_builtin_init ();
79 /**
80 * functions_shutdown: (skip)
82 void
83 functions_shutdown (void)
85 while (unknown_cat != NULL && unknown_cat->functions != NULL) {
86 GnmFunc *func = unknown_cat->functions->data;
87 if (func->usage_count > 0) {
88 g_warning ("Function %s still has %d users.\n",
89 gnm_func_get_name (func, FALSE),
90 func->usage_count);
91 func->usage_count = 0;
93 g_object_unref (func);
95 func_builtin_shutdown ();
97 g_hash_table_destroy (functions_by_name);
98 functions_by_name = NULL;
100 g_hash_table_destroy (functions_by_localized_name);
101 functions_by_localized_name = NULL;
105 * gnm_func_enumerate:
107 * Return value: (element-type GnmFunc) (transfer container):
109 GPtrArray *
110 gnm_func_enumerate (void)
112 GPtrArray *res = g_ptr_array_new ();
113 GHashTableIter hiter;
114 gpointer value;
116 g_hash_table_iter_init (&hiter, functions_by_name);
117 while (g_hash_table_iter_next (&hiter, NULL, &value))
118 g_ptr_array_add (res, value);
120 return res;
123 static GnmValue *
124 error_function_no_full_info (GnmFuncEvalInfo *ei,
125 int argc,
126 GnmExprConstPtr const *argv)
128 return value_new_error (ei->pos, _("Function implementation not available."));
131 static void
132 gnm_func_load_stub (GnmFunc *func)
134 g_return_if_fail (func->fn_type == GNM_FUNC_TYPE_STUB);
136 g_signal_emit (G_OBJECT (func), signals[SIG_LOAD_STUB], 0);
138 if (func->fn_type == GNM_FUNC_TYPE_STUB) {
139 static GnmFuncHelp const no_help[] = { { GNM_FUNC_HELP_END } };
140 gnm_func_set_varargs (func, error_function_no_full_info);
141 func->help = no_help;
145 inline void
146 gnm_func_load_if_stub (GnmFunc *func)
148 if (func->fn_type == GNM_FUNC_TYPE_STUB)
149 gnm_func_load_stub (func);
152 static char *
153 split_at_colon (char const *s, char **rest)
155 char *dup = g_strdup (s);
156 char *colon = strchr (dup, ':');
157 if (colon) {
158 *colon = 0;
159 if (rest) *rest = colon + 1;
160 } else {
161 if (rest) *rest = NULL;
163 return dup;
166 /* ------------------------------------------------------------------------- */
168 static void
169 gnm_func_group_free (GnmFuncGroup *fn_group)
171 g_return_if_fail (fn_group != NULL);
172 g_return_if_fail (fn_group->functions == NULL);
174 if (fn_group->ref_count-- > 1)
175 return;
177 go_string_unref (fn_group->internal_name);
178 go_string_unref (fn_group->display_name);
179 g_free (fn_group);
182 static GnmFuncGroup *
183 gnm_func_group_ref (GnmFuncGroup *fn_group)
185 fn_group->ref_count++;
186 return fn_group;
189 GType
190 gnm_func_group_get_type (void)
192 static GType t = 0;
194 if (t == 0) {
195 t = g_boxed_type_register_static ("GnmFuncGroup",
196 (GBoxedCopyFunc)gnm_func_group_ref,
197 (GBoxedFreeFunc)gnm_func_group_free);
199 return t;
202 static gint
203 function_category_compare (gconstpointer a, gconstpointer b)
205 GnmFuncGroup const *cat_a = a;
206 GnmFuncGroup const *cat_b = b;
208 return go_string_cmp (cat_a->display_name, cat_b->display_name);
211 GnmFuncGroup *
212 gnm_func_group_fetch (char const *name, char const *translation)
214 GnmFuncGroup *cat = NULL;
215 GList *l;
217 g_return_val_if_fail (name != NULL, NULL);
219 for (l = categories; l != NULL; l = l->next) {
220 cat = l->data;
221 if (strcmp (cat->internal_name->str, name) == 0) {
222 break;
226 if (l == NULL) {
227 cat = g_new (GnmFuncGroup, 1);
228 cat->internal_name = go_string_new (name);
229 cat->ref_count = 1;
230 if (translation != NULL) {
231 cat->display_name = go_string_new (translation);
232 cat->has_translation = TRUE;
233 } else {
234 cat->display_name = go_string_new (name);
235 cat->has_translation = FALSE;
237 cat->functions = NULL;
238 categories = g_list_insert_sorted (
239 categories, cat, &function_category_compare);
240 } else if (translation != NULL && translation != name &&
241 !cat->has_translation) {
242 go_string_unref (cat->display_name);
243 cat->display_name = go_string_new (translation);
244 cat->has_translation = TRUE;
245 categories = g_list_remove_link (categories, l);
246 g_list_free_1 (l);
247 categories = g_list_insert_sorted (
248 categories, cat, &function_category_compare);
251 return cat;
254 GnmFuncGroup *
255 gnm_func_group_get_nth (int n)
257 return g_list_nth_data (categories, n);
260 static void
261 gnm_func_group_add_func (GnmFuncGroup *fn_group, GnmFunc *fn_def)
263 g_return_if_fail (fn_group != NULL);
264 g_return_if_fail (fn_def != NULL);
266 fn_group->functions = g_slist_prepend (fn_group->functions, fn_def);
269 static void
270 gnm_func_group_remove_func (GnmFuncGroup *fn_group, GnmFunc *fn_def)
272 g_return_if_fail (fn_group != NULL);
273 g_return_if_fail (fn_def != NULL);
275 fn_group->functions = g_slist_remove (fn_group->functions, fn_def);
276 if (fn_group->functions == NULL) {
277 categories = g_list_remove (categories, fn_group);
278 if (unknown_cat == fn_group)
279 unknown_cat = NULL;
280 gnm_func_group_free (fn_group);
284 /******************************************************************************/
286 static void
287 gnm_func_create_arg_names (GnmFunc *fn_def)
289 int i;
290 GPtrArray *ptr;
292 g_return_if_fail (fn_def != NULL);
294 ptr = g_ptr_array_new ();
295 for (i = 0;
296 fn_def->help && fn_def->help[i].type != GNM_FUNC_HELP_END;
297 i++) {
298 if (fn_def->help[i].type != GNM_FUNC_HELP_ARG)
299 continue;
301 g_ptr_array_add
302 (ptr, split_at_colon
303 (F2(fn_def, fn_def->help[i].text), NULL));
306 fn_def->arg_names = ptr;
309 gboolean
310 gnm_func_is_varargs (GnmFunc *func)
312 gnm_func_load_stub (func);
313 return func->fn_type == GNM_FUNC_TYPE_NODES;
316 gboolean
317 gnm_func_is_fixargs (GnmFunc *func)
319 gnm_func_load_stub (func);
320 return func->fn_type == GNM_FUNC_TYPE_ARGS;
323 void
324 gnm_func_set_stub (GnmFunc *func)
326 func->fn_type = GNM_FUNC_TYPE_STUB;
328 g_free (func->arg_spec);
329 func->arg_spec = NULL;
331 g_free (func->arg_types);
332 func->arg_types = NULL;
334 if (func->arg_names) {
335 g_ptr_array_foreach (func->arg_names, (GFunc)g_free, NULL);
336 g_ptr_array_free (func->arg_names, TRUE);
337 func->arg_names = NULL;
340 func->min_args = func->max_args = 0;
342 func->nodes_func = NULL;
343 func->args_func = NULL;
347 * gnm_func_set_varargs: (skip)
348 * @func: #GnmFunc
349 * @fn: evaluation function
351 void
352 gnm_func_set_varargs (GnmFunc *func, GnmFuncNodes fn)
354 g_return_if_fail (GNM_IS_FUNC (func));
355 g_return_if_fail (fn != NULL);
357 gnm_func_set_stub (func); // Clear out stuff
359 func->fn_type = GNM_FUNC_TYPE_NODES;
360 func->nodes_func = fn;
361 func->min_args = 0;
362 func->min_args = G_MAXINT;
366 * gnm_func_set_fixargs: (skip)
367 * @func: #GnmFunc
368 * @fn: evaluation function
369 * @spec: argument type specification
371 void
372 gnm_func_set_fixargs (GnmFunc *func, GnmFuncArgs fn, const char *spec)
374 char *p;
376 g_return_if_fail (GNM_IS_FUNC (func));
377 g_return_if_fail (fn != NULL);
378 g_return_if_fail (spec != NULL);
380 gnm_func_set_stub (func); // Clear out stuff
382 func->fn_type = GNM_FUNC_TYPE_ARGS;
383 func->args_func = fn;
384 func->arg_spec = g_strdup (spec);
386 func->arg_types = g_strdup (func->arg_spec);
387 p = strchr (func->arg_types, '|');
388 if (p) {
389 func->min_args = p - func->arg_types;
390 memmove (p, p + 1, strlen (p));
391 } else
392 func->min_args = 0;
393 func->max_args = strlen (func->arg_types);
395 gnm_func_create_arg_names (func);
398 static void
399 gnm_func_set_localized_name (GnmFunc *fd, const char *lname)
401 gboolean in_hashes = !(fd->flags & GNM_FUNC_IS_WORKBOOK_LOCAL);
403 if (g_strcmp0 (fd->localized_name, lname) == 0)
404 return;
406 if (in_hashes && fd->localized_name)
407 g_hash_table_remove (functions_by_localized_name, fd->localized_name);
408 g_free (fd->localized_name);
410 fd->localized_name = g_strdup (lname);
411 if (in_hashes && lname)
412 g_hash_table_insert (functions_by_localized_name,
413 fd->localized_name, fd);
417 * gnm_func_inc_usage:
418 * @func: #GnmFunc
420 * This function increments the usage count of @func. A non-zero usage count
421 * prevents the unloading of the function.
423 * Returns: (transfer full): a new reference to @func.
425 GnmFunc *
426 gnm_func_inc_usage (GnmFunc *func)
428 g_return_val_if_fail (func != NULL, NULL);
430 func->usage_count++;
431 if (func->usage_count == 1)
432 g_object_notify (G_OBJECT (func), "in-use");
433 return func;
437 * gnm_func_dec_usage:
438 * @func: (transfer full): #GnmFunc
440 * This function decrements the usage count of @func. When the usage count
441 * reaches zero, the function may be unloaded, for example by unloading the
442 * plugin that defines it.
444 void
445 gnm_func_dec_usage (GnmFunc *func)
447 g_return_if_fail (func != NULL);
448 g_return_if_fail (func->usage_count > 0);
450 func->usage_count--;
451 if (func->usage_count == 0)
452 g_object_notify (G_OBJECT (func), "in-use");
455 gboolean
456 gnm_func_get_in_use (GnmFunc *func)
458 g_return_val_if_fail (func != NULL, FALSE);
460 return func->usage_count > 0;
465 * gnm_func_lookup:
466 * @name: name of function
467 * @scope: (nullable): scope of function, %NULL for global
469 * Returns: (nullable) (transfer none): the function of that name.
471 GnmFunc *
472 gnm_func_lookup (char const *name, Workbook *scope)
474 GnmFunc *fd = g_hash_table_lookup (functions_by_name, name);
475 if (fd != NULL)
476 return fd;
477 if (scope == NULL || scope->sheet_local_functions == NULL)
478 return NULL;
479 return g_hash_table_lookup (scope->sheet_local_functions, (gpointer)name);
483 * gnm_func_lookup_localized:
484 * @name: localized name of function
485 * @scope: (nullable): scope of function, %NULL for global
487 * Returns: (nullable) (transfer none): the function of that name.
489 GnmFunc *
490 gnm_func_lookup_localized (char const *name, Workbook *scope)
492 GnmFunc *fd;
493 GHashTableIter hiter;
494 gpointer value;
496 /* Must localize all function names. */
497 g_hash_table_iter_init (&hiter, functions_by_name);
498 while (g_hash_table_iter_next (&hiter, NULL, &value)) {
499 GnmFunc *fd = value;
500 (void)gnm_func_get_name (fd, TRUE);
503 fd = g_hash_table_lookup (functions_by_localized_name, name);
504 if (fd != NULL)
505 return fd;
506 if (scope == NULL || scope->sheet_local_functions == NULL)
507 return NULL;
508 return g_hash_table_lookup (scope->sheet_local_functions, (gpointer)name);
512 * gnm_func_lookup_prefix:
513 * @prefix: prefix to search for
514 * @scope:
515 * @trans: whether to search translated function names
517 * Returns: (element-type GnmFunc*) (transfer full):
519 GSList *
520 gnm_func_lookup_prefix (char const *prefix, Workbook *scope, gboolean trans)
522 GSList *res = NULL;
523 GHashTableIter hiter;
524 gpointer value;
527 * Always iterate over functions_by_name as the localized name
528 * might not be set yet.
530 g_hash_table_iter_init (&hiter, functions_by_name);
531 while (g_hash_table_iter_next (&hiter, NULL, &value)) {
532 GnmFunc *fd = value;
533 if (!(fd->flags & GNM_FUNC_IS_PLACEHOLDER)) {
534 const char *name = gnm_func_get_name (fd, trans);
535 if (g_str_has_prefix (name, prefix)) {
536 gnm_func_inc_usage (fd);
537 res = g_slist_prepend (res, fd);
542 return res;
546 * gnm_func_get_translation_domain:
547 * @func: #GnmFunc
549 * Returns: (transfer none): the translation domain for @func's help text.
551 char const *
552 gnm_func_get_translation_domain (GnmFunc *func)
554 g_return_val_if_fail (GNM_IS_FUNC (func), NULL);
555 return func->tdomain->str;
559 * gnm_func_set_translation_domain:
560 * @func: #GnmFunc
561 * @tdomain: (nullable): Translation domain, %NULL for Gnumeric's.
563 void
564 gnm_func_set_translation_domain (GnmFunc *func, const char *tdomain)
566 g_return_if_fail (GNM_IS_FUNC (func));
568 if (!tdomain)
569 tdomain = GETTEXT_PACKAGE;
571 if (g_strcmp0 (func->tdomain->str, tdomain) == 0)
572 return;
574 go_string_unref (func->tdomain);
575 func->tdomain = go_string_new (tdomain);
577 g_object_notify (G_OBJECT (func), "translation-domain");
580 GnmFuncFlags
581 gnm_func_get_flags (GnmFunc *func)
583 g_return_val_if_fail (GNM_IS_FUNC (func), GNM_FUNC_SIMPLE);
584 return func->flags;
587 void
588 gnm_func_set_flags (GnmFunc *func, GnmFuncFlags f)
590 g_return_if_fail (GNM_IS_FUNC (func));
591 func->flags = f;
594 GnmFuncImplStatus
595 gnm_func_get_impl_status (GnmFunc *func)
597 g_return_val_if_fail (GNM_IS_FUNC (func), GNM_FUNC_IMPL_STATUS_UNIMPLEMENTED);
598 return func->impl_status;
601 void
602 gnm_func_set_impl_status (GnmFunc *func, GnmFuncImplStatus st)
604 g_return_if_fail (GNM_IS_FUNC (func));
605 func->impl_status = st;
609 GnmFuncTestStatus
610 gnm_func_get_test_status (GnmFunc *func)
612 g_return_val_if_fail (GNM_IS_FUNC (func), GNM_FUNC_TEST_STATUS_UNKNOWN);
613 return func->test_status;
616 void
617 gnm_func_set_test_status (GnmFunc *func, GnmFuncTestStatus st)
619 g_return_if_fail (GNM_IS_FUNC (func));
620 func->test_status = st;
625 * gnm_func_get_function_group:
626 * @func: #GnmFunc
628 * Returns: (transfer none): the function group to which @func belongs.
630 GnmFuncGroup *
631 gnm_func_get_function_group (GnmFunc *func)
633 g_return_val_if_fail (GNM_IS_FUNC (func), NULL);
634 return func->fn_group;
638 void
639 gnm_func_set_function_group (GnmFunc *func, GnmFuncGroup *group)
641 g_return_if_fail (GNM_IS_FUNC (func));
642 g_return_if_fail (group != NULL);
644 if (func->fn_group == group)
645 return;
647 if (func->fn_group)
648 gnm_func_group_remove_func (func->fn_group, func);
649 func->fn_group = group;
650 gnm_func_group_add_func (group, func);
652 if (group == unknown_cat)
653 func->flags |= GNM_FUNC_IS_PLACEHOLDER;
654 else
655 func->flags &= ~GNM_FUNC_IS_PLACEHOLDER;
658 void
659 gnm_func_set_from_desc (GnmFunc *func, GnmFuncDescriptor const *desc)
661 g_return_if_fail (GNM_IS_FUNC (func));
662 g_return_if_fail (desc != NULL);
664 // Not setting name, localized_name. Also not setting things not present
665 // in desc, such as translation domain.
667 if (desc->fn_args != NULL) {
668 gnm_func_set_fixargs (func, desc->fn_args, desc->arg_spec);
669 } else if (desc->fn_nodes != NULL) {
670 if (desc->arg_spec && *desc->arg_spec)
671 g_warning ("Arg spec for node function -- why?");
672 gnm_func_set_varargs (func, desc->fn_nodes);
673 } else {
674 gnm_func_set_stub (func);
675 return;
678 func->help = desc->help ? desc->help : NULL;
679 func->flags = desc->flags;
680 func->impl_status = desc->impl_status;
681 func->test_status = desc->test_status;
686 * gnm_func_add:
687 * @group:
688 * @descriptor:
689 * @tdomain: (nullable):
691 * Returns: (transfer full): a new #GnmFunc.
693 GnmFunc *
694 gnm_func_add (GnmFuncGroup *fn_group,
695 GnmFuncDescriptor const *desc,
696 const char *tdomain)
698 //static char const valid_tokens[] = "fsbraAES?|";
699 GnmFunc *func;
701 g_return_val_if_fail (fn_group != NULL, NULL);
702 g_return_val_if_fail (desc != NULL, NULL);
704 func = g_object_new (GNM_FUNC_TYPE,
705 "name", desc->name,
706 NULL);
707 gnm_func_set_translation_domain (func, tdomain);
709 gnm_func_set_from_desc (func, desc);
711 if (func->fn_type == GNM_FUNC_TYPE_STUB) {
712 g_warning ("Invalid function has neither args nor nodes handler");
713 g_object_unref (func);
714 return NULL;
717 gnm_func_set_function_group (func, fn_group);
719 if (!(func->flags & GNM_FUNC_IS_WORKBOOK_LOCAL))
720 g_hash_table_insert (functions_by_name,
721 (gpointer)(func->name), func);
723 return func;
726 /* Handle unknown functions on import without losing their names */
727 static GnmValue *
728 unknownFunctionHandler (GnmFuncEvalInfo *ei,
729 G_GNUC_UNUSED int argc,
730 G_GNUC_UNUSED GnmExprConstPtr const *argv)
732 return value_new_error_NAME (ei->pos);
735 static char *
736 invent_name (const char *pref, GHashTable *h, const char *template)
738 static int count = 0;
739 char *name = g_utf8_strdown (pref, -1);
741 while (g_hash_table_lookup (h, name)) {
742 count++;
743 g_free (name);
744 name = g_strdup_printf (template, count);
747 return name;
750 static GnmFunc *
751 gnm_func_add_placeholder_full (Workbook *scope,
752 char const *gname, char const *lname,
753 char const *type)
755 GnmFuncDescriptor desc;
756 GnmFunc *func;
757 char const *unknown_cat_name = N_("Unknown Function");
758 gboolean copy_gname = TRUE;
759 gboolean copy_lname = TRUE;
761 g_return_val_if_fail (gname || lname, NULL);
762 g_return_val_if_fail (gname == NULL || gnm_func_lookup (gname, scope) == NULL, NULL);
763 g_return_val_if_fail (lname == NULL || gnm_func_lookup_localized (lname, scope) == NULL, NULL);
765 if (!unknown_cat)
766 unknown_cat = gnm_func_group_fetch
767 (unknown_cat_name, _(unknown_cat_name));
769 if (!gname) {
771 * This is actually a bit of a problem if we don't end up
772 * with a copy of lname (because there already is a function
773 * with that name). We're likely to save a template name,
774 * but I don't see what else to do.
776 gname = invent_name (lname, functions_by_name, "unknown%d");
777 copy_gname = FALSE;
779 if (!lname) {
780 /* xgettext: This represents a made-up translated function name. */
781 lname = invent_name (gname, functions_by_localized_name, _("unknown%d"));
782 copy_lname = FALSE;
785 if (gnm_debug_flag ("func"))
786 g_printerr ("Adding placeholder for %s (aka %s)\n", gname, lname);
788 memset (&desc, 0, sizeof (GnmFuncDescriptor));
789 desc.name = gname;
790 desc.arg_spec = NULL;
791 desc.help = NULL;
792 desc.fn_args = NULL;
793 desc.fn_nodes = &unknownFunctionHandler;
794 desc.flags = GNM_FUNC_IS_PLACEHOLDER;
795 desc.impl_status = GNM_FUNC_IMPL_STATUS_EXISTS;
796 desc.test_status = GNM_FUNC_TEST_STATUS_UNKNOWN;
798 if (scope != NULL)
799 desc.flags |= GNM_FUNC_IS_WORKBOOK_LOCAL;
800 else {
801 #if 0
802 /* WISHLIST : it would be nice to have a log if these. */
803 g_warning ("Unknown %s function : %s", type, desc.name);
804 #endif
807 func = gnm_func_add (unknown_cat, &desc, NULL);
809 if (lname) {
810 gnm_func_set_localized_name (func, lname);
811 if (!copy_lname)
812 g_free ((char *)lname);
815 if (!copy_gname)
816 g_free ((char *)gname);
818 if (scope != NULL) {
819 if (scope->sheet_local_functions == NULL)
820 scope->sheet_local_functions = g_hash_table_new_full (
821 g_str_hash, g_str_equal,
822 NULL, g_object_unref);
823 g_hash_table_insert (scope->sheet_local_functions,
824 (gpointer)func->name, func);
827 return func;
831 * gnm_func_add_placeholder:
832 * @scope: (nullable): scope to defined placeholder, %NULL for global
833 * @name: (nullable): function name
834 * @type:
836 * Returns: (transfer none): a placeholder with the given name.
838 GnmFunc *
839 gnm_func_add_placeholder (Workbook *scope,
840 char const *name, char const *type)
842 return gnm_func_add_placeholder_full (scope, name, NULL, type);
846 * gnm_func_add_placeholder_localized:
847 * @gname: (nullable): function name
848 * @lname: localized function name
850 * Returns: (transfer none): a placeholder with the given localized name.
852 GnmFunc *
853 gnm_func_add_placeholder_localized (char const *gname, char const *lname)
855 return gnm_func_add_placeholder_full (NULL, gname, lname, "?");
859 * gnm_func_lookup_or_add_placeholder:
860 * @name: function name
862 * Returns: (transfer none): a #GnmFunc named @name, either an existing
863 * one or a placeholder.
865 GnmFunc *
866 gnm_func_lookup_or_add_placeholder (char const *name)
868 GnmFunc * f = gnm_func_lookup (name, NULL);
869 if (f == NULL)
870 f = gnm_func_add_placeholder (NULL, name, "");
871 return f;
875 * gnm_func_get_name:
876 * @func: #GnmFunc to query
877 * @localized: if %TRUE, use localized name
879 * Returns: (transfer none): @func's name
881 char const *
882 gnm_func_get_name (GnmFunc const *func, gboolean localized)
884 int i;
885 GnmFunc *fd = (GnmFunc *)func;
887 g_return_val_if_fail (func != NULL, NULL);
889 if (!localized)
890 return func->name;
892 if (func->localized_name)
893 return func->localized_name;
896 * Deduce the translated names from the help texts. This
897 * code doesn't currently check for clashes in translated
898 * names.
901 gnm_func_load_if_stub (fd);
903 for (i = 0;
904 (func->localized_name == NULL &&
905 func->help &&
906 func->help[i].type != GNM_FUNC_HELP_END);
907 i++) {
908 const char *s, *sl;
909 char *U;
910 if (func->help[i].type != GNM_FUNC_HELP_NAME)
911 continue;
913 s = func->help[i].text;
914 sl = F2 (func, s);
915 if (s == sl) /* String not actually translated. */
916 continue;
918 U = split_at_colon (F2 (func, s), NULL);
919 if (U) {
920 char *lname = g_utf8_strdown (U, -1);
921 gnm_func_set_localized_name (fd, lname);
922 g_free (lname);
924 g_free (U);
927 if (!func->localized_name)
928 gnm_func_set_localized_name (fd, fd->name);
930 return func->localized_name;
934 * gnm_func_get_description:
935 * @fn_def: the fn defintion
937 * Returns: (transfer none): the description of the function
939 char const *
940 gnm_func_get_description (GnmFunc const *fn_def)
942 gint i;
943 g_return_val_if_fail (fn_def != NULL, NULL);
945 gnm_func_load_if_stub ((GnmFunc *)fn_def);
947 for (i = 0;
948 fn_def->help && fn_def->help[i].type != GNM_FUNC_HELP_END;
949 i++) {
950 const char *desc;
952 if (fn_def->help[i].type != GNM_FUNC_HELP_NAME)
953 continue;
955 desc = strchr (F2 (fn_def, fn_def->help[i].text), ':');
956 return desc ? (desc + 1) : "";
958 return "";
962 * gnm_func_count_args:
963 * @fn_def: pointer to function definition
964 * @min: (out): location for mininum args
965 * @max: (out): location for mininum args
967 * This calculates the maximum and minimum number of args that can be passed.
968 * For a vararg function, the maximum will be set to G_MAXINT.
970 void
971 gnm_func_count_args (GnmFunc const *fn_def, int *min, int *max)
973 g_return_if_fail (min != NULL);
974 g_return_if_fail (max != NULL);
975 g_return_if_fail (fn_def != NULL);
977 gnm_func_load_if_stub ((GnmFunc *)fn_def);
979 *min = fn_def->min_args;
980 *max = fn_def->max_args;
984 * gnm_func_get_arg_type:
985 * @fn_def: the fn defintion
986 * @arg_idx: zero-based argument offset
988 * Returns: the type of the argument
990 char
991 gnm_func_get_arg_type (GnmFunc const *fn_def, int arg_idx)
993 g_return_val_if_fail (fn_def != NULL, '?');
995 gnm_func_load_if_stub ((GnmFunc *)fn_def);
997 g_return_val_if_fail (arg_idx >= 0 && arg_idx < fn_def->max_args, '?');
999 return fn_def->arg_types ? fn_def->arg_types[arg_idx] : '?';
1003 * gnm_func_get_arg_type_string:
1004 * @fn_def: the fn defintion
1005 * @arg_idx: zero-based argument offset
1007 * Return value: (transfer none): the type of the argument as a string
1009 char const *
1010 gnm_func_get_arg_type_string (GnmFunc const *fn_def,
1011 int arg_idx)
1013 switch (gnm_func_get_arg_type (fn_def, arg_idx)) {
1014 case 'f':
1015 return _("Number");
1016 case 's':
1017 return _("String");
1018 case 'b':
1019 return _("Boolean");
1020 case 'r':
1021 return _("Cell Range");
1022 case 'A':
1023 return _("Area");
1024 case 'E':
1025 return _("Scalar, Blank, or Error");
1026 case 'S':
1027 return _("Scalar");
1028 case '?':
1029 /* Missing values will be NULL. */
1030 return _("Any");
1032 default:
1033 g_warning ("Unknown arg type");
1034 return "Broken";
1039 * gnm_func_get_arg_name:
1040 * @func: #GnmFunc
1041 * @arg_idx: zero-based argument offset
1043 * Returns: (transfer full) (nullable): the name of the argument
1045 char *
1046 gnm_func_get_arg_name (GnmFunc const *func, guint arg_idx)
1048 g_return_val_if_fail (func != NULL, NULL);
1050 gnm_func_load_if_stub ((GnmFunc *)func);
1052 if (func->arg_names && arg_idx < func->arg_names->len)
1053 return g_strdup (g_ptr_array_index (func->arg_names, arg_idx));
1054 return NULL;
1058 * gnm_func_get_arg_description:
1059 * @fn_def: the fn defintion
1060 * @arg_idx: zero-based argument offset
1062 * Returns: (transfer none): the description of the argument
1064 char const*
1065 gnm_func_get_arg_description (GnmFunc const *fn_def, guint arg_idx)
1067 gint i;
1068 g_return_val_if_fail (fn_def != NULL, NULL);
1070 gnm_func_load_if_stub ((GnmFunc *)fn_def);
1072 for (i = 0;
1073 fn_def->help && fn_def->help[i].type != GNM_FUNC_HELP_END;
1074 i++) {
1075 gchar const *desc;
1077 if (fn_def->help[i].type != GNM_FUNC_HELP_ARG)
1078 continue;
1079 if (arg_idx--)
1080 continue;
1082 desc = strchr (F2 (fn_def, fn_def->help[i].text), ':');
1083 if (!desc)
1084 return "";
1086 desc++;
1087 while (g_unichar_isspace (g_utf8_get_char (desc)))
1088 desc = g_utf8_next_char (desc);
1089 return desc;
1092 return "";
1096 * gnm_func_convert_markup_to_pango:
1097 * @desc: the fn or arg description string
1098 * @target: target widget for the markup.
1100 * Return value: the escaped string with @{} markup converted to
1101 * pango markup
1103 char *
1104 gnm_func_convert_markup_to_pango (char const *desc, GtkWidget *target)
1106 GString *str;
1107 gchar *markup, *at;
1108 GdkRGBA link_color;
1109 PangoColor pg;
1110 char *link_color_text, *span_text;
1111 size_t span_text_len;
1113 gnm_get_link_color (target, &link_color);
1114 pg.red = 65535 * link_color.red;
1115 pg.green = 65535 * link_color.green;
1116 pg.blue = 65535 * link_color.blue;
1117 link_color_text = pango_color_to_string (&pg);
1118 span_text = g_strdup_printf ("<span foreground=\"%s\">",
1119 link_color_text);
1120 span_text_len = strlen (span_text);
1121 g_free (link_color_text);
1123 markup = g_markup_escape_text (desc, -1);
1124 str = g_string_new (markup);
1125 g_free (markup);
1127 while ((at = strstr (str->str, "@{"))) {
1128 gint len = at - str->str;
1129 go_string_replace (str, len, 2, span_text, -1);
1130 if ((at = strstr
1131 (str->str + len + span_text_len, "}"))) {
1132 len = at - str->str;
1133 go_string_replace (str, len, 1, "</span>", -1);
1134 } else
1135 g_string_append (str, "</span>");
1137 g_free (span_text);
1139 return g_string_free (str, FALSE);
1143 /* ------------------------------------------------------------------------- */
1145 static inline void
1146 free_values (GnmValue **values, int top)
1148 int i;
1150 for (i = 0; i < top; i++)
1151 if (values [i])
1152 value_release (values [i]);
1155 /* ------------------------------------------------------------------------- */
1158 * function_call_with_exprs:
1159 * @ei: EvalInfo containing valid fn_def!
1161 * Do the guts of calling a function.
1163 * Returns the result.
1165 GnmValue *
1166 function_call_with_exprs (GnmFuncEvalInfo *ei)
1168 GnmFunc const *fn_def;
1169 int i, iter_count, iter_width = 0, iter_height = 0;
1170 char arg_type;
1171 GnmValue **args, *tmp = NULL;
1172 int *iter_item = NULL;
1173 int argc;
1174 GnmExprConstPtr *argv;
1175 GnmExprEvalFlags flags, pass_flags;
1177 g_return_val_if_fail (ei != NULL, NULL);
1178 g_return_val_if_fail (ei->func_call != NULL, NULL);
1180 flags = ei->flags;
1182 argc = ei->func_call->argc;
1183 argv = ei->func_call->argv;
1184 fn_def = ei->func_call->func;
1186 gnm_func_load_if_stub ((GnmFunc *)fn_def);
1188 /* Functions that deal with ExprNodes */
1189 if (fn_def->fn_type == GNM_FUNC_TYPE_NODES)
1190 return fn_def->nodes_func (ei, argc, argv);
1192 /* Functions that take pre-computed Values */
1193 if (argc > fn_def->max_args ||
1194 argc < fn_def->min_args)
1195 return value_new_error_NA (ei->pos);
1197 args = g_alloca (sizeof (GnmValue *) * fn_def->max_args);
1198 iter_count = (eval_pos_is_array_context (ei->pos) &&
1199 (flags & GNM_EXPR_EVAL_PERMIT_NON_SCALAR))
1200 ? 0 : -1;
1202 /* Optimization for IF when implicit iteration is not used. */
1203 if (ei->func_call->func->args_func == gnumeric_if &&
1204 iter_count == -1)
1205 return gnumeric_if2 (ei, argc, argv, flags);
1207 pass_flags = (flags &
1208 (GNM_EXPR_EVAL_ARRAY_CONTEXT));
1210 for (i = 0; i < argc; i++) {
1211 char arg_type = fn_def->arg_types[i];
1212 /* expr is always non-null, missing args are encoded as
1213 * const = empty */
1214 GnmExpr const *expr = argv[i];
1216 if (arg_type == 'A' || arg_type == 'r') {
1217 tmp = args[i] = gnm_expr_eval
1218 (expr, ei->pos,
1219 pass_flags |
1220 GNM_EXPR_EVAL_PERMIT_NON_SCALAR |
1221 GNM_EXPR_EVAL_WANT_REF);
1222 if (VALUE_IS_ERROR (tmp)) {
1223 free_values (args, i);
1224 return tmp;
1227 if (VALUE_IS_CELLRANGE (tmp)) {
1228 gnm_cellref_make_abs (&tmp->v_range.cell.a,
1229 &tmp->v_range.cell.a,
1230 ei->pos);
1231 gnm_cellref_make_abs (&tmp->v_range.cell.b,
1232 &tmp->v_range.cell.b,
1233 ei->pos);
1234 /* Array args accept scalars */
1235 } else if (arg_type != 'A' && !VALUE_IS_ARRAY (tmp)) {
1236 free_values (args, i + 1);
1237 return value_new_error_VALUE (ei->pos);
1239 continue;
1242 /* force scalars whenever we are certain */
1243 tmp = args[i] = gnm_expr_eval
1244 (expr, ei->pos,
1245 pass_flags |
1246 GNM_EXPR_EVAL_PERMIT_EMPTY |
1247 (iter_count >= 0 || arg_type == '?'
1248 ? GNM_EXPR_EVAL_PERMIT_NON_SCALAR
1249 : 0));
1251 if (arg_type == '?') /* '?' arguments are unrestriced */
1252 continue;
1254 /* optional arguments can be blank */
1255 if (i >= fn_def->min_args && VALUE_IS_EMPTY (tmp)) {
1256 if (arg_type == 'E' && !gnm_expr_is_empty (expr)) {
1257 /* An actual argument produced empty. Make
1258 sure function sees that. */
1259 args[i] = value_new_empty ();
1262 continue;
1265 if (tmp == NULL)
1266 tmp = args[i] = value_new_empty ();
1268 /* Handle implicit intersection or iteration depending on flags */
1269 if (VALUE_IS_CELLRANGE (tmp) || VALUE_IS_ARRAY (tmp)) {
1270 if (iter_count > 0) {
1271 if (iter_width != value_area_get_width (tmp, ei->pos) ||
1272 iter_height != value_area_get_height (tmp, ei->pos)) {
1273 free_values (args, i + 1);
1274 return value_new_error_VALUE (ei->pos);
1276 } else {
1277 if (iter_count < 0) {
1278 g_warning ("Damn I thought this was impossible");
1279 iter_count = 0;
1281 iter_item = g_alloca (sizeof (int) * argc);
1282 iter_width = value_area_get_width (tmp, ei->pos);
1283 iter_height = value_area_get_height (tmp, ei->pos);
1285 iter_item [iter_count++] = i;
1287 /* no need to check type, we would fail comparing a range against a "b, f, or s" */
1288 continue;
1291 /* All of these argument types must be scalars */
1292 switch (arg_type) {
1293 case 'b':
1294 if (VALUE_IS_STRING (tmp)) {
1295 gboolean err;
1296 gboolean b = value_get_as_bool (tmp, &err);
1297 if (err) {
1298 free_values (args, i + 1);
1299 return value_new_error_VALUE (ei->pos);
1301 value_release (args[i]);
1302 tmp = args[i] = value_new_bool (b);
1303 break;
1305 /* Fall through. */
1306 case 'f':
1307 if (VALUE_IS_STRING (tmp)) {
1308 tmp = format_match_number (value_peek_string (tmp), NULL,
1309 sheet_date_conv (ei->pos->sheet));
1310 if (tmp == NULL) {
1311 free_values (args, i + 1);
1312 return value_new_error_VALUE (ei->pos);
1314 value_release (args [i]);
1315 args[i] = tmp;
1316 } else if (VALUE_IS_ERROR (tmp)) {
1317 free_values (args, i);
1318 return tmp;
1319 } else if (VALUE_IS_EMPTY (tmp)) {
1320 value_release (args [i]);
1321 tmp = args[i] = value_new_int (0);
1324 if (!VALUE_IS_NUMBER (tmp))
1325 return value_new_error_VALUE (ei->pos);
1326 break;
1328 case 's':
1329 case 'S':
1330 if (VALUE_IS_ERROR (tmp)) {
1331 free_values (args, i);
1332 return tmp;
1334 break;
1336 case 'E': /* nothing necessary */
1337 break;
1339 /* case '?': handled above */
1340 default:
1341 g_warning ("Unknown argument type '%c'", arg_type);
1342 break;
1346 while (i < fn_def->max_args)
1347 args [i++] = NULL;
1349 if (iter_item != NULL) {
1350 int x, y;
1351 GnmValue *res = value_new_array_empty (iter_width, iter_height);
1352 GnmValue const *elem, *err;
1353 GnmValue **iter_vals = g_alloca (sizeof (GnmValue *) * iter_count);
1354 GnmValue **iter_args = g_alloca (sizeof (GnmValue *) * iter_count);
1356 /* collect the args we will iterate on */
1357 for (i = 0 ; i < iter_count; i++)
1358 iter_vals[i] = args[iter_item[i]];
1360 for (x = iter_width; x-- > 0 ; )
1361 for (y = iter_height; y-- > 0 ; ) {
1362 /* marshal the args */
1363 err = NULL;
1364 for (i = 0 ; i < iter_count; i++) {
1365 elem = value_area_get_x_y (iter_vals[i], x, y, ei->pos);
1366 arg_type = fn_def->arg_types[iter_item[i]];
1367 if (arg_type == 'b' || arg_type == 'f') {
1368 if (VALUE_IS_EMPTY (elem))
1369 elem = value_zero;
1370 else if (VALUE_IS_STRING (elem)) {
1371 tmp = format_match_number (value_peek_string (elem), NULL,
1372 sheet_date_conv (ei->pos->sheet));
1373 if (tmp != NULL) {
1374 args [iter_item[i]] = iter_args [i] = tmp;
1375 continue;
1376 } else
1377 break;
1378 } else if (VALUE_IS_ERROR (elem)) {
1379 err = elem;
1380 break;
1381 } else if (!VALUE_IS_NUMBER (elem))
1382 break;
1383 } else if (arg_type == 's') {
1384 if (VALUE_IS_EMPTY (elem)) {
1385 args [iter_item[i]] = iter_args [i] = value_new_string ("");
1386 continue;
1387 } else if (VALUE_IS_ERROR (elem)) {
1388 err = elem;
1389 break;
1390 } else if (!VALUE_IS_STRING (elem))
1391 break;
1392 } else if (elem == NULL) {
1393 args [iter_item[i]] = iter_args [i] = value_new_empty ();
1394 continue;
1396 args [iter_item[i]] = iter_args [i] = value_dup (elem);
1399 res->v_array.vals[x][y] = (i == iter_count)
1400 ? fn_def->args_func (ei, (GnmValue const * const *)args)
1401 : ((err != NULL) ? value_dup (err)
1402 : value_new_error_VALUE (ei->pos));
1403 free_values (iter_args, i);
1406 /* free the primaries, not the already freed iteration */
1407 for (i = 0 ; i < iter_count; i++)
1408 args[iter_item[i]] = iter_vals[i];
1409 tmp = res;
1410 i = fn_def->max_args;
1411 } else
1412 tmp = fn_def->args_func (ei, (GnmValue const * const *)args);
1414 free_values (args, i);
1415 return tmp;
1419 * Use this to invoke a register function: the only drawback is that
1420 * you have to compute/expand all of the values to use this
1422 GnmValue *
1423 function_call_with_values (GnmEvalPos const *ep, char const *fn_name,
1424 int argc, GnmValue const * const *values)
1426 GnmFunc *fn_def;
1428 g_return_val_if_fail (ep != NULL, NULL);
1429 g_return_val_if_fail (fn_name != NULL, NULL);
1430 g_return_val_if_fail (ep->sheet != NULL, NULL);
1432 /* FIXME : support workbook local functions */
1433 fn_def = gnm_func_lookup (fn_name, NULL);
1434 if (fn_def == NULL)
1435 return value_new_error_NAME (ep);
1436 return function_def_call_with_values (ep, fn_def, argc, values);
1439 GnmValue *
1440 function_def_call_with_values (GnmEvalPos const *ep, GnmFunc const *fn_def,
1441 int argc, GnmValue const * const *values)
1443 GnmValue *retval;
1444 GnmExprFunction ef;
1445 GnmFuncEvalInfo fs;
1447 fs.pos = ep;
1448 fs.func_call = &ef;
1449 ef.func = (GnmFunc *)fn_def;
1451 gnm_func_load_if_stub (ef.func);
1453 if (fn_def->fn_type == GNM_FUNC_TYPE_NODES) {
1455 * If function deals with ExprNodes, create some
1456 * temporary ExprNodes with constants.
1458 GnmExprConstant *expr = g_new (GnmExprConstant, argc);
1459 GnmExprConstPtr *argv = g_new (GnmExprConstPtr, argc);
1460 int i;
1462 for (i = 0; i < argc; i++) {
1463 gnm_expr_constant_init (expr + i, values[i]);
1464 argv[i] = (GnmExprConstPtr)(expr + i);
1466 retval = fn_def->nodes_func (&fs, argc, argv);
1467 g_free (argv);
1468 g_free (expr);
1469 } else
1470 retval = fn_def->args_func (&fs, values);
1472 return retval;
1475 /* ------------------------------------------------------------------------- */
1477 typedef struct {
1478 FunctionIterateCB callback;
1479 void *closure;
1480 gboolean strict;
1481 gboolean ignore_subtotal;
1482 } IterateCallbackClosure;
1485 * cb_iterate_cellrange:
1487 * Helper routine used by the function_iterate_do_value routine.
1488 * Invoked by the sheet cell range iterator.
1490 static GnmValue *
1491 cb_iterate_cellrange (GnmCellIter const *iter, gpointer user)
1494 IterateCallbackClosure *data = user;
1495 GnmCell *cell;
1496 GnmValue *res;
1497 GnmEvalPos ep;
1499 if (NULL == (cell = iter->cell)) {
1500 ep.sheet = iter->pp.sheet;
1501 ep.dep = NULL;
1502 ep.eval.col = iter->pp.eval.col;
1503 ep.eval.row = iter->pp.eval.row;
1504 return (*data->callback)(&ep, NULL, data->closure);
1507 if (data->ignore_subtotal && gnm_cell_has_expr (cell) &&
1508 gnm_expr_top_contains_subtotal (cell->base.texpr))
1509 return NULL;
1511 gnm_cell_eval (cell);
1512 eval_pos_init_cell (&ep, cell);
1514 /* If we encounter an error for the strict case, short-circuit here. */
1515 if (data->strict && (NULL != (res = gnm_cell_is_error (cell))))
1516 return value_new_error_str (&ep, res->v_err.mesg);
1518 /* All other cases -- including error -- just call the handler. */
1519 return (*data->callback)(&ep, cell->value, data->closure);
1523 * function_iterate_do_value:
1525 * Helper routine for function_iterate_argument_values.
1527 static GnmValue *
1528 function_iterate_do_value (GnmEvalPos const *ep,
1529 FunctionIterateCB callback,
1530 gpointer closure,
1531 GnmValue const *value,
1532 gboolean strict,
1533 CellIterFlags iter_flags)
1535 GnmValue *res = NULL;
1537 switch (value->v_any.type){
1538 case VALUE_ERROR:
1539 if (strict) {
1540 res = value_dup (value);
1541 break;
1543 /* Fall through. */
1545 case VALUE_EMPTY:
1546 case VALUE_BOOLEAN:
1547 case VALUE_FLOAT:
1548 case VALUE_STRING:
1549 res = (*callback)(ep, value, closure);
1550 break;
1552 case VALUE_ARRAY: {
1553 int x, y;
1555 /* Note the order here. */
1556 for (y = 0; y < value->v_array.y; y++) {
1557 for (x = 0; x < value->v_array.x; x++) {
1558 res = function_iterate_do_value (
1559 ep, callback, closure,
1560 value->v_array.vals [x][y],
1561 strict, CELL_ITER_IGNORE_BLANK);
1562 if (res != NULL)
1563 return res;
1566 break;
1568 case VALUE_CELLRANGE: {
1569 IterateCallbackClosure data;
1571 data.callback = callback;
1572 data.closure = closure;
1573 data.strict = strict;
1574 data.ignore_subtotal = (iter_flags & CELL_ITER_IGNORE_SUBTOTAL) != 0;
1576 res = workbook_foreach_cell_in_range (ep, value, iter_flags,
1577 cb_iterate_cellrange,
1578 &data);
1581 return res;
1585 * function_iterate_argument_values:
1586 * @ep: The position in a workbook at which to evaluate
1587 * @callback: (scope call): The routine to be invoked for every value computed
1588 * @callback_closure: Closure for the callback.
1589 * @argc:
1590 * @argv:
1591 * @strict: If TRUE, the function is considered "strict". This means
1592 * that if an error value occurs as an argument, the iteration
1593 * will stop and that error will be returned. If FALSE, an
1594 * error will be passed on to the callback (as a GnmValue *
1595 * of type VALUE_ERROR).
1596 * @iter_flags:
1598 * Return value:
1599 * NULL : if no errors were reported.
1600 * GnmValue * : if an error was found during strict evaluation
1601 * VALUE_TERMINATE : if the callback requested termination of the iteration.
1603 * This routine provides a simple way for internal functions with variable
1604 * number of arguments to be written: this would iterate over a list of
1605 * expressions (expr_node_list) and will invoke the callback for every
1606 * GnmValue found on the list (this means that ranges get properly expaned).
1608 GnmValue *
1609 function_iterate_argument_values (GnmEvalPos const *ep,
1610 FunctionIterateCB callback,
1611 void *callback_closure,
1612 int argc,
1613 GnmExprConstPtr const *argv,
1614 gboolean strict,
1615 CellIterFlags iter_flags)
1617 GnmValue *result = NULL;
1618 int a;
1620 for (a = 0; result == NULL && a < argc; a++) {
1621 GnmExpr const *expr = argv[a];
1622 GnmValue *val;
1624 if (iter_flags & CELL_ITER_IGNORE_SUBTOTAL &&
1625 gnm_expr_contains_subtotal (expr))
1626 continue;
1628 /* need to drill down into names to handle things like
1629 * sum(name) with name := (A:A,B:B) */
1630 while (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_NAME) {
1631 GnmExprTop const *texpr = expr->name.name->texpr;
1632 expr = texpr ? texpr->expr : NULL;
1633 if (expr == NULL) {
1634 if (strict)
1635 return value_new_error_REF (ep);
1636 break;
1639 if (!expr)
1640 continue;
1642 /* Handle sets as a special case */
1643 if (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_SET) {
1644 result = function_iterate_argument_values
1645 (ep, callback, callback_closure,
1646 expr->set.argc, expr->set.argv,
1647 strict, iter_flags);
1648 continue;
1651 /* We need a cleaner model of what to do here.
1652 * In non-array mode
1653 * SUM(Range)
1654 * will obviously return Range
1656 * SUM(INDIRECT(Range))
1657 * SUM(INDIRECT(Range):....)
1658 * will do implicit intersection on Range (in non-array mode),
1659 * but allow non-scalar results from indirect (no intersection)
1661 * SUM(Range=3)
1662 * will do implicit intersection in non-array mode */
1663 if (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_CONSTANT)
1664 val = value_dup (expr->constant.value);
1665 else if (eval_pos_is_array_context (ep) ||
1666 GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_FUNCALL ||
1667 GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_RANGE_CTOR ||
1668 GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_INTERSECT)
1669 val = gnm_expr_eval (expr, ep,
1670 GNM_EXPR_EVAL_PERMIT_EMPTY | GNM_EXPR_EVAL_PERMIT_NON_SCALAR);
1671 else
1672 val = gnm_expr_eval (expr, ep, GNM_EXPR_EVAL_PERMIT_EMPTY);
1674 if (val == NULL)
1675 continue;
1677 if (strict && VALUE_IS_ERROR (val)) {
1678 /* Be careful not to make VALUE_TERMINATE into a real value */
1679 return val;
1682 result = function_iterate_do_value (ep, callback, callback_closure,
1683 val, strict, iter_flags);
1684 value_release (val);
1686 return result;
1691 * gnm_eval_info_get_func:
1692 * @ei: #GnmFuncEvalInfo
1694 * Returns: (transfer none): the called function.
1696 GnmFunc const *
1697 gnm_eval_info_get_func (GnmFuncEvalInfo const *ei)
1699 return ei->func_call->func;
1703 gnm_eval_info_get_arg_count (GnmFuncEvalInfo const *ei)
1705 return ei->func_call->argc;
1708 GnmDependentFlags
1709 gnm_func_link_dep (GnmFunc *func, GnmFuncEvalInfo *ei, gboolean qlink)
1711 int res = DEPENDENT_NO_FLAG;
1712 g_signal_emit (func, signals[SIG_LINK_DEP], 0, ei, qlink, &res);
1713 return (GnmDependentFlags)res;
1716 /* ------------------------------------------------------------------------- */
1718 static GObjectClass *parent_class;
1720 typedef struct {
1721 GObjectClass parent;
1723 void (*load_stub) (GnmFunc *func);
1724 int (*link_dep) (GnmFunc *func, GnmFuncEvalInfo *ei, gboolean qlink);
1725 } GnmFuncClass;
1727 static void
1728 gnm_func_finalize (GObject *obj)
1730 GnmFunc *func = GNM_FUNC (obj);
1732 g_free (func->arg_types);
1734 g_free ((char *)func->name);
1736 go_string_unref (func->tdomain);
1738 parent_class->finalize (obj);
1741 static void
1742 gnm_func_real_dispose (GObject *obj)
1744 GnmFunc *func = GNM_FUNC (obj);
1746 if (func->usage_count != 0) {
1747 g_printerr ("Function %s still has a usage count of %d\n",
1748 func->name, func->usage_count);
1751 gnm_func_set_stub (func);
1753 if (func->fn_group) {
1754 gnm_func_group_remove_func (func->fn_group, func);
1755 func->fn_group = NULL;
1758 gnm_func_set_localized_name (func, NULL);
1760 if (!(func->flags & GNM_FUNC_IS_WORKBOOK_LOCAL)) {
1761 g_hash_table_remove (functions_by_name, func->name);
1764 parent_class->dispose (obj);
1767 void
1768 gnm_func_dispose (GnmFunc *func)
1770 g_object_run_dispose (G_OBJECT (func));
1773 static void
1774 gnm_func_get_property (GObject *object, guint property_id,
1775 GValue *value, GParamSpec *pspec)
1777 GnmFunc *func = (GnmFunc *)object;
1779 switch (property_id) {
1780 case PROP_NAME:
1781 g_value_set_string (value, func->name);
1782 break;
1783 case PROP_TRANSLATION_DOMAIN:
1784 g_value_set_string (value, func->tdomain->str);
1785 break;
1786 case PROP_IN_USE:
1787 g_value_set_boolean (value, func->usage_count > 0);
1788 break;
1789 default:
1790 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1791 break;
1795 static void
1796 gnm_func_set_property (GObject *object, guint property_id,
1797 GValue const *value, GParamSpec *pspec)
1799 GnmFunc *func = (GnmFunc *)object;
1801 switch (property_id) {
1802 case PROP_NAME:
1803 func->name = g_value_dup_string (value);
1804 break;
1805 case PROP_TRANSLATION_DOMAIN:
1806 gnm_func_set_translation_domain (func,
1807 g_value_get_string (value));
1808 break;
1809 default:
1810 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1811 break;
1815 static void
1816 gnm_func_init (GnmFunc *func)
1818 func->tdomain = go_string_new (GETTEXT_PACKAGE);
1819 func->flags = GNM_FUNC_SIMPLE;
1820 func->impl_status = GNM_FUNC_IMPL_STATUS_UNIMPLEMENTED;
1821 func->test_status = GNM_FUNC_TEST_STATUS_UNKNOWN;
1824 static void
1825 gnm_func_class_init (GObjectClass *gobject_class)
1827 parent_class = g_type_class_peek_parent (gobject_class);
1829 gobject_class->finalize = gnm_func_finalize;
1830 gobject_class->dispose = gnm_func_real_dispose;
1831 gobject_class->get_property = gnm_func_get_property;
1832 gobject_class->set_property = gnm_func_set_property;
1834 g_object_class_install_property (gobject_class, PROP_NAME,
1835 g_param_spec_string ("name",
1836 P_("Name"),
1837 P_("The name of the function."),
1838 NULL,
1839 GSF_PARAM_STATIC |
1840 G_PARAM_READWRITE |
1841 G_PARAM_CONSTRUCT_ONLY));
1843 g_object_class_install_property (gobject_class, PROP_TRANSLATION_DOMAIN,
1844 g_param_spec_string ("translation-domain",
1845 P_("Translation Domain"),
1846 P_("The translation domain for help texts"),
1847 NULL,
1848 GSF_PARAM_STATIC |
1849 G_PARAM_READWRITE));
1851 g_object_class_install_property (gobject_class, PROP_IN_USE,
1852 g_param_spec_boolean ("in-use",
1853 P_("In use"),
1854 P_("Is function being used?"),
1855 FALSE,
1856 GSF_PARAM_STATIC |
1857 G_PARAM_READABLE));
1859 signals[SIG_LOAD_STUB] = g_signal_new
1860 ("load-stub",
1861 GNM_FUNC_TYPE,
1862 G_SIGNAL_RUN_LAST,
1863 G_STRUCT_OFFSET (GnmFuncClass, load_stub),
1864 NULL, NULL,
1865 g_cclosure_marshal_VOID__VOID,
1866 G_TYPE_NONE, 0);
1869 signals[SIG_LINK_DEP] = g_signal_new
1870 ("link-dep",
1871 GNM_FUNC_TYPE,
1872 G_SIGNAL_RUN_LAST,
1873 G_STRUCT_OFFSET (GnmFuncClass, link_dep),
1874 NULL, NULL,
1875 gnm__INT__POINTER_BOOLEAN,
1876 // GnmDependentFlags ... GnmFuncEvalInfo
1877 G_TYPE_INT, 2, G_TYPE_POINTER, G_TYPE_BOOLEAN);
1880 GSF_CLASS (GnmFunc, gnm_func,
1881 gnm_func_class_init, gnm_func_init, G_TYPE_OBJECT)