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
;
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
);
380 go_string_unref (func
->tdomain
);
382 gnm_func_clear_arg_names (func
);
388 gnm_func_ref (GnmFunc
*func
)
390 g_return_val_if_fail (func
!= NULL
, NULL
);
393 if (func
->usage_count
== 1 && func
->usage_notify
!= NULL
)
394 func
->usage_notify (func
, 1);
399 gnm_func_unref (GnmFunc
*func
)
401 g_return_if_fail (func
!= NULL
);
402 g_return_if_fail (func
->usage_count
> 0);
405 if (func
->usage_count
== 0 && func
->usage_notify
!= NULL
)
406 func
->usage_notify (func
, 0);
410 gnm_func_get_type (void)
415 t
= g_boxed_type_register_static ("GnmFunc",
416 (GBoxedCopyFunc
)gnm_func_ref
,
417 (GBoxedFreeFunc
)gnm_func_unref
);
423 gnm_func_lookup (char const *name
, Workbook
*scope
)
425 GnmFunc
*fd
= g_hash_table_lookup (functions_by_name
, name
);
428 if (scope
== NULL
|| scope
->sheet_local_functions
== NULL
)
430 return g_hash_table_lookup (scope
->sheet_local_functions
, (gpointer
)name
);
434 gnm_func_lookup_localized (char const *name
, Workbook
*scope
)
437 GHashTableIter hiter
;
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
)) {
444 (void)gnm_func_get_name (fd
, TRUE
);
447 fd
= g_hash_table_lookup (functions_by_localized_name
, name
);
450 if (scope
== NULL
|| scope
->sheet_local_functions
== NULL
)
452 return g_hash_table_lookup (scope
->sheet_local_functions
, (gpointer
)name
);
456 * gnm_func_lookup_prefix:
457 * @prefix: prefix to search for
459 * @trans: whether to search translated function names
461 * Returns: (element-type GnmFunc*) (transfer full):
464 gnm_func_lookup_prefix (char const *prefix
, Workbook
*scope
, gboolean trans
)
467 GHashTableIter hiter
;
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
)) {
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
)) {
481 res
= g_slist_prepend (res
, fd
);
490 gnm_func_add (GnmFuncGroup
*fn_group
,
491 GnmFuncDescriptor
const *desc
,
494 static char const valid_tokens
[] = "fsbraAES?|";
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);
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
;
539 g_warning ("Invalid function has neither args nor nodes handler");
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
);
556 /* Handle unknown functions on import without losing their names */
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:
570 * @load_desc: (scope async):
571 * @opt_usage_notify: (scope async):
574 gnm_func_upgrade_placeholder (GnmFunc
*fd
,
575 GnmFuncGroup
*fn_group
,
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
);
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
);
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
)) {
615 name
= g_strdup_printf (template, count
);
622 gnm_func_add_placeholder_full (Workbook
*scope
,
623 char const *gname
, char const *lname
,
626 GnmFuncDescriptor desc
;
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
);
637 unknown_cat
= gnm_func_group_fetch
638 (unknown_cat_name
, _(unknown_cat_name
));
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");
651 /* xgettext: This represents a made-up translated function name. */
652 lname
= invent_name (gname
, functions_by_localized_name
, _("unknown%d"));
656 if (gnm_debug_flag ("func"))
657 g_printerr ("Adding placeholder for %s (aka %s)\n", gname
, lname
);
659 memset (&desc
, 0, sizeof (GnmFuncDescriptor
));
661 desc
.arg_spec
= NULL
;
664 desc
.fn_nodes
= &unknownFunctionHandler
;
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
;
672 desc
.flags
|= GNM_FUNC_IS_WORKBOOK_LOCAL
;
675 /* WISHLIST : it would be nice to have a log if these. */
676 g_warning ("Unknown %s function : %s", type
, desc
.name
);
680 func
= gnm_func_add (unknown_cat
, &desc
, NULL
);
683 gnm_func_set_localized_name (func
, lname
);
685 g_free ((char *)lname
);
689 g_free ((char *)gname
);
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
);
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
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
);
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 */
726 gnm_func_lookup_or_add_placeholder (char const *name
)
728 GnmFunc
* f
= gnm_func_lookup (name
, NULL
);
730 f
= gnm_func_add_placeholder (NULL
, name
, "");
735 * gnm_func_get_user_data:
738 * Returns: (transfer none):
741 gnm_func_get_user_data (GnmFunc
const *func
)
743 g_return_val_if_fail (func
!= NULL
, NULL
);
745 return func
->user_data
;
749 gnm_func_set_user_data (GnmFunc
*func
, gpointer user_data
)
751 g_return_if_fail (func
!= NULL
);
753 func
->user_data
= user_data
;
758 * @func: #GnmFunc to query
759 * @localized: if %TRUE, use localized name
761 * Returns: (transfer none): @func's name
764 gnm_func_get_name (GnmFunc
const *func
, gboolean localized
)
767 GnmFunc
*fd
= (GnmFunc
*)func
;
769 g_return_val_if_fail (func
!= NULL
, NULL
);
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
783 gnm_func_load_if_stub (fd
);
786 (func
->localized_name
== NULL
&&
788 func
->help
[i
].type
!= GNM_FUNC_HELP_END
);
792 if (func
->help
[i
].type
!= GNM_FUNC_HELP_NAME
)
795 s
= func
->help
[i
].text
;
797 if (s
== sl
) /* String not actually translated. */
800 U
= split_at_colon (F2 (func
, s
), NULL
);
802 char *lname
= g_utf8_strdown (U
, -1);
803 gnm_func_set_localized_name (fd
, lname
);
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
822 gnm_func_get_description (GnmFunc
const *fn_def
)
825 g_return_val_if_fail (fn_def
!= NULL
, NULL
);
827 gnm_func_load_if_stub ((GnmFunc
*)fn_def
);
830 fn_def
->help
&& fn_def
->help
[i
].type
!= GNM_FUNC_HELP_END
;
834 if (fn_def
->help
[i
].type
!= GNM_FUNC_HELP_NAME
)
837 desc
= strchr (F2 (fn_def
, fn_def
->help
[i
].text
), ':');
838 return desc
? (desc
+ 1) : "";
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.
853 gnm_func_count_args (GnmFunc
const *fn_def
, int *min
, int *max
)
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
) {
871 if (g_ascii_strcasecmp ("INDEX",fn_def
->name
) == 0)
878 ptr
= fn_def
->fn
.args
.arg_spec
;
879 for (i
= vararg
= 0; ptr
&& *ptr
; ptr
++) {
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
899 gnm_func_get_arg_type (GnmFunc
const *fn_def
, int arg_idx
)
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
++) {
918 case GNM_FUNC_TYPE_NODES
:
919 return '?'; /* Close enough for now. */
921 case GNM_FUNC_TYPE_STUB
:
922 #ifndef DEBUG_SWITCH_ENUM
925 g_assert_not_reached ();
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
938 gnm_func_get_arg_type_string (GnmFunc
const *fn_def
,
941 switch (gnm_func_get_arg_type (fn_def
, arg_idx
)) {
949 return _("Cell Range");
953 return _("Scalar, Blank, or Error");
957 /* Missing values will be NULL. */
961 g_warning ("Unknown arg type");
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
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
,
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
995 gnm_func_get_arg_description (GnmFunc
const *fn_def
, guint arg_idx
)
998 g_return_val_if_fail (fn_def
!= NULL
, NULL
);
1000 gnm_func_load_if_stub ((GnmFunc
*)fn_def
);
1003 fn_def
->help
&& fn_def
->help
[i
].type
!= GNM_FUNC_HELP_END
;
1007 if (fn_def
->help
[i
].type
!= GNM_FUNC_HELP_ARG
)
1012 desc
= strchr (F2 (fn_def
, fn_def
->help
[i
].text
), ':');
1017 while (g_unichar_isspace (g_utf8_get_char (desc
)))
1018 desc
= g_utf8_next_char (desc
);
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
1034 gnm_func_convert_markup_to_pango (char const *desc
, GtkWidget
*target
)
1038 GdkColor
*link_color
= NULL
;
1039 char *link_color_text
, *span_text
;
1040 size_t span_text_len
;
1042 gtk_widget_style_get (target
, "link-color", &link_color
, NULL
);
1044 link_color_text
= gdk_color_to_string (link_color
);
1045 gdk_color_free (link_color
);
1047 link_color_text
= g_strdup ("blue");
1048 span_text
= g_strdup_printf ("<span foreground=\"%s\">",
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
);
1057 while ((at
= strstr (str
->str
, "@{"))) {
1058 gint len
= at
- str
->str
;
1059 go_string_replace (str
, len
, 2, span_text
, -1);
1061 (str
->str
+ len
+ span_text_len
, "}"))) {
1062 len
= at
- str
->str
;
1063 go_string_replace (str
, len
, 1, "</span>", -1);
1065 g_string_append (str
, "</span>");
1069 return g_string_free (str
, FALSE
);
1073 /* ------------------------------------------------------------------------- */
1076 free_values (GnmValue
**values
, int top
)
1080 for (i
= 0; i
< top
; 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.
1096 function_call_with_exprs (GnmFuncEvalInfo
*ei
)
1098 GnmFunc
const *fn_def
;
1099 int i
, iter_count
, iter_width
= 0, iter_height
= 0;
1101 GnmValue
**args
, *tmp
= NULL
;
1102 int *iter_item
= NULL
;
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
);
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
))
1132 /* Optimization for IF when implicit iteration is not used. */
1133 if (ei
->func_call
->func
->fn
.args
.func
== gnumeric_if
&&
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
1144 GnmExpr
const *expr
= argv
[i
];
1146 if (arg_type
== 'A' || arg_type
== 'r') {
1147 tmp
= args
[i
] = gnm_expr_eval
1150 GNM_EXPR_EVAL_PERMIT_NON_SCALAR
|
1151 GNM_EXPR_EVAL_WANT_REF
);
1152 if (VALUE_IS_ERROR (tmp
)) {
1153 free_values (args
, i
);
1157 if (VALUE_IS_CELLRANGE (tmp
)) {
1158 gnm_cellref_make_abs (&tmp
->v_range
.cell
.a
,
1159 &tmp
->v_range
.cell
.a
,
1161 gnm_cellref_make_abs (&tmp
->v_range
.cell
.b
,
1162 &tmp
->v_range
.cell
.b
,
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
);
1172 /* force scalars whenever we are certain */
1173 tmp
= args
[i
] = gnm_expr_eval
1176 GNM_EXPR_EVAL_PERMIT_EMPTY
|
1177 (iter_count
>= 0 || arg_type
== '?'
1178 ? GNM_EXPR_EVAL_PERMIT_NON_SCALAR
1181 if (arg_type
== '?') /* '?' arguments are unrestriced */
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 ();
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
);
1207 if (iter_count
< 0) {
1208 g_warning ("Damn I thought this was impossible");
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" */
1221 /* All of these argument types must be scalars */
1224 if (VALUE_IS_STRING (tmp
)) {
1226 gboolean b
= value_get_as_bool (tmp
, &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
);
1237 if (VALUE_IS_STRING (tmp
)) {
1238 tmp
= format_match_number (value_peek_string (tmp
), NULL
,
1239 sheet_date_conv (ei
->pos
->sheet
));
1241 free_values (args
, i
+ 1);
1242 return value_new_error_VALUE (ei
->pos
);
1244 value_release (args
[i
]);
1246 } else if (VALUE_IS_ERROR (tmp
)) {
1247 free_values (args
, i
);
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
);
1260 if (VALUE_IS_ERROR (tmp
)) {
1261 free_values (args
, i
);
1266 case 'E': /* nothing necessary */
1269 /* case '?': handled above */
1271 g_warning ("Unknown argument type '%c'", arg_type
);
1276 while (i
< fn_def
->fn
.args
.max_args
)
1279 if (iter_item
!= NULL
) {
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 */
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
))
1300 else if (VALUE_IS_STRING (elem
)) {
1301 tmp
= format_match_number (value_peek_string (elem
), NULL
,
1302 sheet_date_conv (ei
->pos
->sheet
));
1304 args
[iter_item
[i
]] = iter_args
[i
] = tmp
;
1308 } else if (VALUE_IS_ERROR (elem
)) {
1311 } else if (!VALUE_IS_NUMBER (elem
))
1313 } else if (arg_type
== 's') {
1314 if (VALUE_IS_EMPTY (elem
)) {
1315 args
[iter_item
[i
]] = iter_args
[i
] = value_new_string ("");
1317 } else if (VALUE_IS_ERROR (elem
)) {
1320 } else if (!VALUE_IS_STRING (elem
))
1322 } else if (elem
== NULL
) {
1323 args
[iter_item
[i
]] = iter_args
[i
] = value_new_empty ();
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
];
1340 i
= fn_def
->fn
.args
.max_args
;
1342 tmp
= fn_def
->fn
.args
.func (ei
, (GnmValue
const * const *)args
);
1344 free_values (args
, i
);
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
1353 function_call_with_values (GnmEvalPos
const *ep
, char const *fn_name
,
1354 int argc
, GnmValue
const * const *values
)
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
);
1365 return value_new_error_NAME (ep
);
1366 return function_def_call_with_values (ep
, fn_def
, argc
, values
);
1370 function_def_call_with_values (GnmEvalPos
const *ep
, GnmFunc
const *fn_def
,
1371 int argc
, GnmValue
const * const *values
)
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
);
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
);
1400 retval
= fn_def
->fn
.args
.func (&fs
, values
);
1405 /* ------------------------------------------------------------------------- */
1408 FunctionIterateCB callback
;
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.
1421 cb_iterate_cellrange (GnmCellIter
const *iter
, gpointer user
)
1424 IterateCallbackClosure
*data
= user
;
1429 if (NULL
== (cell
= iter
->cell
)) {
1430 ep
.sheet
= iter
->pp
.sheet
;
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
))
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.
1458 function_iterate_do_value (GnmEvalPos
const *ep
,
1459 FunctionIterateCB callback
,
1461 GnmValue
const *value
,
1463 CellIterFlags iter_flags
)
1465 GnmValue
*res
= NULL
;
1467 switch (value
->v_any
.type
){
1470 res
= value_dup (value
);
1479 res
= (*callback
)(ep
, value
, closure
);
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
);
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
,
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.
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).
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).
1539 function_iterate_argument_values (GnmEvalPos
const *ep
,
1540 FunctionIterateCB callback
,
1541 void *callback_closure
,
1543 GnmExprConstPtr
const *argv
,
1545 CellIterFlags iter_flags
)
1547 GnmValue
*result
= NULL
;
1550 for (a
= 0; result
== NULL
&& a
< argc
; a
++) {
1551 GnmExpr
const *expr
= argv
[a
];
1554 if (iter_flags
& CELL_ITER_IGNORE_SUBTOTAL
&&
1555 gnm_expr_contains_subtotal (expr
))
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
;
1565 return value_new_error_REF (ep
);
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
);
1581 /* We need a cleaner model of what to do here.
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)
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
);
1602 val
= gnm_expr_eval (expr
, ep
, GNM_EXPR_EVAL_PERMIT_EMPTY
);
1607 if (strict
&& VALUE_IS_ERROR (val
)) {
1608 /* Be careful not to make VALUE_TERMINATE into a real value */
1612 result
= function_iterate_do_value (ep
, callback
, callback_closure
,
1613 val
, strict
, iter_flags
);
1614 value_release (val
);
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
;