GUI: Dead kittens.
[gnumeric.git] / src / func.c
blob06b86a0818bdc6b154b39ce3b664a3f59c0a274e
1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 /*
4 * func.c: Function management and utility routines.
6 * Author:
7 * Miguel de Icaza (miguel@gnu.org)
8 * Michael Meeks (mmeeks@gnu.org)
9 * Morten Welinder (terra@gnome.org)
10 * Jody Goldberg (jody@gnome.org)
12 #include <gnumeric-config.h>
13 #include <glib/gi18n-lib.h>
14 #include <glib/gstdio.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"
34 #include <goffice/goffice.h>
35 #include <glib.h>
36 #include <string.h>
37 #include <stdlib.h>
39 #define F2(func,s) dgettext ((func)->tdomain->str, (s))
41 static GList *categories;
42 static GnmFuncGroup *unknown_cat;
44 static GHashTable *functions_by_name;
45 static GHashTable *functions_by_localized_name;
47 /**
48 * functions_init: (skip)
50 void
51 functions_init (void)
53 functions_by_name =
54 g_hash_table_new (go_ascii_strcase_hash, go_ascii_strcase_equal);
56 /* FIXME: ascii??? */
57 functions_by_localized_name =
58 g_hash_table_new (go_ascii_strcase_hash, go_ascii_strcase_equal);
60 func_builtin_init ();
63 /**
64 * functions_shutdown: (skip)
66 void
67 functions_shutdown (void)
69 while (unknown_cat != NULL && unknown_cat->functions != NULL) {
70 GnmFunc *func = unknown_cat->functions->data;
71 if (func->usage_count > 0) {
72 g_warning ("Function %s still has %d users.\n",
73 gnm_func_get_name (func, FALSE),
74 func->usage_count);
75 func->usage_count = 0;
77 gnm_func_free (func);
79 func_builtin_shutdown ();
81 g_hash_table_destroy (functions_by_name);
82 functions_by_name = NULL;
84 g_hash_table_destroy (functions_by_localized_name);
85 functions_by_localized_name = NULL;
88 /**
89 * gnm_func_enumerate:
91 * Return value: (element-type GnmFunc) (transfer container):
93 GPtrArray *
94 gnm_func_enumerate (void)
96 GPtrArray *res = g_ptr_array_new ();
97 GHashTableIter hiter;
98 gpointer value;
100 g_hash_table_iter_init (&hiter, functions_by_name);
101 while (g_hash_table_iter_next (&hiter, NULL, &value))
102 g_ptr_array_add (res, value);
104 return res;
107 inline void
108 gnm_func_load_if_stub (GnmFunc *func)
110 if (func->fn_type == GNM_FUNC_TYPE_STUB)
111 gnm_func_load_stub (func);
114 static char *
115 split_at_colon (char const *s, char **rest)
117 char *dup = g_strdup (s);
118 char *colon = strchr (dup, ':');
119 if (colon) {
120 *colon = 0;
121 if (rest) *rest = colon + 1;
122 } else {
123 if (rest) *rest = NULL;
125 return dup;
128 /* ------------------------------------------------------------------------- */
130 static void
131 gnm_func_group_free (GnmFuncGroup *fn_group)
133 g_return_if_fail (fn_group != NULL);
134 g_return_if_fail (fn_group->functions == NULL);
136 if (fn_group->ref_count-- > 1)
137 return;
139 go_string_unref (fn_group->internal_name);
140 go_string_unref (fn_group->display_name);
141 g_free (fn_group);
144 static GnmFuncGroup *
145 gnm_func_group_ref (GnmFuncGroup *fn_group)
147 fn_group->ref_count++;
148 return fn_group;
151 GType
152 gnm_func_group_get_type (void)
154 static GType t = 0;
156 if (t == 0) {
157 t = g_boxed_type_register_static ("GnmFuncGroup",
158 (GBoxedCopyFunc)gnm_func_group_ref,
159 (GBoxedFreeFunc)gnm_func_group_free);
161 return t;
164 static gint
165 function_category_compare (gconstpointer a, gconstpointer b)
167 GnmFuncGroup const *cat_a = a;
168 GnmFuncGroup const *cat_b = b;
170 return go_string_cmp (cat_a->display_name, cat_b->display_name);
173 GnmFuncGroup *
174 gnm_func_group_fetch (char const *name, char const *translation)
176 GnmFuncGroup *cat = NULL;
177 GList *l;
179 g_return_val_if_fail (name != NULL, NULL);
181 for (l = categories; l != NULL; l = l->next) {
182 cat = l->data;
183 if (strcmp (cat->internal_name->str, name) == 0) {
184 break;
188 if (l == NULL) {
189 cat = g_new (GnmFuncGroup, 1);
190 cat->internal_name = go_string_new (name);
191 cat->ref_count = 1;
192 if (translation != NULL) {
193 cat->display_name = go_string_new (translation);
194 cat->has_translation = TRUE;
195 } else {
196 cat->display_name = go_string_new (name);
197 cat->has_translation = FALSE;
199 cat->functions = NULL;
200 categories = g_list_insert_sorted (
201 categories, cat, &function_category_compare);
202 } else if (translation != NULL && translation != name &&
203 !cat->has_translation) {
204 go_string_unref (cat->display_name);
205 cat->display_name = go_string_new (translation);
206 cat->has_translation = TRUE;
207 categories = g_list_remove_link (categories, l);
208 g_list_free_1 (l);
209 categories = g_list_insert_sorted (
210 categories, cat, &function_category_compare);
213 return cat;
216 GnmFuncGroup *
217 gnm_func_group_get_nth (int n)
219 return g_list_nth_data (categories, n);
222 static void
223 gnm_func_group_add_func (GnmFuncGroup *fn_group, GnmFunc *fn_def)
225 g_return_if_fail (fn_group != NULL);
226 g_return_if_fail (fn_def != NULL);
228 fn_group->functions = g_slist_prepend (fn_group->functions, fn_def);
231 static void
232 gnm_func_group_remove_func (GnmFuncGroup *fn_group, GnmFunc *fn_def)
234 g_return_if_fail (fn_group != NULL);
235 g_return_if_fail (fn_def != NULL);
237 fn_group->functions = g_slist_remove (fn_group->functions, fn_def);
238 if (fn_group->functions == NULL) {
239 categories = g_list_remove (categories, fn_group);
240 if (unknown_cat == fn_group)
241 unknown_cat = NULL;
242 gnm_func_group_free (fn_group);
246 /******************************************************************************/
248 static void
249 extract_arg_types (GnmFunc *def)
251 int i;
253 gnm_func_count_args (def,
254 &def->fn.args.min_args,
255 &def->fn.args.max_args);
256 def->fn.args.arg_types = g_malloc (def->fn.args.max_args + 1);
257 for (i = 0; i < def->fn.args.max_args; i++)
258 def->fn.args.arg_types[i] = gnm_func_get_arg_type (def, i);
259 def->fn.args.arg_types[i] = 0;
262 static GnmValue *
263 error_function_no_full_info (GnmFuncEvalInfo *ei,
264 int argc,
265 GnmExprConstPtr const *argv)
267 return value_new_error (ei->pos, _("Function implementation not available."));
270 static void
271 gnm_func_clear_arg_names (GnmFunc *fd)
273 if (fd->arg_names_p) {
274 g_ptr_array_foreach (fd->arg_names_p, (GFunc) g_free, NULL);
275 g_ptr_array_free (fd->arg_names_p, TRUE);
276 fd->arg_names_p = NULL;
280 static void
281 gnm_func_create_arg_names (GnmFunc *fn_def)
283 int i;
284 GPtrArray *ptr;
286 g_return_if_fail (fn_def != NULL);
288 ptr = g_ptr_array_new ();
289 for (i = 0;
290 fn_def->help && fn_def->help[i].type != GNM_FUNC_HELP_END;
291 i++) {
292 if (fn_def->help[i].type != GNM_FUNC_HELP_ARG)
293 continue;
295 g_ptr_array_add
296 (ptr, split_at_colon
297 (F2(fn_def, fn_def->help[i].text), NULL));
300 gnm_func_clear_arg_names (fn_def);
301 fn_def->arg_names_p = ptr;
305 void
306 gnm_func_load_stub (GnmFunc *func)
308 GnmFuncDescriptor desc;
310 g_return_if_fail (func->fn_type == GNM_FUNC_TYPE_STUB);
312 /* default the content to 0 in case we add new fields
313 * later and the services do not fill them in
315 memset (&desc, 0, sizeof (GnmFuncDescriptor));
317 if (func->fn.load_desc (func, &desc)) {
318 func->help = desc.help ? desc.help : NULL;
319 if (desc.fn_args != NULL) {
320 func->fn_type = GNM_FUNC_TYPE_ARGS;
321 func->fn.args.func = desc.fn_args;
322 func->fn.args.arg_spec = desc.arg_spec;
323 extract_arg_types (func);
324 } else if (desc.fn_nodes != NULL) {
325 func->fn_type = GNM_FUNC_TYPE_NODES;
326 func->fn.nodes = desc.fn_nodes;
327 } else {
328 g_warning ("Invalid function descriptor with no function");
330 func->linker = desc.linker;
331 func->impl_status = desc.impl_status;
332 func->test_status = desc.test_status;
333 func->flags = desc.flags;
334 gnm_func_create_arg_names (func);
335 } else {
336 func->fn_type = GNM_FUNC_TYPE_NODES;
337 func->fn.nodes = &error_function_no_full_info;
338 func->linker = NULL;
342 static void
343 gnm_func_set_localized_name (GnmFunc *fd, const char *lname)
345 gboolean in_hashes = !(fd->flags & GNM_FUNC_IS_WORKBOOK_LOCAL);
347 if (in_hashes && fd->localized_name)
348 g_hash_table_remove (functions_by_localized_name, fd->localized_name);
349 g_free (fd->localized_name);
351 fd->localized_name = g_strdup (lname);
352 if (in_hashes && lname)
353 g_hash_table_insert (functions_by_localized_name,
354 fd->localized_name, fd);
357 void
358 gnm_func_free (GnmFunc *func)
360 GnmFuncGroup *group;
362 g_return_if_fail (func != NULL);
363 g_return_if_fail (func->usage_count == 0);
365 group = func->fn_group;
366 if (group != NULL)
367 gnm_func_group_remove_func (group, func);
369 gnm_func_set_localized_name (func, NULL);
371 if (!(func->flags & GNM_FUNC_IS_WORKBOOK_LOCAL)) {
372 g_hash_table_remove (functions_by_name, func->name);
375 if (func->fn_type == GNM_FUNC_TYPE_ARGS)
376 g_free (func->fn.args.arg_types);
378 g_free ((char *)func->name);
380 go_string_unref (func->tdomain);
382 gnm_func_clear_arg_names (func);
384 g_free (func);
387 GnmFunc *
388 gnm_func_ref (GnmFunc *func)
390 g_return_val_if_fail (func != NULL, NULL);
392 func->usage_count++;
393 if (func->usage_count == 1 && func->usage_notify != NULL)
394 func->usage_notify (func, 1);
395 return func;
398 void
399 gnm_func_unref (GnmFunc *func)
401 g_return_if_fail (func != NULL);
402 g_return_if_fail (func->usage_count > 0);
404 func->usage_count--;
405 if (func->usage_count == 0 && func->usage_notify != NULL)
406 func->usage_notify (func, 0);
409 GType
410 gnm_func_get_type (void)
412 static GType t = 0;
414 if (t == 0) {
415 t = g_boxed_type_register_static ("GnmFunc",
416 (GBoxedCopyFunc)gnm_func_ref,
417 (GBoxedFreeFunc)gnm_func_unref);
419 return t;
422 GnmFunc *
423 gnm_func_lookup (char const *name, Workbook *scope)
425 GnmFunc *fd = g_hash_table_lookup (functions_by_name, name);
426 if (fd != NULL)
427 return fd;
428 if (scope == NULL || scope->sheet_local_functions == NULL)
429 return NULL;
430 return g_hash_table_lookup (scope->sheet_local_functions, (gpointer)name);
433 GnmFunc *
434 gnm_func_lookup_localized (char const *name, Workbook *scope)
436 GnmFunc *fd;
437 GHashTableIter hiter;
438 gpointer value;
440 /* Must localize all function names. */
441 g_hash_table_iter_init (&hiter, functions_by_name);
442 while (g_hash_table_iter_next (&hiter, NULL, &value)) {
443 GnmFunc *fd = value;
444 (void)gnm_func_get_name (fd, TRUE);
447 fd = g_hash_table_lookup (functions_by_localized_name, name);
448 if (fd != NULL)
449 return fd;
450 if (scope == NULL || scope->sheet_local_functions == NULL)
451 return NULL;
452 return g_hash_table_lookup (scope->sheet_local_functions, (gpointer)name);
456 * gnm_func_lookup_prefix:
457 * @prefix: prefix to search for
458 * @scope:
459 * @trans: whether to search translated function names
461 * Returns: (element-type GnmFunc*) (transfer full):
463 GSList *
464 gnm_func_lookup_prefix (char const *prefix, Workbook *scope, gboolean trans)
466 GSList *res = NULL;
467 GHashTableIter hiter;
468 gpointer value;
471 * Always iterate over functions_by_name as the localized name
472 * might not be set yet.
474 g_hash_table_iter_init (&hiter, functions_by_name);
475 while (g_hash_table_iter_next (&hiter, NULL, &value)) {
476 GnmFunc *fd = value;
477 if (!(fd->flags & GNM_FUNC_IS_PLACEHOLDER)) {
478 const char *name = gnm_func_get_name (fd, trans);
479 if (g_str_has_prefix (name, prefix)) {
480 gnm_func_ref (fd);
481 res = g_slist_prepend (res, fd);
486 return res;
489 GnmFunc *
490 gnm_func_add (GnmFuncGroup *fn_group,
491 GnmFuncDescriptor const *desc,
492 const char *tdomain)
494 static char const valid_tokens[] = "fsbraAES?|";
495 GnmFunc *func;
496 char const *ptr;
498 g_return_val_if_fail (fn_group != NULL, NULL);
499 g_return_val_if_fail (desc != NULL, NULL);
501 func = g_new (GnmFunc, 1);
503 if (!tdomain)
504 tdomain = GETTEXT_PACKAGE;
506 func->name = g_strdup (desc->name);
507 func->help = desc->help ? desc->help : NULL;
508 func->tdomain = go_string_new (tdomain);
509 func->linker = desc->linker;
510 func->usage_notify = desc->usage_notify;
511 func->flags = desc->flags;
512 func->impl_status = desc->impl_status;
513 func->test_status = desc->test_status;
514 func->localized_name = NULL;
515 func->arg_names_p = NULL;
517 func->user_data = NULL;
518 func->usage_count = 0;
520 if (desc->fn_args != NULL) {
521 /* Check those arguments */
522 for (ptr = desc->arg_spec ; *ptr ; ptr++) {
523 g_return_val_if_fail (strchr (valid_tokens, *ptr), NULL);
526 func->fn_type = GNM_FUNC_TYPE_ARGS;
527 func->fn.args.func = desc->fn_args;
528 func->fn.args.arg_spec = desc->arg_spec;
529 extract_arg_types (func);
530 } else if (desc->fn_nodes != NULL) {
532 if (desc->arg_spec && *desc->arg_spec) {
533 g_warning ("Arg spec for node function -- why?");
536 func->fn_type = GNM_FUNC_TYPE_NODES;
537 func->fn.nodes = desc->fn_nodes;
538 } else {
539 g_warning ("Invalid function has neither args nor nodes handler");
540 g_free (func);
541 return NULL;
544 func->fn_group = fn_group;
545 if (fn_group != NULL)
546 gnm_func_group_add_func (fn_group, func);
547 if (!(func->flags & GNM_FUNC_IS_WORKBOOK_LOCAL))
548 g_hash_table_insert (functions_by_name,
549 (gpointer)(func->name), func);
551 gnm_func_create_arg_names (func);
553 return func;
556 /* Handle unknown functions on import without losing their names */
557 static GnmValue *
558 unknownFunctionHandler (GnmFuncEvalInfo *ei,
559 G_GNUC_UNUSED int argc,
560 G_GNUC_UNUSED GnmExprConstPtr const *argv)
562 return value_new_error_NAME (ei->pos);
566 * gnm_func_upgrade_placeholder:
567 * @fd:
568 * @fn_group:
569 * @tdomain:
570 * @load_desc: (scope async):
571 * @opt_usage_notify: (scope async):
573 void
574 gnm_func_upgrade_placeholder (GnmFunc *fd,
575 GnmFuncGroup *fn_group,
576 const char *tdomain,
577 GnmFuncLoadDesc load_desc,
578 GnmFuncUsageNotify opt_usage_notify)
580 g_return_if_fail (fd != NULL);
581 g_return_if_fail (fd->flags & GNM_FUNC_IS_PLACEHOLDER);
582 g_return_if_fail (fn_group != NULL);
584 if (!tdomain)
585 tdomain = GETTEXT_PACKAGE;
587 /* Remove from unknown_cat */
588 gnm_func_group_remove_func (fd->fn_group, fd);
590 fd->fn_type = GNM_FUNC_TYPE_STUB;
591 fd->fn.load_desc = load_desc;
592 fd->usage_notify = opt_usage_notify;
594 go_string_unref (fd->tdomain);
595 fd->tdomain = go_string_new (tdomain);
597 /* Clear localized_name so we can deduce the proper name. */
598 gnm_func_set_localized_name (fd, NULL);
600 fd->flags &= ~GNM_FUNC_IS_PLACEHOLDER;
602 fd->fn_group = fn_group;
603 gnm_func_group_add_func (fn_group, fd);
606 static char *
607 invent_name (const char *pref, GHashTable *h, const char *template)
609 static int count = 0;
610 char *name = g_utf8_strdown (pref, -1);
612 while (g_hash_table_lookup (h, name)) {
613 count++;
614 g_free (name);
615 name = g_strdup_printf (template, count);
618 return name;
621 static GnmFunc *
622 gnm_func_add_placeholder_full (Workbook *scope,
623 char const *gname, char const *lname,
624 char const *type)
626 GnmFuncDescriptor desc;
627 GnmFunc *func;
628 char const *unknown_cat_name = N_("Unknown Function");
629 gboolean copy_gname = TRUE;
630 gboolean copy_lname = TRUE;
632 g_return_val_if_fail (gname || lname, NULL);
633 g_return_val_if_fail (gname == NULL || gnm_func_lookup (gname, scope) == NULL, NULL);
634 g_return_val_if_fail (lname == NULL || gnm_func_lookup_localized (lname, scope) == NULL, NULL);
636 if (!unknown_cat)
637 unknown_cat = gnm_func_group_fetch
638 (unknown_cat_name, _(unknown_cat_name));
640 if (!gname) {
642 * This is actually a bit of a problem if we don't end up
643 * with a copy of lname (because there already is a function
644 * with that name). We're likely to save a template name,
645 * but I don't see what else to do.
647 gname = invent_name (lname, functions_by_name, "unknown%d");
648 copy_gname = FALSE;
650 if (!lname) {
651 /* xgettext: This represents a made-up translated function name. */
652 lname = invent_name (gname, functions_by_localized_name, _("unknown%d"));
653 copy_lname = FALSE;
656 if (gnm_debug_flag ("func"))
657 g_printerr ("Adding placeholder for %s (aka %s)\n", gname, lname);
659 memset (&desc, 0, sizeof (GnmFuncDescriptor));
660 desc.name = gname;
661 desc.arg_spec = NULL;
662 desc.help = NULL;
663 desc.fn_args = NULL;
664 desc.fn_nodes = &unknownFunctionHandler;
665 desc.linker = NULL;
666 desc.usage_notify = NULL;
667 desc.flags = GNM_FUNC_IS_PLACEHOLDER;
668 desc.impl_status = GNM_FUNC_IMPL_STATUS_EXISTS;
669 desc.test_status = GNM_FUNC_TEST_STATUS_UNKNOWN;
671 if (scope != NULL)
672 desc.flags |= GNM_FUNC_IS_WORKBOOK_LOCAL;
673 else {
674 #if 0
675 /* WISHLIST : it would be nice to have a log if these. */
676 g_warning ("Unknown %s function : %s", type, desc.name);
677 #endif
680 func = gnm_func_add (unknown_cat, &desc, NULL);
682 if (lname) {
683 gnm_func_set_localized_name (func, lname);
684 if (!copy_lname)
685 g_free ((char *)lname);
688 if (!copy_gname)
689 g_free ((char *)gname);
691 if (scope != NULL) {
692 if (scope->sheet_local_functions == NULL)
693 scope->sheet_local_functions = g_hash_table_new_full (
694 g_str_hash, g_str_equal,
695 NULL, (GDestroyNotify) gnm_func_free);
696 g_hash_table_insert (scope->sheet_local_functions,
697 (gpointer)func->name, func);
700 return func;
704 * When importing it is useful to keep track of unknown function names.
705 * We may be missing a plugin or something similar.
707 * TODO : Eventully we should be able to keep track of these
708 * and replace them with something else. Possibly even reordering the
709 * arguments.
711 GnmFunc *
712 gnm_func_add_placeholder (Workbook *scope,
713 char const *name, char const *type)
715 return gnm_func_add_placeholder_full (scope, name, NULL, type);
718 GnmFunc *
719 gnm_func_add_placeholder_localized (char const *gname, char const *lname)
721 return gnm_func_add_placeholder_full (NULL, gname, lname, "?");
724 /* Utility routine to be used for import and analysis tools */
725 GnmFunc *
726 gnm_func_lookup_or_add_placeholder (char const *name)
728 GnmFunc * f = gnm_func_lookup (name, NULL);
729 if (f == NULL)
730 f = gnm_func_add_placeholder (NULL, name, "");
731 return f;
735 * gnm_func_get_user_data:
736 * @func:
738 * Returns: (transfer none):
740 gpointer
741 gnm_func_get_user_data (GnmFunc const *func)
743 g_return_val_if_fail (func != NULL, NULL);
745 return func->user_data;
748 void
749 gnm_func_set_user_data (GnmFunc *func, gpointer user_data)
751 g_return_if_fail (func != NULL);
753 func->user_data = user_data;
757 * gnm_func_get_name:
758 * @func: #GnmFunc to query
759 * @localized: if %TRUE, use localized name
761 * Returns: (transfer none): @func's name
763 char const *
764 gnm_func_get_name (GnmFunc const *func, gboolean localized)
766 int i;
767 GnmFunc *fd = (GnmFunc *)func;
769 g_return_val_if_fail (func != NULL, NULL);
771 if (!localized)
772 return func->name;
774 if (func->localized_name)
775 return func->localized_name;
778 * Deduce the translated names from the help texts. This
779 * code doesn't currently check for clashes in translated
780 * names.
783 gnm_func_load_if_stub (fd);
785 for (i = 0;
786 (func->localized_name == NULL &&
787 func->help &&
788 func->help[i].type != GNM_FUNC_HELP_END);
789 i++) {
790 const char *s, *sl;
791 char *U;
792 if (func->help[i].type != GNM_FUNC_HELP_NAME)
793 continue;
795 s = func->help[i].text;
796 sl = F2 (func, s);
797 if (s == sl) /* String not actually translated. */
798 continue;
800 U = split_at_colon (F2 (func, s), NULL);
801 if (U) {
802 char *lname = g_utf8_strdown (U, -1);
803 gnm_func_set_localized_name (fd, lname);
804 g_free (lname);
806 g_free (U);
809 if (!func->localized_name)
810 gnm_func_set_localized_name (fd, fd->name);
812 return func->localized_name;
816 * gnm_func_get_description:
817 * @fn_def: the fn defintion
819 * Returns: (transfer none): the description of the function
821 char const*
822 gnm_func_get_description (GnmFunc const *fn_def)
824 gint i;
825 g_return_val_if_fail (fn_def != NULL, NULL);
827 gnm_func_load_if_stub ((GnmFunc *)fn_def);
829 for (i = 0;
830 fn_def->help && fn_def->help[i].type != GNM_FUNC_HELP_END;
831 i++) {
832 const char *desc;
834 if (fn_def->help[i].type != GNM_FUNC_HELP_NAME)
835 continue;
837 desc = strchr (F2 (fn_def, fn_def->help[i].text), ':');
838 return desc ? (desc + 1) : "";
840 return "";
844 * gnm_func_count_args:
845 * @fn_def: pointer to function definition
846 * @min: (out): location for mininum args
847 * @max: (out): location for mininum args
849 * This calculates the maximum and minimum number of args tha can be passed.
850 * For a vararg function, the maximum will be set to G_MAXINT.
852 void
853 gnm_func_count_args (GnmFunc const *fn_def, int *min, int *max)
855 char const *ptr;
856 int i;
857 int vararg;
859 g_return_if_fail (min != NULL);
860 g_return_if_fail (max != NULL);
861 g_return_if_fail (fn_def != NULL);
863 gnm_func_load_if_stub ((GnmFunc *)fn_def);
866 * FIXME: clearly for 'nodes' functions many of
867 * the type fields will need to be filled.
869 if (fn_def->fn_type == GNM_FUNC_TYPE_NODES) {
870 *min = 0;
871 if (g_ascii_strcasecmp ("INDEX",fn_def->name) == 0)
872 *max = 4;
873 else
874 *max = G_MAXINT;
875 return;
878 ptr = fn_def->fn.args.arg_spec;
879 for (i = vararg = 0; ptr && *ptr; ptr++) {
880 if (*ptr == '|') {
881 vararg = 1;
882 *min = i;
883 } else
884 i++;
886 *max = i;
887 if (!vararg)
888 *min = i;
892 * gnm_func_get_arg_type:
893 * @fn_def: the fn defintion
894 * @arg_idx: zero based argument offset
896 * Returns: the type of the argument
898 char
899 gnm_func_get_arg_type (GnmFunc const *fn_def, int arg_idx)
901 char const *ptr;
903 g_return_val_if_fail (arg_idx >= 0, '?');
904 g_return_val_if_fail (fn_def != NULL, '?');
906 gnm_func_load_if_stub ((GnmFunc *)fn_def);
908 switch (fn_def->fn_type) {
909 case GNM_FUNC_TYPE_ARGS:
910 for (ptr = fn_def->fn.args.arg_spec; ptr && *ptr; ptr++) {
911 if (*ptr == '|')
912 continue;
913 if (arg_idx-- == 0)
914 return *ptr;
916 return '?';
918 case GNM_FUNC_TYPE_NODES:
919 return '?'; /* Close enough for now. */
921 case GNM_FUNC_TYPE_STUB:
922 #ifndef DEBUG_SWITCH_ENUM
923 default:
924 #endif
925 g_assert_not_reached ();
926 return '?';
931 * gnm_func_get_arg_type_string:
932 * @fn_def: the fn defintion
933 * @arg_idx: zero based argument offset
935 * Return value: (transfer none): the type of the argument as a string
937 char const *
938 gnm_func_get_arg_type_string (GnmFunc const *fn_def,
939 int arg_idx)
941 switch (gnm_func_get_arg_type (fn_def, arg_idx)) {
942 case 'f':
943 return _("Number");
944 case 's':
945 return _("String");
946 case 'b':
947 return _("Boolean");
948 case 'r':
949 return _("Cell Range");
950 case 'A':
951 return _("Area");
952 case 'E':
953 return _("Scalar, Blank, or Error");
954 case 'S':
955 return _("Scalar");
956 case '?':
957 /* Missing values will be NULL. */
958 return _("Any");
960 default:
961 g_warning ("Unknown arg type");
962 return "Broken";
967 * gnm_func_get_arg_name:
968 * @fn_def: the fn defintion
969 * @arg_idx: zero based argument offset
971 * Returns: (transfer full): the name of the argument
973 char *
974 gnm_func_get_arg_name (GnmFunc const *fn_def, guint arg_idx)
976 g_return_val_if_fail (fn_def != NULL, NULL);
978 gnm_func_load_if_stub ((GnmFunc *)fn_def);
980 if ((fn_def->arg_names_p != NULL)
981 && (arg_idx < fn_def->arg_names_p->len))
982 return g_strdup (g_ptr_array_index (fn_def->arg_names_p,
983 arg_idx));
984 return NULL;
988 * gnm_func_get_arg_description:
989 * @fn_def: the fn defintion
990 * @arg_idx: zero based argument offset
992 * Returns: (transfer none): the description of the argument
994 char const*
995 gnm_func_get_arg_description (GnmFunc const *fn_def, guint arg_idx)
997 gint i;
998 g_return_val_if_fail (fn_def != NULL, NULL);
1000 gnm_func_load_if_stub ((GnmFunc *)fn_def);
1002 for (i = 0;
1003 fn_def->help && fn_def->help[i].type != GNM_FUNC_HELP_END;
1004 i++) {
1005 gchar const *desc;
1007 if (fn_def->help[i].type != GNM_FUNC_HELP_ARG)
1008 continue;
1009 if (arg_idx--)
1010 continue;
1012 desc = strchr (F2 (fn_def, fn_def->help[i].text), ':');
1013 if (!desc)
1014 return "";
1016 desc++;
1017 while (g_unichar_isspace (g_utf8_get_char (desc)))
1018 desc = g_utf8_next_char (desc);
1019 return desc;
1022 return "";
1026 * gnm_func_convert_markup_to_pango:
1027 * @desc: the fn or arg description string
1028 * @target: target widget for the markup.
1030 * Return value: the escaped string with @{} markup converted to
1031 * pango markup
1033 char *
1034 gnm_func_convert_markup_to_pango (char const *desc, GtkWidget *target)
1036 GString *str;
1037 gchar *markup, *at;
1038 GdkRGBA link_color;
1039 PangoColor pg;
1040 char *link_color_text, *span_text;
1041 size_t span_text_len;
1043 gnm_get_link_color (target, &link_color);
1044 pg.red = 65535 * link_color.red;
1045 pg.green = 65535 * link_color.green;
1046 pg.blue = 65535 * link_color.blue;
1047 link_color_text = pango_color_to_string (&pg);
1048 span_text = g_strdup_printf ("<span foreground=\"%s\">",
1049 link_color_text);
1050 span_text_len = strlen (span_text);
1051 g_free (link_color_text);
1053 markup = g_markup_escape_text (desc, -1);
1054 str = g_string_new (markup);
1055 g_free (markup);
1057 while ((at = strstr (str->str, "@{"))) {
1058 gint len = at - str->str;
1059 go_string_replace (str, len, 2, span_text, -1);
1060 if ((at = strstr
1061 (str->str + len + span_text_len, "}"))) {
1062 len = at - str->str;
1063 go_string_replace (str, len, 1, "</span>", -1);
1064 } else
1065 g_string_append (str, "</span>");
1067 g_free (span_text);
1069 return g_string_free (str, FALSE);
1073 /* ------------------------------------------------------------------------- */
1075 static inline void
1076 free_values (GnmValue **values, int top)
1078 int i;
1080 for (i = 0; i < top; i++)
1081 if (values [i])
1082 value_release (values [i]);
1085 /* ------------------------------------------------------------------------- */
1088 * function_call_with_exprs:
1089 * @ei: EvalInfo containing valid fn_def!
1091 * Do the guts of calling a function.
1093 * Returns the result.
1095 GnmValue *
1096 function_call_with_exprs (GnmFuncEvalInfo *ei)
1098 GnmFunc const *fn_def;
1099 int i, iter_count, iter_width = 0, iter_height = 0;
1100 char arg_type;
1101 GnmValue **args, *tmp = NULL;
1102 int *iter_item = NULL;
1103 int argc;
1104 GnmExprConstPtr *argv;
1105 GnmExprEvalFlags flags, pass_flags;
1107 g_return_val_if_fail (ei != NULL, NULL);
1108 g_return_val_if_fail (ei->func_call != NULL, NULL);
1110 flags = ei->flags;
1112 argc = ei->func_call->argc;
1113 argv = ei->func_call->argv;
1114 fn_def = ei->func_call->func;
1116 gnm_func_load_if_stub ((GnmFunc *)fn_def);
1118 /* Functions that deal with ExprNodes */
1119 if (fn_def->fn_type == GNM_FUNC_TYPE_NODES)
1120 return fn_def->fn.nodes (ei, argc, argv);
1122 /* Functions that take pre-computed Values */
1123 if (argc > fn_def->fn.args.max_args ||
1124 argc < fn_def->fn.args.min_args)
1125 return value_new_error_NA (ei->pos);
1127 args = g_alloca (sizeof (GnmValue *) * fn_def->fn.args.max_args);
1128 iter_count = (eval_pos_is_array_context (ei->pos) &&
1129 (flags & GNM_EXPR_EVAL_PERMIT_NON_SCALAR))
1130 ? 0 : -1;
1132 /* Optimization for IF when implicit iteration is not used. */
1133 if (ei->func_call->func->fn.args.func == gnumeric_if &&
1134 iter_count == -1)
1135 return gnumeric_if2 (ei, argc, argv, flags);
1137 pass_flags = (flags &
1138 (GNM_EXPR_EVAL_ARRAY_CONTEXT));
1140 for (i = 0; i < argc; i++) {
1141 char arg_type = fn_def->fn.args.arg_types[i];
1142 /* expr is always non-null, missing args are encoded as
1143 * const = empty */
1144 GnmExpr const *expr = argv[i];
1146 if (arg_type == 'A' || arg_type == 'r') {
1147 tmp = args[i] = gnm_expr_eval
1148 (expr, ei->pos,
1149 pass_flags |
1150 GNM_EXPR_EVAL_PERMIT_NON_SCALAR |
1151 GNM_EXPR_EVAL_WANT_REF);
1152 if (VALUE_IS_ERROR (tmp)) {
1153 free_values (args, i);
1154 return tmp;
1157 if (VALUE_IS_CELLRANGE (tmp)) {
1158 gnm_cellref_make_abs (&tmp->v_range.cell.a,
1159 &tmp->v_range.cell.a,
1160 ei->pos);
1161 gnm_cellref_make_abs (&tmp->v_range.cell.b,
1162 &tmp->v_range.cell.b,
1163 ei->pos);
1164 /* Array args accept scalars */
1165 } else if (arg_type != 'A' && !VALUE_IS_ARRAY (tmp)) {
1166 free_values (args, i + 1);
1167 return value_new_error_VALUE (ei->pos);
1169 continue;
1172 /* force scalars whenever we are certain */
1173 tmp = args[i] = gnm_expr_eval
1174 (expr, ei->pos,
1175 pass_flags |
1176 GNM_EXPR_EVAL_PERMIT_EMPTY |
1177 (iter_count >= 0 || arg_type == '?'
1178 ? GNM_EXPR_EVAL_PERMIT_NON_SCALAR
1179 : 0));
1181 if (arg_type == '?') /* '?' arguments are unrestriced */
1182 continue;
1184 /* optional arguments can be blank */
1185 if (i >= fn_def->fn.args.min_args && VALUE_IS_EMPTY (tmp)) {
1186 if (arg_type == 'E' && !gnm_expr_is_empty (expr)) {
1187 /* An actual argument produced empty. Make
1188 sure function sees that. */
1189 args[i] = value_new_empty ();
1192 continue;
1195 if (tmp == NULL)
1196 tmp = args[i] = value_new_empty ();
1198 /* Handle implicit intersection or iteration depending on flags */
1199 if (VALUE_IS_CELLRANGE (tmp) || VALUE_IS_ARRAY (tmp)) {
1200 if (iter_count > 0) {
1201 if (iter_width != value_area_get_width (tmp, ei->pos) ||
1202 iter_height != value_area_get_height (tmp, ei->pos)) {
1203 free_values (args, i + 1);
1204 return value_new_error_VALUE (ei->pos);
1206 } else {
1207 if (iter_count < 0) {
1208 g_warning ("Damn I thought this was impossible");
1209 iter_count = 0;
1211 iter_item = g_alloca (sizeof (int) * argc);
1212 iter_width = value_area_get_width (tmp, ei->pos);
1213 iter_height = value_area_get_height (tmp, ei->pos);
1215 iter_item [iter_count++] = i;
1217 /* no need to check type, we would fail comparing a range against a "b, f, or s" */
1218 continue;
1221 /* All of these argument types must be scalars */
1222 switch (arg_type) {
1223 case 'b':
1224 if (VALUE_IS_STRING (tmp)) {
1225 gboolean err;
1226 gboolean b = value_get_as_bool (tmp, &err);
1227 if (err) {
1228 free_values (args, i + 1);
1229 return value_new_error_VALUE (ei->pos);
1231 value_release (args[i]);
1232 tmp = args[i] = value_new_bool (b);
1233 break;
1235 /* Fall through. */
1236 case 'f':
1237 if (VALUE_IS_STRING (tmp)) {
1238 tmp = format_match_number (value_peek_string (tmp), NULL,
1239 sheet_date_conv (ei->pos->sheet));
1240 if (tmp == NULL) {
1241 free_values (args, i + 1);
1242 return value_new_error_VALUE (ei->pos);
1244 value_release (args [i]);
1245 args[i] = tmp;
1246 } else if (VALUE_IS_ERROR (tmp)) {
1247 free_values (args, i);
1248 return tmp;
1249 } else if (VALUE_IS_EMPTY (tmp)) {
1250 value_release (args [i]);
1251 tmp = args[i] = value_new_int (0);
1254 if (!VALUE_IS_NUMBER (tmp))
1255 return value_new_error_VALUE (ei->pos);
1256 break;
1258 case 's':
1259 case 'S':
1260 if (VALUE_IS_ERROR (tmp)) {
1261 free_values (args, i);
1262 return tmp;
1264 break;
1266 case 'E': /* nothing necessary */
1267 break;
1269 /* case '?': handled above */
1270 default:
1271 g_warning ("Unknown argument type '%c'", arg_type);
1272 break;
1276 while (i < fn_def->fn.args.max_args)
1277 args [i++] = NULL;
1279 if (iter_item != NULL) {
1280 int x, y;
1281 GnmValue *res = value_new_array_empty (iter_width, iter_height);
1282 GnmValue const *elem, *err;
1283 GnmValue **iter_vals = g_alloca (sizeof (GnmValue *) * iter_count);
1284 GnmValue **iter_args = g_alloca (sizeof (GnmValue *) * iter_count);
1286 /* collect the args we will iterate on */
1287 for (i = 0 ; i < iter_count; i++)
1288 iter_vals[i] = args[iter_item[i]];
1290 for (x = iter_width; x-- > 0 ; )
1291 for (y = iter_height; y-- > 0 ; ) {
1292 /* marshal the args */
1293 err = NULL;
1294 for (i = 0 ; i < iter_count; i++) {
1295 elem = value_area_get_x_y (iter_vals[i], x, y, ei->pos);
1296 arg_type = fn_def->fn.args.arg_types[iter_item[i]];
1297 if (arg_type == 'b' || arg_type == 'f') {
1298 if (VALUE_IS_EMPTY (elem))
1299 elem = value_zero;
1300 else if (VALUE_IS_STRING (elem)) {
1301 tmp = format_match_number (value_peek_string (elem), NULL,
1302 sheet_date_conv (ei->pos->sheet));
1303 if (tmp != NULL) {
1304 args [iter_item[i]] = iter_args [i] = tmp;
1305 continue;
1306 } else
1307 break;
1308 } else if (VALUE_IS_ERROR (elem)) {
1309 err = elem;
1310 break;
1311 } else if (!VALUE_IS_NUMBER (elem))
1312 break;
1313 } else if (arg_type == 's') {
1314 if (VALUE_IS_EMPTY (elem)) {
1315 args [iter_item[i]] = iter_args [i] = value_new_string ("");
1316 continue;
1317 } else if (VALUE_IS_ERROR (elem)) {
1318 err = elem;
1319 break;
1320 } else if (!VALUE_IS_STRING (elem))
1321 break;
1322 } else if (elem == NULL) {
1323 args [iter_item[i]] = iter_args [i] = value_new_empty ();
1324 continue;
1326 args [iter_item[i]] = iter_args [i] = value_dup (elem);
1329 res->v_array.vals[x][y] = (i == iter_count)
1330 ? fn_def->fn.args.func (ei, (GnmValue const * const *)args)
1331 : ((err != NULL) ? value_dup (err)
1332 : value_new_error_VALUE (ei->pos));
1333 free_values (iter_args, i);
1336 /* free the primaries, not the already freed iteration */
1337 for (i = 0 ; i < iter_count; i++)
1338 args[iter_item[i]] = iter_vals[i];
1339 tmp = res;
1340 i = fn_def->fn.args.max_args;
1341 } else
1342 tmp = fn_def->fn.args.func (ei, (GnmValue const * const *)args);
1344 free_values (args, i);
1345 return tmp;
1349 * Use this to invoke a register function: the only drawback is that
1350 * you have to compute/expand all of the values to use this
1352 GnmValue *
1353 function_call_with_values (GnmEvalPos const *ep, char const *fn_name,
1354 int argc, GnmValue const * const *values)
1356 GnmFunc *fn_def;
1358 g_return_val_if_fail (ep != NULL, NULL);
1359 g_return_val_if_fail (fn_name != NULL, NULL);
1360 g_return_val_if_fail (ep->sheet != NULL, NULL);
1362 /* FIXME : support workbook local functions */
1363 fn_def = gnm_func_lookup (fn_name, NULL);
1364 if (fn_def == NULL)
1365 return value_new_error_NAME (ep);
1366 return function_def_call_with_values (ep, fn_def, argc, values);
1369 GnmValue *
1370 function_def_call_with_values (GnmEvalPos const *ep, GnmFunc const *fn_def,
1371 int argc, GnmValue const * const *values)
1373 GnmValue *retval;
1374 GnmExprFunction ef;
1375 GnmFuncEvalInfo fs;
1377 fs.pos = ep;
1378 fs.func_call = &ef;
1379 ef.func = (GnmFunc *)fn_def;
1381 gnm_func_load_if_stub ((GnmFunc *)fn_def);
1383 if (fn_def->fn_type == GNM_FUNC_TYPE_NODES) {
1385 * If function deals with ExprNodes, create some
1386 * temporary ExprNodes with constants.
1388 GnmExprConstant *expr = g_new (GnmExprConstant, argc);
1389 GnmExprConstPtr *argv = g_new (GnmExprConstPtr, argc);
1390 int i;
1392 for (i = 0; i < argc; i++) {
1393 gnm_expr_constant_init (expr + i, values[i]);
1394 argv[i] = (GnmExprConstPtr)(expr + i);
1396 retval = fn_def->fn.nodes (&fs, argc, argv);
1397 g_free (argv);
1398 g_free (expr);
1399 } else
1400 retval = fn_def->fn.args.func (&fs, values);
1402 return retval;
1405 /* ------------------------------------------------------------------------- */
1407 typedef struct {
1408 FunctionIterateCB callback;
1409 void *closure;
1410 gboolean strict;
1411 gboolean ignore_subtotal;
1412 } IterateCallbackClosure;
1415 * cb_iterate_cellrange:
1417 * Helper routine used by the function_iterate_do_value routine.
1418 * Invoked by the sheet cell range iterator.
1420 static GnmValue *
1421 cb_iterate_cellrange (GnmCellIter const *iter, gpointer user)
1424 IterateCallbackClosure *data = user;
1425 GnmCell *cell;
1426 GnmValue *res;
1427 GnmEvalPos ep;
1429 if (NULL == (cell = iter->cell)) {
1430 ep.sheet = iter->pp.sheet;
1431 ep.dep = NULL;
1432 ep.eval.col = iter->pp.eval.col;
1433 ep.eval.row = iter->pp.eval.row;
1434 return (*data->callback)(&ep, NULL, data->closure);
1437 if (data->ignore_subtotal && gnm_cell_has_expr (cell) &&
1438 gnm_expr_top_contains_subtotal (cell->base.texpr))
1439 return NULL;
1441 gnm_cell_eval (cell);
1442 eval_pos_init_cell (&ep, cell);
1444 /* If we encounter an error for the strict case, short-circuit here. */
1445 if (data->strict && (NULL != (res = gnm_cell_is_error (cell))))
1446 return value_new_error_str (&ep, res->v_err.mesg);
1448 /* All other cases -- including error -- just call the handler. */
1449 return (*data->callback)(&ep, cell->value, data->closure);
1453 * function_iterate_do_value:
1455 * Helper routine for function_iterate_argument_values.
1457 static GnmValue *
1458 function_iterate_do_value (GnmEvalPos const *ep,
1459 FunctionIterateCB callback,
1460 gpointer closure,
1461 GnmValue const *value,
1462 gboolean strict,
1463 CellIterFlags iter_flags)
1465 GnmValue *res = NULL;
1467 switch (value->v_any.type){
1468 case VALUE_ERROR:
1469 if (strict) {
1470 res = value_dup (value);
1471 break;
1473 /* Fall through. */
1475 case VALUE_EMPTY:
1476 case VALUE_BOOLEAN:
1477 case VALUE_FLOAT:
1478 case VALUE_STRING:
1479 res = (*callback)(ep, value, closure);
1480 break;
1482 case VALUE_ARRAY: {
1483 int x, y;
1485 /* Note the order here. */
1486 for (y = 0; y < value->v_array.y; y++) {
1487 for (x = 0; x < value->v_array.x; x++) {
1488 res = function_iterate_do_value (
1489 ep, callback, closure,
1490 value->v_array.vals [x][y],
1491 strict, CELL_ITER_IGNORE_BLANK);
1492 if (res != NULL)
1493 return res;
1496 break;
1498 case VALUE_CELLRANGE: {
1499 IterateCallbackClosure data;
1501 data.callback = callback;
1502 data.closure = closure;
1503 data.strict = strict;
1504 data.ignore_subtotal = (iter_flags & CELL_ITER_IGNORE_SUBTOTAL) != 0;
1506 res = workbook_foreach_cell_in_range (ep, value, iter_flags,
1507 cb_iterate_cellrange,
1508 &data);
1511 return res;
1515 * function_iterate_argument_values:
1516 * @ep: The position in a workbook at which to evaluate
1517 * @callback: (scope call): The routine to be invoked for every value computed
1518 * @callback_closure: Closure for the callback.
1519 * @argc:
1520 * @argv:
1521 * @strict: If TRUE, the function is considered "strict". This means
1522 * that if an error value occurs as an argument, the iteration
1523 * will stop and that error will be returned. If FALSE, an
1524 * error will be passed on to the callback (as a GnmValue *
1525 * of type VALUE_ERROR).
1526 * @iter_flags:
1528 * Return value:
1529 * NULL : if no errors were reported.
1530 * GnmValue * : if an error was found during strict evaluation
1531 * VALUE_TERMINATE : if the callback requested termination of the iteration.
1533 * This routine provides a simple way for internal functions with variable
1534 * number of arguments to be written: this would iterate over a list of
1535 * expressions (expr_node_list) and will invoke the callback for every
1536 * GnmValue found on the list (this means that ranges get properly expaned).
1538 GnmValue *
1539 function_iterate_argument_values (GnmEvalPos const *ep,
1540 FunctionIterateCB callback,
1541 void *callback_closure,
1542 int argc,
1543 GnmExprConstPtr const *argv,
1544 gboolean strict,
1545 CellIterFlags iter_flags)
1547 GnmValue *result = NULL;
1548 int a;
1550 for (a = 0; result == NULL && a < argc; a++) {
1551 GnmExpr const *expr = argv[a];
1552 GnmValue *val;
1554 if (iter_flags & CELL_ITER_IGNORE_SUBTOTAL &&
1555 gnm_expr_contains_subtotal (expr))
1556 continue;
1558 /* need to drill down into names to handle things like
1559 * sum(name) with name := (A:A,B:B) */
1560 while (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_NAME) {
1561 GnmExprTop const *texpr = expr->name.name->texpr;
1562 expr = texpr ? texpr->expr : NULL;
1563 if (expr == NULL) {
1564 if (strict)
1565 return value_new_error_REF (ep);
1566 break;
1569 if (!expr)
1570 continue;
1572 /* Handle sets as a special case */
1573 if (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_SET) {
1574 result = function_iterate_argument_values
1575 (ep, callback, callback_closure,
1576 expr->set.argc, expr->set.argv,
1577 strict, iter_flags);
1578 continue;
1581 /* We need a cleaner model of what to do here.
1582 * In non-array mode
1583 * SUM(Range)
1584 * will obviously return Range
1586 * SUM(INDIRECT(Range))
1587 * SUM(INDIRECT(Range):....)
1588 * will do implicit intersection on Range (in non-array mode),
1589 * but allow non-scalar results from indirect (no intersection)
1591 * SUM(Range=3)
1592 * will do implicit intersection in non-array mode */
1593 if (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_CONSTANT)
1594 val = value_dup (expr->constant.value);
1595 else if (eval_pos_is_array_context (ep) ||
1596 GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_FUNCALL ||
1597 GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_RANGE_CTOR ||
1598 GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_INTERSECT)
1599 val = gnm_expr_eval (expr, ep,
1600 GNM_EXPR_EVAL_PERMIT_EMPTY | GNM_EXPR_EVAL_PERMIT_NON_SCALAR);
1601 else
1602 val = gnm_expr_eval (expr, ep, GNM_EXPR_EVAL_PERMIT_EMPTY);
1604 if (val == NULL)
1605 continue;
1607 if (strict && VALUE_IS_ERROR (val)) {
1608 /* Be careful not to make VALUE_TERMINATE into a real value */
1609 return val;
1612 result = function_iterate_do_value (ep, callback, callback_closure,
1613 val, strict, iter_flags);
1614 value_release (val);
1616 return result;
1620 GnmFunc const *
1621 gnm_eval_info_get_func (GnmFuncEvalInfo const *ei)
1623 return ei->func_call->func;
1627 gnm_eval_info_get_arg_count (GnmFuncEvalInfo const *ei)
1629 return ei->func_call->argc;