1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
4 * func.c: Function management and utility routines.
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>
18 #include "parse-util.h"
19 #include "dependent.h"
21 #include "expr-impl.h"
22 #include "expr-name.h"
24 #include "workbook-priv.h"
27 #include "number-match.h"
28 #include "func-builtin.h"
29 #include "command-context-stderr.h"
30 #include "gnm-plugin.h"
33 #include <goffice/goffice.h>
38 #define F2(func,s) dgettext ((func)->tdomain->str, (s))
40 static GList
*categories
;
41 static GnmFuncGroup
*unknown_cat
;
43 static GHashTable
*functions_by_name
;
44 static GHashTable
*functions_by_localized_name
;
50 g_hash_table_new (go_ascii_strcase_hash
, go_ascii_strcase_equal
);
53 functions_by_localized_name
=
54 g_hash_table_new (go_ascii_strcase_hash
, go_ascii_strcase_equal
);
60 functions_shutdown (void)
62 while (unknown_cat
!= NULL
&& unknown_cat
->functions
!= NULL
) {
63 GnmFunc
*func
= unknown_cat
->functions
->data
;
64 if (func
->usage_count
> 0) {
65 g_warning ("Function %s still has %d users.\n",
66 gnm_func_get_name (func
, FALSE
),
68 func
->usage_count
= 0;
72 func_builtin_shutdown ();
74 g_hash_table_destroy (functions_by_name
);
75 functions_by_name
= NULL
;
77 g_hash_table_destroy (functions_by_localized_name
);
78 functions_by_localized_name
= NULL
;
84 * Return value: (element-type GnmFunc) (transfer container):
87 gnm_func_enumerate (void)
89 GPtrArray
*res
= g_ptr_array_new ();
93 g_hash_table_iter_init (&hiter
, functions_by_name
);
94 while (g_hash_table_iter_next (&hiter
, NULL
, &value
))
95 g_ptr_array_add (res
, value
);
101 gnm_func_load_if_stub (GnmFunc
*func
)
103 if (func
->fn_type
== GNM_FUNC_TYPE_STUB
)
104 gnm_func_load_stub (func
);
108 split_at_colon (char const *s
, char **rest
)
110 char *dup
= g_strdup (s
);
111 char *colon
= strchr (dup
, ':');
114 if (rest
) *rest
= colon
+ 1;
116 if (rest
) *rest
= NULL
;
121 /* ------------------------------------------------------------------------- */
124 gnm_func_group_free (GnmFuncGroup
*fn_group
)
126 g_return_if_fail (fn_group
!= NULL
);
127 g_return_if_fail (fn_group
->functions
== NULL
);
129 if (fn_group
->ref_count
-- > 1)
132 go_string_unref (fn_group
->internal_name
);
133 go_string_unref (fn_group
->display_name
);
137 static GnmFuncGroup
*
138 gnm_func_group_ref (GnmFuncGroup
*fn_group
)
140 fn_group
->ref_count
++;
145 gnm_func_group_get_type (void)
150 t
= g_boxed_type_register_static ("GnmFuncGroup",
151 (GBoxedCopyFunc
)gnm_func_group_ref
,
152 (GBoxedFreeFunc
)gnm_func_group_free
);
158 function_category_compare (gconstpointer a
, gconstpointer b
)
160 GnmFuncGroup
const *cat_a
= a
;
161 GnmFuncGroup
const *cat_b
= b
;
163 return go_string_cmp (cat_a
->display_name
, cat_b
->display_name
);
167 gnm_func_group_fetch (char const *name
, char const *translation
)
169 GnmFuncGroup
*cat
= NULL
;
172 g_return_val_if_fail (name
!= NULL
, NULL
);
174 for (l
= categories
; l
!= NULL
; l
= l
->next
) {
176 if (strcmp (cat
->internal_name
->str
, name
) == 0) {
182 cat
= g_new (GnmFuncGroup
, 1);
183 cat
->internal_name
= go_string_new (name
);
185 if (translation
!= NULL
) {
186 cat
->display_name
= go_string_new (translation
);
187 cat
->has_translation
= TRUE
;
189 cat
->display_name
= go_string_new (name
);
190 cat
->has_translation
= FALSE
;
192 cat
->functions
= NULL
;
193 categories
= g_list_insert_sorted (
194 categories
, cat
, &function_category_compare
);
195 } else if (translation
!= NULL
&& translation
!= name
&&
196 !cat
->has_translation
) {
197 go_string_unref (cat
->display_name
);
198 cat
->display_name
= go_string_new (translation
);
199 cat
->has_translation
= TRUE
;
200 categories
= g_list_remove_link (categories
, l
);
202 categories
= g_list_insert_sorted (
203 categories
, cat
, &function_category_compare
);
210 gnm_func_group_get_nth (int n
)
212 return g_list_nth_data (categories
, n
);
216 gnm_func_group_add_func (GnmFuncGroup
*fn_group
, GnmFunc
*fn_def
)
218 g_return_if_fail (fn_group
!= NULL
);
219 g_return_if_fail (fn_def
!= NULL
);
221 fn_group
->functions
= g_slist_prepend (fn_group
->functions
, fn_def
);
225 gnm_func_group_remove_func (GnmFuncGroup
*fn_group
, GnmFunc
*fn_def
)
227 g_return_if_fail (fn_group
!= NULL
);
228 g_return_if_fail (fn_def
!= NULL
);
230 fn_group
->functions
= g_slist_remove (fn_group
->functions
, fn_def
);
231 if (fn_group
->functions
== NULL
) {
232 categories
= g_list_remove (categories
, fn_group
);
233 if (unknown_cat
== fn_group
)
235 gnm_func_group_free (fn_group
);
239 /******************************************************************************/
242 extract_arg_types (GnmFunc
*def
)
246 function_def_count_args (def
,
247 &def
->fn
.args
.min_args
,
248 &def
->fn
.args
.max_args
);
249 def
->fn
.args
.arg_types
= g_malloc (def
->fn
.args
.max_args
+ 1);
250 for (i
= 0; i
< def
->fn
.args
.max_args
; i
++)
251 def
->fn
.args
.arg_types
[i
] = function_def_get_arg_type (def
, i
);
252 def
->fn
.args
.arg_types
[i
] = 0;
256 error_function_no_full_info (GnmFuncEvalInfo
*ei
,
258 GnmExprConstPtr
const *argv
)
260 return value_new_error (ei
->pos
, _("Function implementation not available."));
264 gnm_func_clear_arg_names (GnmFunc
*fd
)
266 if (fd
->arg_names_p
) {
267 g_ptr_array_foreach (fd
->arg_names_p
, (GFunc
) g_free
, NULL
);
268 g_ptr_array_free (fd
->arg_names_p
, TRUE
);
269 fd
->arg_names_p
= NULL
;
274 gnm_func_create_arg_names (GnmFunc
*fn_def
)
279 g_return_if_fail (fn_def
!= NULL
);
281 ptr
= g_ptr_array_new ();
283 fn_def
->help
&& fn_def
->help
[i
].type
!= GNM_FUNC_HELP_END
;
285 if (fn_def
->help
[i
].type
!= GNM_FUNC_HELP_ARG
)
290 (F2(fn_def
, fn_def
->help
[i
].text
), NULL
));
293 gnm_func_clear_arg_names (fn_def
);
294 fn_def
->arg_names_p
= ptr
;
299 gnm_func_load_stub (GnmFunc
*func
)
301 GnmFuncDescriptor desc
;
303 g_return_if_fail (func
->fn_type
== GNM_FUNC_TYPE_STUB
);
305 /* default the content to 0 in case we add new fields
306 * later and the services do not fill them in
308 memset (&desc
, 0, sizeof (GnmFuncDescriptor
));
310 if (func
->fn
.load_desc (func
, &desc
)) {
311 func
->help
= desc
.help
? desc
.help
: NULL
;
312 if (desc
.fn_args
!= NULL
) {
313 func
->fn_type
= GNM_FUNC_TYPE_ARGS
;
314 func
->fn
.args
.func
= desc
.fn_args
;
315 func
->fn
.args
.arg_spec
= desc
.arg_spec
;
316 extract_arg_types (func
);
317 } else if (desc
.fn_nodes
!= NULL
) {
318 func
->fn_type
= GNM_FUNC_TYPE_NODES
;
319 func
->fn
.nodes
= desc
.fn_nodes
;
321 g_warning ("Invalid function descriptor with no function");
323 func
->linker
= desc
.linker
;
324 func
->impl_status
= desc
.impl_status
;
325 func
->test_status
= desc
.test_status
;
326 func
->flags
= desc
.flags
;
327 gnm_func_create_arg_names (func
);
329 func
->fn_type
= GNM_FUNC_TYPE_NODES
;
330 func
->fn
.nodes
= &error_function_no_full_info
;
336 gnm_func_set_localized_name (GnmFunc
*fd
, const char *lname
)
338 gboolean in_hashes
= !(fd
->flags
& GNM_FUNC_IS_WORKBOOK_LOCAL
);
340 if (in_hashes
&& fd
->localized_name
)
341 g_hash_table_remove (functions_by_localized_name
, fd
->localized_name
);
342 g_free (fd
->localized_name
);
344 fd
->localized_name
= g_strdup (lname
);
345 if (in_hashes
&& lname
)
346 g_hash_table_insert (functions_by_localized_name
,
347 fd
->localized_name
, fd
);
351 gnm_func_free (GnmFunc
*func
)
355 g_return_if_fail (func
!= NULL
);
356 g_return_if_fail (func
->usage_count
== 0);
358 group
= func
->fn_group
;
360 gnm_func_group_remove_func (group
, func
);
362 gnm_func_set_localized_name (func
, NULL
);
364 if (!(func
->flags
& GNM_FUNC_IS_WORKBOOK_LOCAL
)) {
365 g_hash_table_remove (functions_by_name
, func
->name
);
368 if (func
->fn_type
== GNM_FUNC_TYPE_ARGS
)
369 g_free (func
->fn
.args
.arg_types
);
371 g_free ((char *)func
->name
);
374 go_string_unref (func
->tdomain
);
376 gnm_func_clear_arg_names (func
);
382 gnm_func_ref (GnmFunc
*func
)
384 g_return_val_if_fail (func
!= NULL
, NULL
);
387 if (func
->usage_count
== 1 && func
->usage_notify
!= NULL
)
388 func
->usage_notify (func
, 1);
393 gnm_func_unref (GnmFunc
*func
)
395 g_return_if_fail (func
!= NULL
);
396 g_return_if_fail (func
->usage_count
> 0);
399 if (func
->usage_count
== 0 && func
->usage_notify
!= NULL
)
400 func
->usage_notify (func
, 0);
404 gnm_func_get_type (void)
409 t
= g_boxed_type_register_static ("GnmFunc",
410 (GBoxedCopyFunc
)gnm_func_ref
,
411 (GBoxedFreeFunc
)gnm_func_unref
);
417 gnm_func_lookup (char const *name
, Workbook
*scope
)
419 GnmFunc
*fd
= g_hash_table_lookup (functions_by_name
, name
);
422 if (scope
== NULL
|| scope
->sheet_local_functions
== NULL
)
424 return g_hash_table_lookup (scope
->sheet_local_functions
, (gpointer
)name
);
428 gnm_func_lookup_localized (char const *name
, Workbook
*scope
)
431 GHashTableIter hiter
;
434 /* Must localize all function names. */
435 g_hash_table_iter_init (&hiter
, functions_by_name
);
436 while (g_hash_table_iter_next (&hiter
, NULL
, &value
)) {
438 (void)gnm_func_get_name (fd
, TRUE
);
441 fd
= g_hash_table_lookup (functions_by_localized_name
, name
);
444 if (scope
== NULL
|| scope
->sheet_local_functions
== NULL
)
446 return g_hash_table_lookup (scope
->sheet_local_functions
, (gpointer
)name
);
450 * gnm_func_lookup_prefix:
451 * @prefix: prefix to search for
453 * @trans: whether to search translated function names
455 * Returns: (element-type GnmFunc*) (transfer full):
458 gnm_func_lookup_prefix (char const *prefix
, Workbook
*scope
, gboolean trans
)
461 GHashTableIter hiter
;
465 * Always iterate over functions_by_name as the localized name
466 * might not be set yet.
468 g_hash_table_iter_init (&hiter
, functions_by_name
);
469 while (g_hash_table_iter_next (&hiter
, NULL
, &value
)) {
471 if (!(fd
->flags
& GNM_FUNC_IS_PLACEHOLDER
)) {
472 const char *name
= gnm_func_get_name (fd
, trans
);
473 if (g_str_has_prefix (name
, prefix
)) {
475 res
= g_slist_prepend (res
, fd
);
484 gnm_func_add (GnmFuncGroup
*fn_group
,
485 GnmFuncDescriptor
const *desc
,
488 static char const valid_tokens
[] = "fsbraAES?|";
492 g_return_val_if_fail (fn_group
!= NULL
, NULL
);
493 g_return_val_if_fail (desc
!= NULL
, NULL
);
495 func
= g_new (GnmFunc
, 1);
498 tdomain
= GETTEXT_PACKAGE
;
500 func
->name
= g_strdup (desc
->name
);
501 func
->help
= desc
->help
? desc
->help
: NULL
;
502 func
->tdomain
= go_string_new (tdomain
);
503 func
->linker
= desc
->linker
;
504 func
->usage_notify
= desc
->usage_notify
;
505 func
->flags
= desc
->flags
;
506 func
->impl_status
= desc
->impl_status
;
507 func
->test_status
= desc
->test_status
;
508 func
->localized_name
= NULL
;
509 func
->arg_names_p
= NULL
;
511 func
->user_data
= NULL
;
512 func
->usage_count
= 0;
514 if (desc
->fn_args
!= NULL
) {
515 /* Check those arguments */
516 for (ptr
= desc
->arg_spec
; *ptr
; ptr
++) {
517 g_return_val_if_fail (strchr (valid_tokens
, *ptr
), NULL
);
520 func
->fn_type
= GNM_FUNC_TYPE_ARGS
;
521 func
->fn
.args
.func
= desc
->fn_args
;
522 func
->fn
.args
.arg_spec
= desc
->arg_spec
;
523 extract_arg_types (func
);
524 } else if (desc
->fn_nodes
!= NULL
) {
526 if (desc
->arg_spec
&& *desc
->arg_spec
) {
527 g_warning ("Arg spec for node function -- why?");
530 func
->fn_type
= GNM_FUNC_TYPE_NODES
;
531 func
->fn
.nodes
= desc
->fn_nodes
;
533 g_warning ("Invalid function has neither args nor nodes handler");
538 func
->fn_group
= fn_group
;
539 if (fn_group
!= NULL
)
540 gnm_func_group_add_func (fn_group
, func
);
541 if (!(func
->flags
& GNM_FUNC_IS_WORKBOOK_LOCAL
))
542 g_hash_table_insert (functions_by_name
,
543 (gpointer
)(func
->name
), func
);
545 gnm_func_create_arg_names (func
);
550 /* Handle unknown functions on import without losing their names */
552 unknownFunctionHandler (GnmFuncEvalInfo
*ei
,
553 G_GNUC_UNUSED
int argc
,
554 G_GNUC_UNUSED GnmExprConstPtr
const *argv
)
556 return value_new_error_NAME (ei
->pos
);
560 * gnm_func_upgrade_placeholder:
564 * @load_desc: (scope async):
565 * @opt_usage_notify: (scope async):
568 gnm_func_upgrade_placeholder (GnmFunc
*fd
,
569 GnmFuncGroup
*fn_group
,
571 GnmFuncLoadDesc load_desc
,
572 GnmFuncUsageNotify opt_usage_notify
)
574 g_return_if_fail (fd
!= NULL
);
575 g_return_if_fail (fd
->flags
& GNM_FUNC_IS_PLACEHOLDER
);
576 g_return_if_fail (fn_group
!= NULL
);
579 tdomain
= GETTEXT_PACKAGE
;
581 /* Remove from unknown_cat */
582 gnm_func_group_remove_func (fd
->fn_group
, fd
);
584 fd
->fn_type
= GNM_FUNC_TYPE_STUB
;
585 fd
->fn
.load_desc
= load_desc
;
586 fd
->usage_notify
= opt_usage_notify
;
588 go_string_unref (fd
->tdomain
);
589 fd
->tdomain
= go_string_new (tdomain
);
591 /* Clear localized_name so we can deduce the proper name. */
592 gnm_func_set_localized_name (fd
, NULL
);
594 fd
->flags
&= ~GNM_FUNC_IS_PLACEHOLDER
;
596 fd
->fn_group
= fn_group
;
597 gnm_func_group_add_func (fn_group
, fd
);
601 invent_name (const char *pref
, GHashTable
*h
, const char *template)
603 static int count
= 0;
604 char *name
= g_utf8_strdown (pref
, -1);
606 while (g_hash_table_lookup (h
, name
)) {
609 name
= g_strdup_printf (template, count
);
616 gnm_func_add_placeholder_full (Workbook
*scope
,
617 char const *gname
, char const *lname
,
620 GnmFuncDescriptor desc
;
622 char const *unknown_cat_name
= N_("Unknown Function");
623 gboolean copy_gname
= TRUE
;
624 gboolean copy_lname
= TRUE
;
626 g_return_val_if_fail (gname
|| lname
, NULL
);
627 g_return_val_if_fail (gname
== NULL
|| gnm_func_lookup (gname
, scope
) == NULL
, NULL
);
628 g_return_val_if_fail (lname
== NULL
|| gnm_func_lookup_localized (lname
, scope
) == NULL
, NULL
);
631 unknown_cat
= gnm_func_group_fetch
632 (unknown_cat_name
, _(unknown_cat_name
));
636 * This is actually a bit of a problem if we don't end up
637 * with a copy of lname (because there already is a function
638 * with that name). We're likely to save a template name,
639 * but I don't see what else to do.
641 gname
= invent_name (lname
, functions_by_name
, "unknown%d");
645 /* xgettext: This represents a made-up translated function name. */
646 lname
= invent_name (gname
, functions_by_localized_name
, _("unknown%d"));
650 if (gnm_debug_flag ("func"))
651 g_printerr ("Adding placeholder for %s (aka %s)\n", gname
, lname
);
653 memset (&desc
, 0, sizeof (GnmFuncDescriptor
));
655 desc
.arg_spec
= NULL
;
658 desc
.fn_nodes
= &unknownFunctionHandler
;
660 desc
.usage_notify
= NULL
;
661 desc
.flags
= GNM_FUNC_IS_PLACEHOLDER
;
662 desc
.impl_status
= GNM_FUNC_IMPL_STATUS_EXISTS
;
663 desc
.test_status
= GNM_FUNC_TEST_STATUS_UNKNOWN
;
666 desc
.flags
|= GNM_FUNC_IS_WORKBOOK_LOCAL
;
669 /* WISHLIST : it would be nice to have a log if these. */
670 g_warning ("Unknown %s function : %s", type
, desc
.name
);
674 func
= gnm_func_add (unknown_cat
, &desc
, NULL
);
677 gnm_func_set_localized_name (func
, lname
);
679 g_free ((char *)lname
);
683 g_free ((char *)gname
);
686 if (scope
->sheet_local_functions
== NULL
)
687 scope
->sheet_local_functions
= g_hash_table_new_full (
688 g_str_hash
, g_str_equal
,
689 NULL
, (GDestroyNotify
) gnm_func_free
);
690 g_hash_table_insert (scope
->sheet_local_functions
,
691 (gpointer
)func
->name
, func
);
698 * When importing it is useful to keep track of unknown function names.
699 * We may be missing a plugin or something similar.
701 * TODO : Eventully we should be able to keep track of these
702 * and replace them with something else. Possibly even reordering the
706 gnm_func_add_placeholder (Workbook
*scope
,
707 char const *name
, char const *type
)
709 return gnm_func_add_placeholder_full (scope
, name
, NULL
, type
);
713 gnm_func_add_placeholder_localized (char const *gname
, char const *lname
)
715 return gnm_func_add_placeholder_full (NULL
, gname
, lname
, "?");
718 /* Utility routine to be used for import and analysis tools */
720 gnm_func_lookup_or_add_placeholder (char const *name
)
722 GnmFunc
* f
= gnm_func_lookup (name
, NULL
);
724 f
= gnm_func_add_placeholder (NULL
, name
, "");
729 * gnm_func_get_user_data:
732 * Returns: (transfer none):
735 gnm_func_get_user_data (GnmFunc
const *func
)
737 g_return_val_if_fail (func
!= NULL
, NULL
);
739 return func
->user_data
;
743 gnm_func_set_user_data (GnmFunc
*func
, gpointer user_data
)
745 g_return_if_fail (func
!= NULL
);
747 func
->user_data
= user_data
;
751 gnm_func_get_name (GnmFunc
const *func
, gboolean localized_function_names
)
754 GnmFunc
*fd
= (GnmFunc
*)func
;
756 g_return_val_if_fail (func
!= NULL
, NULL
);
758 if (!localized_function_names
)
761 if (func
->localized_name
)
762 return func
->localized_name
;
765 * Deduce the translated names from the help texts. This
766 * code doesn't currently check for clashes in translated
770 gnm_func_load_if_stub (fd
);
773 (func
->localized_name
== NULL
&&
775 func
->help
[i
].type
!= GNM_FUNC_HELP_END
);
779 if (func
->help
[i
].type
!= GNM_FUNC_HELP_NAME
)
782 s
= func
->help
[i
].text
;
784 if (s
== sl
) /* String not actually translated. */
787 U
= split_at_colon (F2 (func
, s
), NULL
);
789 char *lname
= g_utf8_strdown (U
, -1);
790 gnm_func_set_localized_name (fd
, lname
);
796 if (!func
->localized_name
)
797 gnm_func_set_localized_name (fd
, fd
->name
);
799 return func
->localized_name
;
803 * gnm_func_get_description:
804 * @fn_def: the fn defintion
806 * Return value: the description of the function
810 gnm_func_get_description (GnmFunc
const *fn_def
)
813 g_return_val_if_fail (fn_def
!= NULL
, NULL
);
815 gnm_func_load_if_stub ((GnmFunc
*)fn_def
);
818 fn_def
->help
&& fn_def
->help
[i
].type
!= GNM_FUNC_HELP_END
;
822 if (fn_def
->help
[i
].type
!= GNM_FUNC_HELP_NAME
)
825 desc
= strchr (F2 (fn_def
, fn_def
->help
[i
].text
), ':');
826 return desc
? (desc
+ 1) : "";
832 * function_def_count_args:
833 * @fn_def: pointer to function definition
834 * @min: pointer to min. args
835 * @max: pointer to max. args
837 * This calculates the max and min args that
838 * can be passed; NB max can be G_MAXINT for
840 * NB. this data is not authoratitive for a
845 function_def_count_args (GnmFunc
const *fn_def
,
852 g_return_if_fail (min
!= NULL
);
853 g_return_if_fail (max
!= NULL
);
854 g_return_if_fail (fn_def
!= NULL
);
856 gnm_func_load_if_stub ((GnmFunc
*)fn_def
);
859 * FIXME: clearly for 'nodes' functions many of
860 * the type fields will need to be filled.
862 if (fn_def
->fn_type
== GNM_FUNC_TYPE_NODES
) {
864 if (g_ascii_strcasecmp ("INDEX",fn_def
->name
) == 0)
871 ptr
= fn_def
->fn
.args
.arg_spec
;
872 for (i
= vararg
= 0; ptr
&& *ptr
; ptr
++) {
885 * function_def_get_arg_type:
886 * @fn_def: the fn defintion
887 * @arg_idx: zero based argument offset
889 * Return value: the type of the argument
892 function_def_get_arg_type (GnmFunc
const *fn_def
, int arg_idx
)
896 g_return_val_if_fail (arg_idx
>= 0, '?');
897 g_return_val_if_fail (fn_def
!= NULL
, '?');
899 gnm_func_load_if_stub ((GnmFunc
*)fn_def
);
901 switch (fn_def
->fn_type
) {
902 case GNM_FUNC_TYPE_ARGS
:
903 for (ptr
= fn_def
->fn
.args
.arg_spec
; ptr
&& *ptr
; ptr
++) {
911 case GNM_FUNC_TYPE_NODES
:
912 return '?'; /* Close enough for now. */
914 case GNM_FUNC_TYPE_STUB
:
915 #ifndef DEBUG_SWITCH_ENUM
918 g_assert_not_reached ();
924 * function_def_get_arg_type_string:
925 * @fn_def: the fn defintion
926 * @arg_idx: zero based argument offset
928 * Return value: the type of the argument as a string
931 function_def_get_arg_type_string (GnmFunc
const *fn_def
,
934 switch (function_def_get_arg_type (fn_def
, arg_idx
)) {
942 return _("Cell Range");
946 return _("Scalar, Blank, or Error");
950 /* Missing values will be NULL. */
954 g_warning ("Unknown arg type");
960 * function_def_get_arg_name:
961 * @fn_def: the fn defintion
962 * @arg_idx: zero based argument offset
964 * Return value: the name of the argument (must be freed)
967 function_def_get_arg_name (GnmFunc
const *fn_def
, guint arg_idx
)
969 g_return_val_if_fail (fn_def
!= NULL
, NULL
);
971 gnm_func_load_if_stub ((GnmFunc
*)fn_def
);
973 if ((fn_def
->arg_names_p
!= NULL
)
974 && (arg_idx
< fn_def
->arg_names_p
->len
))
975 return g_strdup (g_ptr_array_index (fn_def
->arg_names_p
,
981 * gnm_func_get_arg_description:
982 * @fn_def: the fn defintion
983 * @arg_idx: zero based argument offset
985 * Return value: the namedescription of the argument
988 gnm_func_get_arg_description (GnmFunc
const *fn_def
, guint arg_idx
)
991 g_return_val_if_fail (fn_def
!= NULL
, NULL
);
993 gnm_func_load_if_stub ((GnmFunc
*)fn_def
);
996 fn_def
->help
&& fn_def
->help
[i
].type
!= GNM_FUNC_HELP_END
;
1000 if (fn_def
->help
[i
].type
!= GNM_FUNC_HELP_ARG
)
1005 desc
= strchr (F2 (fn_def
, fn_def
->help
[i
].text
), ':');
1010 while (g_unichar_isspace (g_utf8_get_char (desc
)))
1011 desc
= g_utf8_next_char (desc
);
1019 * gnm_func_convert_markup_to_pango:
1020 * @desc: the fn or arg description string
1021 * @target: target widget for the markup.
1023 * Return value: the escaped string with @{} markup converted to
1027 gnm_func_convert_markup_to_pango (char const *desc
, GtkWidget
*target
)
1031 GdkColor
*link_color
= NULL
;
1032 char *link_color_text
, *span_text
;
1033 size_t span_text_len
;
1035 gtk_widget_style_get (target
, "link-color", &link_color
, NULL
);
1037 link_color_text
= gdk_color_to_string (link_color
);
1038 gdk_color_free (link_color
);
1040 link_color_text
= g_strdup ("blue");
1041 span_text
= g_strdup_printf ("<span foreground=\"%s\">",
1043 span_text_len
= strlen (span_text
);
1044 g_free (link_color_text
);
1046 markup
= g_markup_escape_text (desc
, -1);
1047 str
= g_string_new (markup
);
1050 while ((at
= strstr (str
->str
, "@{"))) {
1051 gint len
= at
- str
->str
;
1052 go_string_replace (str
, len
, 2, span_text
, -1);
1054 (str
->str
+ len
+ span_text_len
, "}"))) {
1055 len
= at
- str
->str
;
1056 go_string_replace (str
, len
, 1, "</span>", -1);
1058 g_string_append (str
, "</span>");
1062 return g_string_free (str
, FALSE
);
1066 /* ------------------------------------------------------------------------- */
1069 free_values (GnmValue
**values
, int top
)
1073 for (i
= 0; i
< top
; i
++)
1075 value_release (values
[i
]);
1078 /* ------------------------------------------------------------------------- */
1081 * function_call_with_exprs:
1082 * @ei: EvalInfo containing valid fn_def!
1084 * Do the guts of calling a function.
1086 * Returns the result.
1089 function_call_with_exprs (GnmFuncEvalInfo
*ei
)
1091 GnmFunc
const *fn_def
;
1092 int i
, iter_count
, iter_width
= 0, iter_height
= 0;
1094 GnmValue
**args
, *tmp
= NULL
;
1095 int *iter_item
= NULL
;
1097 GnmExprConstPtr
*argv
;
1098 GnmExprEvalFlags flags
, pass_flags
;
1100 g_return_val_if_fail (ei
!= NULL
, NULL
);
1101 g_return_val_if_fail (ei
->func_call
!= NULL
, NULL
);
1105 argc
= ei
->func_call
->argc
;
1106 argv
= ei
->func_call
->argv
;
1107 fn_def
= ei
->func_call
->func
;
1109 gnm_func_load_if_stub ((GnmFunc
*)fn_def
);
1111 /* Functions that deal with ExprNodes */
1112 if (fn_def
->fn_type
== GNM_FUNC_TYPE_NODES
)
1113 return fn_def
->fn
.nodes (ei
, argc
, argv
);
1115 /* Functions that take pre-computed Values */
1116 if (argc
> fn_def
->fn
.args
.max_args
||
1117 argc
< fn_def
->fn
.args
.min_args
)
1118 return value_new_error_NA (ei
->pos
);
1120 args
= g_alloca (sizeof (GnmValue
*) * fn_def
->fn
.args
.max_args
);
1121 iter_count
= (eval_pos_is_array_context (ei
->pos
) &&
1122 (flags
& GNM_EXPR_EVAL_PERMIT_NON_SCALAR
))
1125 /* Optimization for IF when implicit iteration is not used. */
1126 if (ei
->func_call
->func
->fn
.args
.func
== gnumeric_if
&&
1128 return gnumeric_if2 (ei
, argc
, argv
, flags
);
1130 pass_flags
= (flags
&
1131 (GNM_EXPR_EVAL_ARRAY_CONTEXT
));
1133 for (i
= 0; i
< argc
; i
++) {
1134 char arg_type
= fn_def
->fn
.args
.arg_types
[i
];
1135 /* expr is always non-null, missing args are encoded as
1137 GnmExpr
const *expr
= argv
[i
];
1139 if (arg_type
== 'A' || arg_type
== 'r') {
1140 tmp
= args
[i
] = gnm_expr_eval
1143 GNM_EXPR_EVAL_PERMIT_NON_SCALAR
|
1144 GNM_EXPR_EVAL_WANT_REF
);
1145 if (VALUE_IS_ERROR (tmp
)) {
1146 free_values (args
, i
);
1150 if (VALUE_IS_CELLRANGE (tmp
)) {
1151 gnm_cellref_make_abs (&tmp
->v_range
.cell
.a
,
1152 &tmp
->v_range
.cell
.a
,
1154 gnm_cellref_make_abs (&tmp
->v_range
.cell
.b
,
1155 &tmp
->v_range
.cell
.b
,
1157 /* Array args accept scalars */
1158 } else if (arg_type
!= 'A' && !VALUE_IS_ARRAY (tmp
)) {
1159 free_values (args
, i
+ 1);
1160 return value_new_error_VALUE (ei
->pos
);
1165 /* force scalars whenever we are certain */
1166 tmp
= args
[i
] = gnm_expr_eval
1169 GNM_EXPR_EVAL_PERMIT_EMPTY
|
1170 (iter_count
>= 0 || arg_type
== '?'
1171 ? GNM_EXPR_EVAL_PERMIT_NON_SCALAR
1174 if (arg_type
== '?') /* '?' arguments are unrestriced */
1177 /* optional arguments can be blank */
1178 if (i
>= fn_def
->fn
.args
.min_args
&& VALUE_IS_EMPTY (tmp
)) {
1179 if (arg_type
== 'E' && !gnm_expr_is_empty (expr
)) {
1180 /* An actual argument produced empty. Make
1181 sure function sees that. */
1182 args
[i
] = value_new_empty ();
1189 tmp
= args
[i
] = value_new_empty ();
1191 /* Handle implicit intersection or iteration depending on flags */
1192 if (VALUE_IS_CELLRANGE (tmp
) || VALUE_IS_ARRAY (tmp
)) {
1193 if (iter_count
> 0) {
1194 if (iter_width
!= value_area_get_width (tmp
, ei
->pos
) ||
1195 iter_height
!= value_area_get_height (tmp
, ei
->pos
)) {
1196 free_values (args
, i
+ 1);
1197 return value_new_error_VALUE (ei
->pos
);
1200 if (iter_count
< 0) {
1201 g_warning ("Damn I thought this was impossible");
1204 iter_item
= g_alloca (sizeof (int) * argc
);
1205 iter_width
= value_area_get_width (tmp
, ei
->pos
);
1206 iter_height
= value_area_get_height (tmp
, ei
->pos
);
1208 iter_item
[iter_count
++] = i
;
1210 /* no need to check type, we would fail comparing a range against a "b, f, or s" */
1214 /* All of these argument types must be scalars */
1217 if (VALUE_IS_STRING (tmp
)) {
1219 gboolean b
= value_get_as_bool (tmp
, &err
);
1221 free_values (args
, i
+ 1);
1222 return value_new_error_VALUE (ei
->pos
);
1224 value_release (args
[i
]);
1225 tmp
= args
[i
] = value_new_bool (b
);
1230 if (VALUE_IS_STRING (tmp
)) {
1231 tmp
= format_match_number (value_peek_string (tmp
), NULL
,
1232 workbook_date_conv (ei
->pos
->sheet
->workbook
));
1234 free_values (args
, i
+ 1);
1235 return value_new_error_VALUE (ei
->pos
);
1237 value_release (args
[i
]);
1239 } else if (VALUE_IS_ERROR (tmp
)) {
1240 free_values (args
, i
);
1242 } else if (VALUE_IS_EMPTY (tmp
)) {
1243 value_release (args
[i
]);
1244 tmp
= args
[i
] = value_new_int (0);
1247 if (!VALUE_IS_NUMBER (tmp
))
1248 return value_new_error_VALUE (ei
->pos
);
1253 if (VALUE_IS_ERROR (tmp
)) {
1254 free_values (args
, i
);
1259 case 'E': /* nothing necessary */
1262 /* case '?': handled above */
1264 g_warning ("Unknown argument type '%c'", arg_type
);
1269 while (i
< fn_def
->fn
.args
.max_args
)
1272 if (iter_item
!= NULL
) {
1274 GnmValue
*res
= value_new_array_empty (iter_width
, iter_height
);
1275 GnmValue
const *elem
, *err
;
1276 GnmValue
**iter_vals
= g_alloca (sizeof (GnmValue
*) * iter_count
);
1277 GnmValue
**iter_args
= g_alloca (sizeof (GnmValue
*) * iter_count
);
1279 /* collect the args we will iterate on */
1280 for (i
= 0 ; i
< iter_count
; i
++)
1281 iter_vals
[i
] = args
[iter_item
[i
]];
1283 for (x
= iter_width
; x
-- > 0 ; )
1284 for (y
= iter_height
; y
-- > 0 ; ) {
1285 /* marshal the args */
1287 for (i
= 0 ; i
< iter_count
; i
++) {
1288 elem
= value_area_get_x_y (iter_vals
[i
], x
, y
, ei
->pos
);
1289 arg_type
= fn_def
->fn
.args
.arg_types
[iter_item
[i
]];
1290 if (arg_type
== 'b' || arg_type
== 'f') {
1291 if (VALUE_IS_EMPTY (elem
))
1293 else if (VALUE_IS_STRING (elem
)) {
1294 tmp
= format_match_number (value_peek_string (elem
), NULL
,
1295 workbook_date_conv (ei
->pos
->sheet
->workbook
));
1297 args
[iter_item
[i
]] = iter_args
[i
] = tmp
;
1301 } else if (VALUE_IS_ERROR (elem
)) {
1304 } else if (!VALUE_IS_NUMBER (elem
))
1306 } else if (arg_type
== 's') {
1307 if (VALUE_IS_EMPTY (elem
)) {
1308 args
[iter_item
[i
]] = iter_args
[i
] = value_new_string ("");
1310 } else if (VALUE_IS_ERROR (elem
)) {
1313 } else if (!VALUE_IS_STRING (elem
))
1315 } else if (elem
== NULL
) {
1316 args
[iter_item
[i
]] = iter_args
[i
] = value_new_empty ();
1319 args
[iter_item
[i
]] = iter_args
[i
] = value_dup (elem
);
1322 res
->v_array
.vals
[x
][y
] = (i
== iter_count
)
1323 ? fn_def
->fn
.args
.func (ei
, (GnmValue
const * const *)args
)
1324 : ((err
!= NULL
) ? value_dup (err
)
1325 : value_new_error_VALUE (ei
->pos
));
1326 free_values (iter_args
, i
);
1329 /* free the primaries, not the already freed iteration */
1330 for (i
= 0 ; i
< iter_count
; i
++)
1331 args
[iter_item
[i
]] = iter_vals
[i
];
1333 i
= fn_def
->fn
.args
.max_args
;
1335 tmp
= fn_def
->fn
.args
.func (ei
, (GnmValue
const * const *)args
);
1337 free_values (args
, i
);
1342 * Use this to invoke a register function: the only drawback is that
1343 * you have to compute/expand all of the values to use this
1346 function_call_with_values (GnmEvalPos
const *ep
, char const *fn_name
,
1347 int argc
, GnmValue
const * const *values
)
1351 g_return_val_if_fail (ep
!= NULL
, NULL
);
1352 g_return_val_if_fail (fn_name
!= NULL
, NULL
);
1353 g_return_val_if_fail (ep
->sheet
!= NULL
, NULL
);
1355 /* FIXME : support workbook local functions */
1356 fn_def
= gnm_func_lookup (fn_name
, NULL
);
1358 return value_new_error_NAME (ep
);
1359 return function_def_call_with_values (ep
, fn_def
, argc
, values
);
1363 function_def_call_with_values (GnmEvalPos
const *ep
, GnmFunc
const *fn_def
,
1364 int argc
, GnmValue
const * const *values
)
1372 ef
.func
= (GnmFunc
*)fn_def
;
1374 gnm_func_load_if_stub ((GnmFunc
*)fn_def
);
1376 if (fn_def
->fn_type
== GNM_FUNC_TYPE_NODES
) {
1378 * If function deals with ExprNodes, create some
1379 * temporary ExprNodes with constants.
1381 GnmExprConstant
*expr
= g_new (GnmExprConstant
, argc
);
1382 GnmExprConstPtr
*argv
= g_new (GnmExprConstPtr
, argc
);
1385 for (i
= 0; i
< argc
; i
++) {
1386 gnm_expr_constant_init (expr
+ i
, values
[i
]);
1387 argv
[i
] = (GnmExprConstPtr
)(expr
+ i
);
1389 retval
= fn_def
->fn
.nodes (&fs
, argc
, argv
);
1393 retval
= fn_def
->fn
.args
.func (&fs
, values
);
1398 /* ------------------------------------------------------------------------- */
1401 FunctionIterateCB callback
;
1404 gboolean ignore_subtotal
;
1405 } IterateCallbackClosure
;
1408 * cb_iterate_cellrange:
1410 * Helper routine used by the function_iterate_do_value routine.
1411 * Invoked by the sheet cell range iterator.
1414 cb_iterate_cellrange (GnmCellIter
const *iter
, gpointer user
)
1417 IterateCallbackClosure
*data
= user
;
1422 if (NULL
== (cell
= iter
->cell
)) {
1423 ep
.sheet
= iter
->pp
.sheet
;
1425 ep
.eval
.col
= iter
->pp
.eval
.col
;
1426 ep
.eval
.row
= iter
->pp
.eval
.row
;
1427 return (*data
->callback
)(&ep
, NULL
, data
->closure
);
1430 if (data
->ignore_subtotal
&& gnm_cell_has_expr (cell
) &&
1431 gnm_expr_top_contains_subtotal (cell
->base
.texpr
))
1434 gnm_cell_eval (cell
);
1435 eval_pos_init_cell (&ep
, cell
);
1437 /* If we encounter an error for the strict case, short-circuit here. */
1438 if (data
->strict
&& (NULL
!= (res
= gnm_cell_is_error (cell
))))
1439 return value_new_error_str (&ep
, res
->v_err
.mesg
);
1441 /* All other cases -- including error -- just call the handler. */
1442 return (*data
->callback
)(&ep
, cell
->value
, data
->closure
);
1446 * function_iterate_do_value:
1448 * Helper routine for function_iterate_argument_values.
1451 function_iterate_do_value (GnmEvalPos
const *ep
,
1452 FunctionIterateCB callback
,
1454 GnmValue
const *value
,
1456 CellIterFlags iter_flags
)
1458 GnmValue
*res
= NULL
;
1460 switch (value
->v_any
.type
){
1463 res
= value_dup (value
);
1472 res
= (*callback
)(ep
, value
, closure
);
1478 /* Note the order here. */
1479 for (y
= 0; y
< value
->v_array
.y
; y
++) {
1480 for (x
= 0; x
< value
->v_array
.x
; x
++) {
1481 res
= function_iterate_do_value (
1482 ep
, callback
, closure
,
1483 value
->v_array
.vals
[x
][y
],
1484 strict
, CELL_ITER_IGNORE_BLANK
);
1491 case VALUE_CELLRANGE
: {
1492 IterateCallbackClosure data
;
1494 data
.callback
= callback
;
1495 data
.closure
= closure
;
1496 data
.strict
= strict
;
1497 data
.ignore_subtotal
= (iter_flags
& CELL_ITER_IGNORE_SUBTOTAL
) != 0;
1499 res
= workbook_foreach_cell_in_range (ep
, value
, iter_flags
,
1500 cb_iterate_cellrange
,
1508 * function_iterate_argument_values:
1509 * @ep: The position in a workbook at which to evaluate
1510 * @callback: (scope call): The routine to be invoked for every value computed
1511 * @callback_closure: Closure for the callback.
1514 * @strict: If TRUE, the function is considered "strict". This means
1515 * that if an error value occurs as an argument, the iteration
1516 * will stop and that error will be returned. If FALSE, an
1517 * error will be passed on to the callback (as a GnmValue *
1518 * of type VALUE_ERROR).
1522 * NULL : if no errors were reported.
1523 * GnmValue * : if an error was found during strict evaluation
1524 * VALUE_TERMINATE : if the callback requested termination of the iteration.
1526 * This routine provides a simple way for internal functions with variable
1527 * number of arguments to be written: this would iterate over a list of
1528 * expressions (expr_node_list) and will invoke the callback for every
1529 * GnmValue found on the list (this means that ranges get properly expaned).
1532 function_iterate_argument_values (GnmEvalPos
const *ep
,
1533 FunctionIterateCB callback
,
1534 void *callback_closure
,
1536 GnmExprConstPtr
const *argv
,
1538 CellIterFlags iter_flags
)
1540 GnmValue
*result
= NULL
;
1543 for (a
= 0; result
== NULL
&& a
< argc
; a
++) {
1544 GnmExpr
const *expr
= argv
[a
];
1547 if (iter_flags
& CELL_ITER_IGNORE_SUBTOTAL
&&
1548 gnm_expr_contains_subtotal (expr
))
1551 /* need to drill down into names to handle things like
1552 * sum(name) with name := (A:A,B:B) */
1553 while (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_NAME
) {
1554 GnmExprTop
const *texpr
= expr
->name
.name
->texpr
;
1555 expr
= texpr
? texpr
->expr
: NULL
;
1558 return value_new_error_REF (ep
);
1565 /* Handle sets as a special case */
1566 if (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_SET
) {
1567 result
= function_iterate_argument_values
1568 (ep
, callback
, callback_closure
,
1569 expr
->set
.argc
, expr
->set
.argv
,
1570 strict
, iter_flags
);
1574 /* We need a cleaner model of what to do here.
1577 * will obviously return Range
1579 * SUM(INDIRECT(Range))
1580 * SUM(INDIRECT(Range):....)
1581 * will do implicit intersection on Range (in non-array mode),
1582 * but allow non-scalar results from indirect (no intersection)
1585 * will do implicit intersection in non-array mode */
1586 if (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_CONSTANT
)
1587 val
= value_dup (expr
->constant
.value
);
1588 else if (eval_pos_is_array_context (ep
) ||
1589 GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_FUNCALL
||
1590 GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_RANGE_CTOR
||
1591 GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_INTERSECT
)
1592 val
= gnm_expr_eval (expr
, ep
,
1593 GNM_EXPR_EVAL_PERMIT_EMPTY
| GNM_EXPR_EVAL_PERMIT_NON_SCALAR
);
1595 val
= gnm_expr_eval (expr
, ep
,
1596 GNM_EXPR_EVAL_PERMIT_EMPTY
);
1601 if (strict
&& VALUE_IS_ERROR (val
)) {
1602 /* Be careful not to make VALUE_TERMINATE into a real value */
1606 result
= function_iterate_do_value (ep
, callback
, callback_closure
,
1607 val
, strict
, iter_flags
);
1608 value_release (val
);