3 * func.c: Function management and utility routines.
6 * Miguel de Icaza (miguel@gnu.org)
7 * Michael Meeks (mmeeks@gnu.org)
8 * Morten Welinder (terra@gnome.org)
9 * Jody Goldberg (jody@gnome.org)
11 #include <gnumeric-config.h>
12 #include <glib/gi18n-lib.h>
13 #include <glib/gstdio.h>
17 #include <parse-util.h>
18 #include <dependent.h>
20 #include <expr-impl.h>
21 #include <expr-name.h>
23 #include <workbook-priv.h>
26 #include <number-match.h>
27 #include <func-builtin.h>
28 #include <command-context-stderr.h>
29 #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
;
47 * functions_init: (skip)
53 g_hash_table_new (go_ascii_strcase_hash
, go_ascii_strcase_equal
);
56 functions_by_localized_name
=
57 g_hash_table_new (go_ascii_strcase_hash
, go_ascii_strcase_equal
);
63 * functions_shutdown: (skip)
66 functions_shutdown (void)
68 while (unknown_cat
!= NULL
&& unknown_cat
->functions
!= NULL
) {
69 GnmFunc
*func
= unknown_cat
->functions
->data
;
70 if (func
->usage_count
> 0) {
71 g_warning ("Function %s still has %d users.\n",
72 gnm_func_get_name (func
, FALSE
),
74 func
->usage_count
= 0;
78 func_builtin_shutdown ();
80 g_hash_table_destroy (functions_by_name
);
81 functions_by_name
= NULL
;
83 g_hash_table_destroy (functions_by_localized_name
);
84 functions_by_localized_name
= NULL
;
90 * Return value: (element-type GnmFunc) (transfer container):
93 gnm_func_enumerate (void)
95 GPtrArray
*res
= g_ptr_array_new ();
99 g_hash_table_iter_init (&hiter
, functions_by_name
);
100 while (g_hash_table_iter_next (&hiter
, NULL
, &value
))
101 g_ptr_array_add (res
, value
);
107 gnm_func_load_if_stub (GnmFunc
*func
)
109 if (func
->fn_type
== GNM_FUNC_TYPE_STUB
)
110 gnm_func_load_stub (func
);
114 split_at_colon (char const *s
, char **rest
)
116 char *dup
= g_strdup (s
);
117 char *colon
= strchr (dup
, ':');
120 if (rest
) *rest
= colon
+ 1;
122 if (rest
) *rest
= NULL
;
127 /* ------------------------------------------------------------------------- */
130 gnm_func_group_free (GnmFuncGroup
*fn_group
)
132 g_return_if_fail (fn_group
!= NULL
);
133 g_return_if_fail (fn_group
->functions
== NULL
);
135 if (fn_group
->ref_count
-- > 1)
138 go_string_unref (fn_group
->internal_name
);
139 go_string_unref (fn_group
->display_name
);
143 static GnmFuncGroup
*
144 gnm_func_group_ref (GnmFuncGroup
*fn_group
)
146 fn_group
->ref_count
++;
151 gnm_func_group_get_type (void)
156 t
= g_boxed_type_register_static ("GnmFuncGroup",
157 (GBoxedCopyFunc
)gnm_func_group_ref
,
158 (GBoxedFreeFunc
)gnm_func_group_free
);
164 function_category_compare (gconstpointer a
, gconstpointer b
)
166 GnmFuncGroup
const *cat_a
= a
;
167 GnmFuncGroup
const *cat_b
= b
;
169 return go_string_cmp (cat_a
->display_name
, cat_b
->display_name
);
173 gnm_func_group_fetch (char const *name
, char const *translation
)
175 GnmFuncGroup
*cat
= NULL
;
178 g_return_val_if_fail (name
!= NULL
, NULL
);
180 for (l
= categories
; l
!= NULL
; l
= l
->next
) {
182 if (strcmp (cat
->internal_name
->str
, name
) == 0) {
188 cat
= g_new (GnmFuncGroup
, 1);
189 cat
->internal_name
= go_string_new (name
);
191 if (translation
!= NULL
) {
192 cat
->display_name
= go_string_new (translation
);
193 cat
->has_translation
= TRUE
;
195 cat
->display_name
= go_string_new (name
);
196 cat
->has_translation
= FALSE
;
198 cat
->functions
= NULL
;
199 categories
= g_list_insert_sorted (
200 categories
, cat
, &function_category_compare
);
201 } else if (translation
!= NULL
&& translation
!= name
&&
202 !cat
->has_translation
) {
203 go_string_unref (cat
->display_name
);
204 cat
->display_name
= go_string_new (translation
);
205 cat
->has_translation
= TRUE
;
206 categories
= g_list_remove_link (categories
, l
);
208 categories
= g_list_insert_sorted (
209 categories
, cat
, &function_category_compare
);
216 gnm_func_group_get_nth (int n
)
218 return g_list_nth_data (categories
, n
);
222 gnm_func_group_add_func (GnmFuncGroup
*fn_group
, GnmFunc
*fn_def
)
224 g_return_if_fail (fn_group
!= NULL
);
225 g_return_if_fail (fn_def
!= NULL
);
227 fn_group
->functions
= g_slist_prepend (fn_group
->functions
, fn_def
);
231 gnm_func_group_remove_func (GnmFuncGroup
*fn_group
, GnmFunc
*fn_def
)
233 g_return_if_fail (fn_group
!= NULL
);
234 g_return_if_fail (fn_def
!= NULL
);
236 fn_group
->functions
= g_slist_remove (fn_group
->functions
, fn_def
);
237 if (fn_group
->functions
== NULL
) {
238 categories
= g_list_remove (categories
, fn_group
);
239 if (unknown_cat
== fn_group
)
241 gnm_func_group_free (fn_group
);
245 /******************************************************************************/
248 extract_arg_types (GnmFunc
*def
)
252 gnm_func_count_args (def
,
253 &def
->fn
.args
.min_args
,
254 &def
->fn
.args
.max_args
);
255 def
->fn
.args
.arg_types
= g_malloc (def
->fn
.args
.max_args
+ 1);
256 for (i
= 0; i
< def
->fn
.args
.max_args
; i
++)
257 def
->fn
.args
.arg_types
[i
] = gnm_func_get_arg_type (def
, i
);
258 def
->fn
.args
.arg_types
[i
] = 0;
262 error_function_no_full_info (GnmFuncEvalInfo
*ei
,
264 GnmExprConstPtr
const *argv
)
266 return value_new_error (ei
->pos
, _("Function implementation not available."));
270 gnm_func_clear_arg_names (GnmFunc
*fd
)
272 if (fd
->arg_names_p
) {
273 g_ptr_array_foreach (fd
->arg_names_p
, (GFunc
) g_free
, NULL
);
274 g_ptr_array_free (fd
->arg_names_p
, TRUE
);
275 fd
->arg_names_p
= NULL
;
280 gnm_func_create_arg_names (GnmFunc
*fn_def
)
285 g_return_if_fail (fn_def
!= NULL
);
287 ptr
= g_ptr_array_new ();
289 fn_def
->help
&& fn_def
->help
[i
].type
!= GNM_FUNC_HELP_END
;
291 if (fn_def
->help
[i
].type
!= GNM_FUNC_HELP_ARG
)
296 (F2(fn_def
, fn_def
->help
[i
].text
), NULL
));
299 gnm_func_clear_arg_names (fn_def
);
300 fn_def
->arg_names_p
= ptr
;
305 gnm_func_load_stub (GnmFunc
*func
)
307 GnmFuncDescriptor desc
;
309 g_return_if_fail (func
->fn_type
== GNM_FUNC_TYPE_STUB
);
311 /* default the content to 0 in case we add new fields
312 * later and the services do not fill them in
314 memset (&desc
, 0, sizeof (GnmFuncDescriptor
));
316 if (func
->fn
.load_desc (func
, &desc
)) {
317 func
->help
= desc
.help
? desc
.help
: NULL
;
318 if (desc
.fn_args
!= NULL
) {
319 func
->fn_type
= GNM_FUNC_TYPE_ARGS
;
320 func
->fn
.args
.func
= desc
.fn_args
;
321 func
->fn
.args
.arg_spec
= desc
.arg_spec
;
322 extract_arg_types (func
);
323 } else if (desc
.fn_nodes
!= NULL
) {
324 func
->fn_type
= GNM_FUNC_TYPE_NODES
;
325 func
->fn
.nodes
= desc
.fn_nodes
;
327 g_warning ("Invalid function descriptor with no function");
329 func
->linker
= desc
.linker
;
330 func
->impl_status
= desc
.impl_status
;
331 func
->test_status
= desc
.test_status
;
332 func
->flags
= desc
.flags
;
333 gnm_func_create_arg_names (func
);
335 func
->fn_type
= GNM_FUNC_TYPE_NODES
;
336 func
->fn
.nodes
= &error_function_no_full_info
;
342 gnm_func_set_localized_name (GnmFunc
*fd
, const char *lname
)
344 gboolean in_hashes
= !(fd
->flags
& GNM_FUNC_IS_WORKBOOK_LOCAL
);
346 if (in_hashes
&& fd
->localized_name
)
347 g_hash_table_remove (functions_by_localized_name
, fd
->localized_name
);
348 g_free (fd
->localized_name
);
350 fd
->localized_name
= g_strdup (lname
);
351 if (in_hashes
&& lname
)
352 g_hash_table_insert (functions_by_localized_name
,
353 fd
->localized_name
, fd
);
357 gnm_func_free (GnmFunc
*func
)
361 g_return_if_fail (func
!= NULL
);
362 g_return_if_fail (func
->usage_count
== 0);
364 group
= func
->fn_group
;
366 gnm_func_group_remove_func (group
, func
);
368 gnm_func_set_localized_name (func
, NULL
);
370 if (!(func
->flags
& GNM_FUNC_IS_WORKBOOK_LOCAL
)) {
371 g_hash_table_remove (functions_by_name
, func
->name
);
374 if (func
->fn_type
== GNM_FUNC_TYPE_ARGS
)
375 g_free (func
->fn
.args
.arg_types
);
377 g_free ((char *)func
->name
);
379 go_string_unref (func
->tdomain
);
381 gnm_func_clear_arg_names (func
);
387 gnm_func_ref (GnmFunc
*func
)
389 g_return_val_if_fail (func
!= NULL
, NULL
);
392 if (func
->usage_count
== 1 && func
->usage_notify
!= NULL
)
393 func
->usage_notify (func
, 1);
398 gnm_func_unref (GnmFunc
*func
)
400 g_return_if_fail (func
!= NULL
);
401 g_return_if_fail (func
->usage_count
> 0);
404 if (func
->usage_count
== 0 && func
->usage_notify
!= NULL
)
405 func
->usage_notify (func
, 0);
409 gnm_func_get_type (void)
414 t
= g_boxed_type_register_static ("GnmFunc",
415 (GBoxedCopyFunc
)gnm_func_ref
,
416 (GBoxedFreeFunc
)gnm_func_unref
);
422 gnm_func_lookup (char const *name
, Workbook
*scope
)
424 GnmFunc
*fd
= g_hash_table_lookup (functions_by_name
, name
);
427 if (scope
== NULL
|| scope
->sheet_local_functions
== NULL
)
429 return g_hash_table_lookup (scope
->sheet_local_functions
, (gpointer
)name
);
433 gnm_func_lookup_localized (char const *name
, Workbook
*scope
)
436 GHashTableIter hiter
;
439 /* Must localize all function names. */
440 g_hash_table_iter_init (&hiter
, functions_by_name
);
441 while (g_hash_table_iter_next (&hiter
, NULL
, &value
)) {
443 (void)gnm_func_get_name (fd
, TRUE
);
446 fd
= g_hash_table_lookup (functions_by_localized_name
, name
);
449 if (scope
== NULL
|| scope
->sheet_local_functions
== NULL
)
451 return g_hash_table_lookup (scope
->sheet_local_functions
, (gpointer
)name
);
455 * gnm_func_lookup_prefix:
456 * @prefix: prefix to search for
458 * @trans: whether to search translated function names
460 * Returns: (element-type GnmFunc*) (transfer full):
463 gnm_func_lookup_prefix (char const *prefix
, Workbook
*scope
, gboolean trans
)
466 GHashTableIter hiter
;
470 * Always iterate over functions_by_name as the localized name
471 * might not be set yet.
473 g_hash_table_iter_init (&hiter
, functions_by_name
);
474 while (g_hash_table_iter_next (&hiter
, NULL
, &value
)) {
476 if (!(fd
->flags
& GNM_FUNC_IS_PLACEHOLDER
)) {
477 const char *name
= gnm_func_get_name (fd
, trans
);
478 if (g_str_has_prefix (name
, prefix
)) {
480 res
= g_slist_prepend (res
, fd
);
489 gnm_func_add (GnmFuncGroup
*fn_group
,
490 GnmFuncDescriptor
const *desc
,
493 static char const valid_tokens
[] = "fsbraAES?|";
497 g_return_val_if_fail (fn_group
!= NULL
, NULL
);
498 g_return_val_if_fail (desc
!= NULL
, NULL
);
500 func
= g_new (GnmFunc
, 1);
503 tdomain
= GETTEXT_PACKAGE
;
505 func
->name
= g_strdup (desc
->name
);
506 func
->help
= desc
->help
? desc
->help
: NULL
;
507 func
->tdomain
= go_string_new (tdomain
);
508 func
->linker
= desc
->linker
;
509 func
->usage_notify
= desc
->usage_notify
;
510 func
->flags
= desc
->flags
;
511 func
->impl_status
= desc
->impl_status
;
512 func
->test_status
= desc
->test_status
;
513 func
->localized_name
= NULL
;
514 func
->arg_names_p
= NULL
;
516 func
->user_data
= NULL
;
517 func
->usage_count
= 0;
519 if (desc
->fn_args
!= NULL
) {
520 /* Check those arguments */
521 for (ptr
= desc
->arg_spec
; *ptr
; ptr
++) {
522 g_return_val_if_fail (strchr (valid_tokens
, *ptr
), NULL
);
525 func
->fn_type
= GNM_FUNC_TYPE_ARGS
;
526 func
->fn
.args
.func
= desc
->fn_args
;
527 func
->fn
.args
.arg_spec
= desc
->arg_spec
;
528 extract_arg_types (func
);
529 } else if (desc
->fn_nodes
!= NULL
) {
531 if (desc
->arg_spec
&& *desc
->arg_spec
) {
532 g_warning ("Arg spec for node function -- why?");
535 func
->fn_type
= GNM_FUNC_TYPE_NODES
;
536 func
->fn
.nodes
= desc
->fn_nodes
;
538 g_warning ("Invalid function has neither args nor nodes handler");
543 func
->fn_group
= fn_group
;
544 if (fn_group
!= NULL
)
545 gnm_func_group_add_func (fn_group
, func
);
546 if (!(func
->flags
& GNM_FUNC_IS_WORKBOOK_LOCAL
))
547 g_hash_table_insert (functions_by_name
,
548 (gpointer
)(func
->name
), func
);
550 gnm_func_create_arg_names (func
);
555 /* Handle unknown functions on import without losing their names */
557 unknownFunctionHandler (GnmFuncEvalInfo
*ei
,
558 G_GNUC_UNUSED
int argc
,
559 G_GNUC_UNUSED GnmExprConstPtr
const *argv
)
561 return value_new_error_NAME (ei
->pos
);
565 * gnm_func_upgrade_placeholder:
569 * @load_desc: (scope async):
570 * @opt_usage_notify: (scope async):
573 gnm_func_upgrade_placeholder (GnmFunc
*fd
,
574 GnmFuncGroup
*fn_group
,
576 GnmFuncLoadDesc load_desc
,
577 GnmFuncUsageNotify opt_usage_notify
)
579 g_return_if_fail (fd
!= NULL
);
580 g_return_if_fail (fd
->flags
& GNM_FUNC_IS_PLACEHOLDER
);
581 g_return_if_fail (fn_group
!= NULL
);
584 tdomain
= GETTEXT_PACKAGE
;
586 /* Remove from unknown_cat */
587 gnm_func_group_remove_func (fd
->fn_group
, fd
);
589 fd
->fn_type
= GNM_FUNC_TYPE_STUB
;
590 fd
->fn
.load_desc
= load_desc
;
591 fd
->usage_notify
= opt_usage_notify
;
593 go_string_unref (fd
->tdomain
);
594 fd
->tdomain
= go_string_new (tdomain
);
596 /* Clear localized_name so we can deduce the proper name. */
597 gnm_func_set_localized_name (fd
, NULL
);
599 fd
->flags
&= ~GNM_FUNC_IS_PLACEHOLDER
;
601 fd
->fn_group
= fn_group
;
602 gnm_func_group_add_func (fn_group
, fd
);
606 invent_name (const char *pref
, GHashTable
*h
, const char *template)
608 static int count
= 0;
609 char *name
= g_utf8_strdown (pref
, -1);
611 while (g_hash_table_lookup (h
, name
)) {
614 name
= g_strdup_printf (template, count
);
621 gnm_func_add_placeholder_full (Workbook
*scope
,
622 char const *gname
, char const *lname
,
625 GnmFuncDescriptor desc
;
627 char const *unknown_cat_name
= N_("Unknown Function");
628 gboolean copy_gname
= TRUE
;
629 gboolean copy_lname
= TRUE
;
631 g_return_val_if_fail (gname
|| lname
, NULL
);
632 g_return_val_if_fail (gname
== NULL
|| gnm_func_lookup (gname
, scope
) == NULL
, NULL
);
633 g_return_val_if_fail (lname
== NULL
|| gnm_func_lookup_localized (lname
, scope
) == NULL
, NULL
);
636 unknown_cat
= gnm_func_group_fetch
637 (unknown_cat_name
, _(unknown_cat_name
));
641 * This is actually a bit of a problem if we don't end up
642 * with a copy of lname (because there already is a function
643 * with that name). We're likely to save a template name,
644 * but I don't see what else to do.
646 gname
= invent_name (lname
, functions_by_name
, "unknown%d");
650 /* xgettext: This represents a made-up translated function name. */
651 lname
= invent_name (gname
, functions_by_localized_name
, _("unknown%d"));
655 if (gnm_debug_flag ("func"))
656 g_printerr ("Adding placeholder for %s (aka %s)\n", gname
, lname
);
658 memset (&desc
, 0, sizeof (GnmFuncDescriptor
));
660 desc
.arg_spec
= NULL
;
663 desc
.fn_nodes
= &unknownFunctionHandler
;
665 desc
.usage_notify
= NULL
;
666 desc
.flags
= GNM_FUNC_IS_PLACEHOLDER
;
667 desc
.impl_status
= GNM_FUNC_IMPL_STATUS_EXISTS
;
668 desc
.test_status
= GNM_FUNC_TEST_STATUS_UNKNOWN
;
671 desc
.flags
|= GNM_FUNC_IS_WORKBOOK_LOCAL
;
674 /* WISHLIST : it would be nice to have a log if these. */
675 g_warning ("Unknown %s function : %s", type
, desc
.name
);
679 func
= gnm_func_add (unknown_cat
, &desc
, NULL
);
682 gnm_func_set_localized_name (func
, lname
);
684 g_free ((char *)lname
);
688 g_free ((char *)gname
);
691 if (scope
->sheet_local_functions
== NULL
)
692 scope
->sheet_local_functions
= g_hash_table_new_full (
693 g_str_hash
, g_str_equal
,
694 NULL
, (GDestroyNotify
) gnm_func_free
);
695 g_hash_table_insert (scope
->sheet_local_functions
,
696 (gpointer
)func
->name
, func
);
703 * When importing it is useful to keep track of unknown function names.
704 * We may be missing a plugin or something similar.
706 * TODO : Eventully we should be able to keep track of these
707 * and replace them with something else. Possibly even reordering the
711 gnm_func_add_placeholder (Workbook
*scope
,
712 char const *name
, char const *type
)
714 return gnm_func_add_placeholder_full (scope
, name
, NULL
, type
);
718 gnm_func_add_placeholder_localized (char const *gname
, char const *lname
)
720 return gnm_func_add_placeholder_full (NULL
, gname
, lname
, "?");
723 /* Utility routine to be used for import and analysis tools */
725 gnm_func_lookup_or_add_placeholder (char const *name
)
727 GnmFunc
* f
= gnm_func_lookup (name
, NULL
);
729 f
= gnm_func_add_placeholder (NULL
, name
, "");
734 * gnm_func_get_user_data:
737 * Returns: (transfer none):
740 gnm_func_get_user_data (GnmFunc
const *func
)
742 g_return_val_if_fail (func
!= NULL
, NULL
);
744 return func
->user_data
;
748 gnm_func_set_user_data (GnmFunc
*func
, gpointer user_data
)
750 g_return_if_fail (func
!= NULL
);
752 func
->user_data
= user_data
;
757 * @func: #GnmFunc to query
758 * @localized: if %TRUE, use localized name
760 * Returns: (transfer none): @func's name
763 gnm_func_get_name (GnmFunc
const *func
, gboolean localized
)
766 GnmFunc
*fd
= (GnmFunc
*)func
;
768 g_return_val_if_fail (func
!= NULL
, NULL
);
773 if (func
->localized_name
)
774 return func
->localized_name
;
777 * Deduce the translated names from the help texts. This
778 * code doesn't currently check for clashes in translated
782 gnm_func_load_if_stub (fd
);
785 (func
->localized_name
== NULL
&&
787 func
->help
[i
].type
!= GNM_FUNC_HELP_END
);
791 if (func
->help
[i
].type
!= GNM_FUNC_HELP_NAME
)
794 s
= func
->help
[i
].text
;
796 if (s
== sl
) /* String not actually translated. */
799 U
= split_at_colon (F2 (func
, s
), NULL
);
801 char *lname
= g_utf8_strdown (U
, -1);
802 gnm_func_set_localized_name (fd
, lname
);
808 if (!func
->localized_name
)
809 gnm_func_set_localized_name (fd
, fd
->name
);
811 return func
->localized_name
;
815 * gnm_func_get_description:
816 * @fn_def: the fn defintion
818 * Returns: (transfer none): the description of the function
821 gnm_func_get_description (GnmFunc
const *fn_def
)
824 g_return_val_if_fail (fn_def
!= NULL
, NULL
);
826 gnm_func_load_if_stub ((GnmFunc
*)fn_def
);
829 fn_def
->help
&& fn_def
->help
[i
].type
!= GNM_FUNC_HELP_END
;
833 if (fn_def
->help
[i
].type
!= GNM_FUNC_HELP_NAME
)
836 desc
= strchr (F2 (fn_def
, fn_def
->help
[i
].text
), ':');
837 return desc
? (desc
+ 1) : "";
843 * gnm_func_count_args:
844 * @fn_def: pointer to function definition
845 * @min: (out): location for mininum args
846 * @max: (out): location for mininum args
848 * This calculates the maximum and minimum number of args tha can be passed.
849 * For a vararg function, the maximum will be set to G_MAXINT.
852 gnm_func_count_args (GnmFunc
const *fn_def
, int *min
, int *max
)
858 g_return_if_fail (min
!= NULL
);
859 g_return_if_fail (max
!= NULL
);
860 g_return_if_fail (fn_def
!= NULL
);
862 gnm_func_load_if_stub ((GnmFunc
*)fn_def
);
865 * FIXME: clearly for 'nodes' functions many of
866 * the type fields will need to be filled.
868 if (fn_def
->fn_type
== GNM_FUNC_TYPE_NODES
) {
870 if (g_ascii_strcasecmp ("INDEX",fn_def
->name
) == 0)
877 ptr
= fn_def
->fn
.args
.arg_spec
;
878 for (i
= vararg
= 0; ptr
&& *ptr
; ptr
++) {
891 * gnm_func_get_arg_type:
892 * @fn_def: the fn defintion
893 * @arg_idx: zero based argument offset
895 * Returns: the type of the argument
898 gnm_func_get_arg_type (GnmFunc
const *fn_def
, int arg_idx
)
902 g_return_val_if_fail (arg_idx
>= 0, '?');
903 g_return_val_if_fail (fn_def
!= NULL
, '?');
905 gnm_func_load_if_stub ((GnmFunc
*)fn_def
);
907 switch (fn_def
->fn_type
) {
908 case GNM_FUNC_TYPE_ARGS
:
909 for (ptr
= fn_def
->fn
.args
.arg_spec
; ptr
&& *ptr
; ptr
++) {
917 case GNM_FUNC_TYPE_NODES
:
918 return '?'; /* Close enough for now. */
920 case GNM_FUNC_TYPE_STUB
:
921 #ifndef DEBUG_SWITCH_ENUM
924 g_assert_not_reached ();
930 * gnm_func_get_arg_type_string:
931 * @fn_def: the fn defintion
932 * @arg_idx: zero based argument offset
934 * Return value: (transfer none): the type of the argument as a string
937 gnm_func_get_arg_type_string (GnmFunc
const *fn_def
,
940 switch (gnm_func_get_arg_type (fn_def
, arg_idx
)) {
948 return _("Cell Range");
952 return _("Scalar, Blank, or Error");
956 /* Missing values will be NULL. */
960 g_warning ("Unknown arg type");
966 * gnm_func_get_arg_name:
967 * @fn_def: the fn defintion
968 * @arg_idx: zero based argument offset
970 * Returns: (transfer full): the name of the argument
973 gnm_func_get_arg_name (GnmFunc
const *fn_def
, guint arg_idx
)
975 g_return_val_if_fail (fn_def
!= NULL
, NULL
);
977 gnm_func_load_if_stub ((GnmFunc
*)fn_def
);
979 if ((fn_def
->arg_names_p
!= NULL
)
980 && (arg_idx
< fn_def
->arg_names_p
->len
))
981 return g_strdup (g_ptr_array_index (fn_def
->arg_names_p
,
987 * gnm_func_get_arg_description:
988 * @fn_def: the fn defintion
989 * @arg_idx: zero based argument offset
991 * Returns: (transfer none): the description of the argument
994 gnm_func_get_arg_description (GnmFunc
const *fn_def
, guint arg_idx
)
997 g_return_val_if_fail (fn_def
!= NULL
, NULL
);
999 gnm_func_load_if_stub ((GnmFunc
*)fn_def
);
1002 fn_def
->help
&& fn_def
->help
[i
].type
!= GNM_FUNC_HELP_END
;
1006 if (fn_def
->help
[i
].type
!= GNM_FUNC_HELP_ARG
)
1011 desc
= strchr (F2 (fn_def
, fn_def
->help
[i
].text
), ':');
1016 while (g_unichar_isspace (g_utf8_get_char (desc
)))
1017 desc
= g_utf8_next_char (desc
);
1025 * gnm_func_convert_markup_to_pango:
1026 * @desc: the fn or arg description string
1027 * @target: target widget for the markup.
1029 * Return value: the escaped string with @{} markup converted to
1033 gnm_func_convert_markup_to_pango (char const *desc
, GtkWidget
*target
)
1039 char *link_color_text
, *span_text
;
1040 size_t span_text_len
;
1042 gnm_get_link_color (target
, &link_color
);
1043 pg
.red
= 65535 * link_color
.red
;
1044 pg
.green
= 65535 * link_color
.green
;
1045 pg
.blue
= 65535 * link_color
.blue
;
1046 link_color_text
= pango_color_to_string (&pg
);
1047 span_text
= g_strdup_printf ("<span foreground=\"%s\">",
1049 span_text_len
= strlen (span_text
);
1050 g_free (link_color_text
);
1052 markup
= g_markup_escape_text (desc
, -1);
1053 str
= g_string_new (markup
);
1056 while ((at
= strstr (str
->str
, "@{"))) {
1057 gint len
= at
- str
->str
;
1058 go_string_replace (str
, len
, 2, span_text
, -1);
1060 (str
->str
+ len
+ span_text_len
, "}"))) {
1061 len
= at
- str
->str
;
1062 go_string_replace (str
, len
, 1, "</span>", -1);
1064 g_string_append (str
, "</span>");
1068 return g_string_free (str
, FALSE
);
1072 /* ------------------------------------------------------------------------- */
1075 free_values (GnmValue
**values
, int top
)
1079 for (i
= 0; i
< top
; i
++)
1081 value_release (values
[i
]);
1084 /* ------------------------------------------------------------------------- */
1087 * function_call_with_exprs:
1088 * @ei: EvalInfo containing valid fn_def!
1090 * Do the guts of calling a function.
1092 * Returns the result.
1095 function_call_with_exprs (GnmFuncEvalInfo
*ei
)
1097 GnmFunc
const *fn_def
;
1098 int i
, iter_count
, iter_width
= 0, iter_height
= 0;
1100 GnmValue
**args
, *tmp
= NULL
;
1101 int *iter_item
= NULL
;
1103 GnmExprConstPtr
*argv
;
1104 GnmExprEvalFlags flags
, pass_flags
;
1106 g_return_val_if_fail (ei
!= NULL
, NULL
);
1107 g_return_val_if_fail (ei
->func_call
!= NULL
, NULL
);
1111 argc
= ei
->func_call
->argc
;
1112 argv
= ei
->func_call
->argv
;
1113 fn_def
= ei
->func_call
->func
;
1115 gnm_func_load_if_stub ((GnmFunc
*)fn_def
);
1117 /* Functions that deal with ExprNodes */
1118 if (fn_def
->fn_type
== GNM_FUNC_TYPE_NODES
)
1119 return fn_def
->fn
.nodes (ei
, argc
, argv
);
1121 /* Functions that take pre-computed Values */
1122 if (argc
> fn_def
->fn
.args
.max_args
||
1123 argc
< fn_def
->fn
.args
.min_args
)
1124 return value_new_error_NA (ei
->pos
);
1126 args
= g_alloca (sizeof (GnmValue
*) * fn_def
->fn
.args
.max_args
);
1127 iter_count
= (eval_pos_is_array_context (ei
->pos
) &&
1128 (flags
& GNM_EXPR_EVAL_PERMIT_NON_SCALAR
))
1131 /* Optimization for IF when implicit iteration is not used. */
1132 if (ei
->func_call
->func
->fn
.args
.func
== gnumeric_if
&&
1134 return gnumeric_if2 (ei
, argc
, argv
, flags
);
1136 pass_flags
= (flags
&
1137 (GNM_EXPR_EVAL_ARRAY_CONTEXT
));
1139 for (i
= 0; i
< argc
; i
++) {
1140 char arg_type
= fn_def
->fn
.args
.arg_types
[i
];
1141 /* expr is always non-null, missing args are encoded as
1143 GnmExpr
const *expr
= argv
[i
];
1145 if (arg_type
== 'A' || arg_type
== 'r') {
1146 tmp
= args
[i
] = gnm_expr_eval
1149 GNM_EXPR_EVAL_PERMIT_NON_SCALAR
|
1150 GNM_EXPR_EVAL_WANT_REF
);
1151 if (VALUE_IS_ERROR (tmp
)) {
1152 free_values (args
, i
);
1156 if (VALUE_IS_CELLRANGE (tmp
)) {
1157 gnm_cellref_make_abs (&tmp
->v_range
.cell
.a
,
1158 &tmp
->v_range
.cell
.a
,
1160 gnm_cellref_make_abs (&tmp
->v_range
.cell
.b
,
1161 &tmp
->v_range
.cell
.b
,
1163 /* Array args accept scalars */
1164 } else if (arg_type
!= 'A' && !VALUE_IS_ARRAY (tmp
)) {
1165 free_values (args
, i
+ 1);
1166 return value_new_error_VALUE (ei
->pos
);
1171 /* force scalars whenever we are certain */
1172 tmp
= args
[i
] = gnm_expr_eval
1175 GNM_EXPR_EVAL_PERMIT_EMPTY
|
1176 (iter_count
>= 0 || arg_type
== '?'
1177 ? GNM_EXPR_EVAL_PERMIT_NON_SCALAR
1180 if (arg_type
== '?') /* '?' arguments are unrestriced */
1183 /* optional arguments can be blank */
1184 if (i
>= fn_def
->fn
.args
.min_args
&& VALUE_IS_EMPTY (tmp
)) {
1185 if (arg_type
== 'E' && !gnm_expr_is_empty (expr
)) {
1186 /* An actual argument produced empty. Make
1187 sure function sees that. */
1188 args
[i
] = value_new_empty ();
1195 tmp
= args
[i
] = value_new_empty ();
1197 /* Handle implicit intersection or iteration depending on flags */
1198 if (VALUE_IS_CELLRANGE (tmp
) || VALUE_IS_ARRAY (tmp
)) {
1199 if (iter_count
> 0) {
1200 if (iter_width
!= value_area_get_width (tmp
, ei
->pos
) ||
1201 iter_height
!= value_area_get_height (tmp
, ei
->pos
)) {
1202 free_values (args
, i
+ 1);
1203 return value_new_error_VALUE (ei
->pos
);
1206 if (iter_count
< 0) {
1207 g_warning ("Damn I thought this was impossible");
1210 iter_item
= g_alloca (sizeof (int) * argc
);
1211 iter_width
= value_area_get_width (tmp
, ei
->pos
);
1212 iter_height
= value_area_get_height (tmp
, ei
->pos
);
1214 iter_item
[iter_count
++] = i
;
1216 /* no need to check type, we would fail comparing a range against a "b, f, or s" */
1220 /* All of these argument types must be scalars */
1223 if (VALUE_IS_STRING (tmp
)) {
1225 gboolean b
= value_get_as_bool (tmp
, &err
);
1227 free_values (args
, i
+ 1);
1228 return value_new_error_VALUE (ei
->pos
);
1230 value_release (args
[i
]);
1231 tmp
= args
[i
] = value_new_bool (b
);
1236 if (VALUE_IS_STRING (tmp
)) {
1237 tmp
= format_match_number (value_peek_string (tmp
), NULL
,
1238 sheet_date_conv (ei
->pos
->sheet
));
1240 free_values (args
, i
+ 1);
1241 return value_new_error_VALUE (ei
->pos
);
1243 value_release (args
[i
]);
1245 } else if (VALUE_IS_ERROR (tmp
)) {
1246 free_values (args
, i
);
1248 } else if (VALUE_IS_EMPTY (tmp
)) {
1249 value_release (args
[i
]);
1250 tmp
= args
[i
] = value_new_int (0);
1253 if (!VALUE_IS_NUMBER (tmp
))
1254 return value_new_error_VALUE (ei
->pos
);
1259 if (VALUE_IS_ERROR (tmp
)) {
1260 free_values (args
, i
);
1265 case 'E': /* nothing necessary */
1268 /* case '?': handled above */
1270 g_warning ("Unknown argument type '%c'", arg_type
);
1275 while (i
< fn_def
->fn
.args
.max_args
)
1278 if (iter_item
!= NULL
) {
1280 GnmValue
*res
= value_new_array_empty (iter_width
, iter_height
);
1281 GnmValue
const *elem
, *err
;
1282 GnmValue
**iter_vals
= g_alloca (sizeof (GnmValue
*) * iter_count
);
1283 GnmValue
**iter_args
= g_alloca (sizeof (GnmValue
*) * iter_count
);
1285 /* collect the args we will iterate on */
1286 for (i
= 0 ; i
< iter_count
; i
++)
1287 iter_vals
[i
] = args
[iter_item
[i
]];
1289 for (x
= iter_width
; x
-- > 0 ; )
1290 for (y
= iter_height
; y
-- > 0 ; ) {
1291 /* marshal the args */
1293 for (i
= 0 ; i
< iter_count
; i
++) {
1294 elem
= value_area_get_x_y (iter_vals
[i
], x
, y
, ei
->pos
);
1295 arg_type
= fn_def
->fn
.args
.arg_types
[iter_item
[i
]];
1296 if (arg_type
== 'b' || arg_type
== 'f') {
1297 if (VALUE_IS_EMPTY (elem
))
1299 else if (VALUE_IS_STRING (elem
)) {
1300 tmp
= format_match_number (value_peek_string (elem
), NULL
,
1301 sheet_date_conv (ei
->pos
->sheet
));
1303 args
[iter_item
[i
]] = iter_args
[i
] = tmp
;
1307 } else if (VALUE_IS_ERROR (elem
)) {
1310 } else if (!VALUE_IS_NUMBER (elem
))
1312 } else if (arg_type
== 's') {
1313 if (VALUE_IS_EMPTY (elem
)) {
1314 args
[iter_item
[i
]] = iter_args
[i
] = value_new_string ("");
1316 } else if (VALUE_IS_ERROR (elem
)) {
1319 } else if (!VALUE_IS_STRING (elem
))
1321 } else if (elem
== NULL
) {
1322 args
[iter_item
[i
]] = iter_args
[i
] = value_new_empty ();
1325 args
[iter_item
[i
]] = iter_args
[i
] = value_dup (elem
);
1328 res
->v_array
.vals
[x
][y
] = (i
== iter_count
)
1329 ? fn_def
->fn
.args
.func (ei
, (GnmValue
const * const *)args
)
1330 : ((err
!= NULL
) ? value_dup (err
)
1331 : value_new_error_VALUE (ei
->pos
));
1332 free_values (iter_args
, i
);
1335 /* free the primaries, not the already freed iteration */
1336 for (i
= 0 ; i
< iter_count
; i
++)
1337 args
[iter_item
[i
]] = iter_vals
[i
];
1339 i
= fn_def
->fn
.args
.max_args
;
1341 tmp
= fn_def
->fn
.args
.func (ei
, (GnmValue
const * const *)args
);
1343 free_values (args
, i
);
1348 * Use this to invoke a register function: the only drawback is that
1349 * you have to compute/expand all of the values to use this
1352 function_call_with_values (GnmEvalPos
const *ep
, char const *fn_name
,
1353 int argc
, GnmValue
const * const *values
)
1357 g_return_val_if_fail (ep
!= NULL
, NULL
);
1358 g_return_val_if_fail (fn_name
!= NULL
, NULL
);
1359 g_return_val_if_fail (ep
->sheet
!= NULL
, NULL
);
1361 /* FIXME : support workbook local functions */
1362 fn_def
= gnm_func_lookup (fn_name
, NULL
);
1364 return value_new_error_NAME (ep
);
1365 return function_def_call_with_values (ep
, fn_def
, argc
, values
);
1369 function_def_call_with_values (GnmEvalPos
const *ep
, GnmFunc
const *fn_def
,
1370 int argc
, GnmValue
const * const *values
)
1378 ef
.func
= (GnmFunc
*)fn_def
;
1380 gnm_func_load_if_stub ((GnmFunc
*)fn_def
);
1382 if (fn_def
->fn_type
== GNM_FUNC_TYPE_NODES
) {
1384 * If function deals with ExprNodes, create some
1385 * temporary ExprNodes with constants.
1387 GnmExprConstant
*expr
= g_new (GnmExprConstant
, argc
);
1388 GnmExprConstPtr
*argv
= g_new (GnmExprConstPtr
, argc
);
1391 for (i
= 0; i
< argc
; i
++) {
1392 gnm_expr_constant_init (expr
+ i
, values
[i
]);
1393 argv
[i
] = (GnmExprConstPtr
)(expr
+ i
);
1395 retval
= fn_def
->fn
.nodes (&fs
, argc
, argv
);
1399 retval
= fn_def
->fn
.args
.func (&fs
, values
);
1404 /* ------------------------------------------------------------------------- */
1407 FunctionIterateCB callback
;
1410 gboolean ignore_subtotal
;
1411 } IterateCallbackClosure
;
1414 * cb_iterate_cellrange:
1416 * Helper routine used by the function_iterate_do_value routine.
1417 * Invoked by the sheet cell range iterator.
1420 cb_iterate_cellrange (GnmCellIter
const *iter
, gpointer user
)
1423 IterateCallbackClosure
*data
= user
;
1428 if (NULL
== (cell
= iter
->cell
)) {
1429 ep
.sheet
= iter
->pp
.sheet
;
1431 ep
.eval
.col
= iter
->pp
.eval
.col
;
1432 ep
.eval
.row
= iter
->pp
.eval
.row
;
1433 return (*data
->callback
)(&ep
, NULL
, data
->closure
);
1436 if (data
->ignore_subtotal
&& gnm_cell_has_expr (cell
) &&
1437 gnm_expr_top_contains_subtotal (cell
->base
.texpr
))
1440 gnm_cell_eval (cell
);
1441 eval_pos_init_cell (&ep
, cell
);
1443 /* If we encounter an error for the strict case, short-circuit here. */
1444 if (data
->strict
&& (NULL
!= (res
= gnm_cell_is_error (cell
))))
1445 return value_new_error_str (&ep
, res
->v_err
.mesg
);
1447 /* All other cases -- including error -- just call the handler. */
1448 return (*data
->callback
)(&ep
, cell
->value
, data
->closure
);
1452 * function_iterate_do_value:
1454 * Helper routine for function_iterate_argument_values.
1457 function_iterate_do_value (GnmEvalPos
const *ep
,
1458 FunctionIterateCB callback
,
1460 GnmValue
const *value
,
1462 CellIterFlags iter_flags
)
1464 GnmValue
*res
= NULL
;
1466 switch (value
->v_any
.type
){
1469 res
= value_dup (value
);
1478 res
= (*callback
)(ep
, value
, closure
);
1484 /* Note the order here. */
1485 for (y
= 0; y
< value
->v_array
.y
; y
++) {
1486 for (x
= 0; x
< value
->v_array
.x
; x
++) {
1487 res
= function_iterate_do_value (
1488 ep
, callback
, closure
,
1489 value
->v_array
.vals
[x
][y
],
1490 strict
, CELL_ITER_IGNORE_BLANK
);
1497 case VALUE_CELLRANGE
: {
1498 IterateCallbackClosure data
;
1500 data
.callback
= callback
;
1501 data
.closure
= closure
;
1502 data
.strict
= strict
;
1503 data
.ignore_subtotal
= (iter_flags
& CELL_ITER_IGNORE_SUBTOTAL
) != 0;
1505 res
= workbook_foreach_cell_in_range (ep
, value
, iter_flags
,
1506 cb_iterate_cellrange
,
1514 * function_iterate_argument_values:
1515 * @ep: The position in a workbook at which to evaluate
1516 * @callback: (scope call): The routine to be invoked for every value computed
1517 * @callback_closure: Closure for the callback.
1520 * @strict: If TRUE, the function is considered "strict". This means
1521 * that if an error value occurs as an argument, the iteration
1522 * will stop and that error will be returned. If FALSE, an
1523 * error will be passed on to the callback (as a GnmValue *
1524 * of type VALUE_ERROR).
1528 * NULL : if no errors were reported.
1529 * GnmValue * : if an error was found during strict evaluation
1530 * VALUE_TERMINATE : if the callback requested termination of the iteration.
1532 * This routine provides a simple way for internal functions with variable
1533 * number of arguments to be written: this would iterate over a list of
1534 * expressions (expr_node_list) and will invoke the callback for every
1535 * GnmValue found on the list (this means that ranges get properly expaned).
1538 function_iterate_argument_values (GnmEvalPos
const *ep
,
1539 FunctionIterateCB callback
,
1540 void *callback_closure
,
1542 GnmExprConstPtr
const *argv
,
1544 CellIterFlags iter_flags
)
1546 GnmValue
*result
= NULL
;
1549 for (a
= 0; result
== NULL
&& a
< argc
; a
++) {
1550 GnmExpr
const *expr
= argv
[a
];
1553 if (iter_flags
& CELL_ITER_IGNORE_SUBTOTAL
&&
1554 gnm_expr_contains_subtotal (expr
))
1557 /* need to drill down into names to handle things like
1558 * sum(name) with name := (A:A,B:B) */
1559 while (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_NAME
) {
1560 GnmExprTop
const *texpr
= expr
->name
.name
->texpr
;
1561 expr
= texpr
? texpr
->expr
: NULL
;
1564 return value_new_error_REF (ep
);
1571 /* Handle sets as a special case */
1572 if (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_SET
) {
1573 result
= function_iterate_argument_values
1574 (ep
, callback
, callback_closure
,
1575 expr
->set
.argc
, expr
->set
.argv
,
1576 strict
, iter_flags
);
1580 /* We need a cleaner model of what to do here.
1583 * will obviously return Range
1585 * SUM(INDIRECT(Range))
1586 * SUM(INDIRECT(Range):....)
1587 * will do implicit intersection on Range (in non-array mode),
1588 * but allow non-scalar results from indirect (no intersection)
1591 * will do implicit intersection in non-array mode */
1592 if (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_CONSTANT
)
1593 val
= value_dup (expr
->constant
.value
);
1594 else if (eval_pos_is_array_context (ep
) ||
1595 GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_FUNCALL
||
1596 GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_RANGE_CTOR
||
1597 GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_INTERSECT
)
1598 val
= gnm_expr_eval (expr
, ep
,
1599 GNM_EXPR_EVAL_PERMIT_EMPTY
| GNM_EXPR_EVAL_PERMIT_NON_SCALAR
);
1601 val
= gnm_expr_eval (expr
, ep
, GNM_EXPR_EVAL_PERMIT_EMPTY
);
1606 if (strict
&& VALUE_IS_ERROR (val
)) {
1607 /* Be careful not to make VALUE_TERMINATE into a real value */
1611 result
= function_iterate_do_value (ep
, callback
, callback_closure
,
1612 val
, strict
, iter_flags
);
1613 value_release (val
);
1620 gnm_eval_info_get_func (GnmFuncEvalInfo
const *ei
)
1622 return ei
->func_call
->func
;
1626 gnm_eval_info_get_arg_count (GnmFuncEvalInfo
const *ei
)
1628 return ei
->func_call
->argc
;