1 /*
2 * func.c: Function management and utility routines.
3 *
4 * Author:
5 * Miguel de Icaza (miguel@gnu.org)
6 * Michael Meeks (mmeeks@gnu.org)
7 * Morten Welinder (terra@gnome.org)
8 * Jody Goldberg (jody@gnome.org)
9 */
10
11 #include <gnumeric-config.h>
12 #include <glib/gi18n-lib.h>
13 #include <glib/gstdio.h>
14 #include <gnm-i18n.h>
15 #include <gnumeric.h>
16 #include <func.h>
17
18 #include <parse-util.h>
19 #include <dependent.h>
20 #include <expr.h>
21 #include <expr-impl.h>
22 #include <expr-name.h>
23 #include <cell.h>
24 #include <workbook-priv.h>
25 #include <sheet.h>
26 #include <value.h>
27 #include <number-match.h>
28 #include <func-builtin.h>
29 #include <command-context-stderr.h>
30 #include <gnm-plugin.h>
31 #include <gutils.h>
32 #include <gui-util.h>
33 #include <expr-deriv.h>
34 #include <gnm-marshalers.h>
35
36 #include <goffice/goffice.h>
37 #include <glib.h>
38 #include <string.h>
39 #include <stdlib.h>
40
41 enum {
42 PROP_0,
43 PROP_NAME,
44 PROP_TRANSLATION_DOMAIN,
45 PROP_IN_USE,
46 };
47
48 enum {
49 SIG_LOAD_STUB,
50 SIG_LINK_DEP,
51 SIG_DERIVATIVE,
52 LAST_SIGNAL
53 };
54 static guint signals[LAST_SIGNAL] = { 0 };
55
56
57 static GList *categories;
58 static GnmFuncGroup *unknown_cat;
59
60 static GHashTable *functions_by_name;
61 static GHashTable *functions_by_localized_name;
62
63 static GnmFunc *fn_if;
64
65 /**
66 * gnm_func_init_: (skip)
67 */
68 void
gnm_func_init_(void)69 gnm_func_init_ (void)
70 {
71 functions_by_name =
72 g_hash_table_new (go_ascii_strcase_hash, go_ascii_strcase_equal);
73
74 /* FIXME: ascii??? */
75 functions_by_localized_name =
76 g_hash_table_new (go_ascii_strcase_hash, go_ascii_strcase_equal);
77
78 gnm_func_builtin_init ();
79
80 fn_if = gnm_func_lookup ("if", NULL);
81 }
82
83 /**
84 * gnm_func_shutdown_: (skip)
85 */
86 void
gnm_func_shutdown_(void)87 gnm_func_shutdown_ (void)
88 {
89 fn_if = NULL;
90
91 while (unknown_cat != NULL && unknown_cat->functions != NULL) {
92 GnmFunc *func = unknown_cat->functions->data;
93 if (func->usage_count > 0) {
94 g_warning ("Function %s still has %d users.\n",
95 gnm_func_get_name (func, FALSE),
96 func->usage_count);
97 func->usage_count = 0;
98 }
99 g_object_unref (func);
100 }
101 gnm_func_builtin_shutdown ();
102
103 g_hash_table_destroy (functions_by_name);
104 functions_by_name = NULL;
105
106 g_hash_table_destroy (functions_by_localized_name);
107 functions_by_localized_name = NULL;
108 }
109
110 /**
111 * gnm_func_enumerate:
112 *
113 * Return value: (element-type GnmFunc) (transfer container):
114 */
115 GPtrArray *
gnm_func_enumerate(void)116 gnm_func_enumerate (void)
117 {
118 GPtrArray *res = g_ptr_array_new ();
119 GHashTableIter hiter;
120 gpointer value;
121
122 g_hash_table_iter_init (&hiter, functions_by_name);
123 while (g_hash_table_iter_next (&hiter, NULL, &value))
124 g_ptr_array_add (res, value);
125
126 return res;
127 }
128
129 static GnmValue *
error_function_no_full_info(GnmFuncEvalInfo * ei,int argc,GnmExprConstPtr const * argv)130 error_function_no_full_info (GnmFuncEvalInfo *ei,
131 int argc,
132 GnmExprConstPtr const *argv)
133 {
134 return value_new_error (ei->pos, _("Function implementation not available."));
135 }
136
137 static void
gnm_func_load_stub(GnmFunc * func)138 gnm_func_load_stub (GnmFunc *func)
139 {
140 g_return_if_fail (func->fn_type == GNM_FUNC_TYPE_STUB);
141
142 g_signal_emit (G_OBJECT (func), signals[SIG_LOAD_STUB], 0);
143
144 if (func->fn_type == GNM_FUNC_TYPE_STUB) {
145 g_printerr ("Failed to load %s\n", func->name);
146 gnm_func_set_varargs (func, error_function_no_full_info, NULL);
147 gnm_func_set_help (func, NULL, 0);
148 }
149 }
150
151 inline void
gnm_func_load_if_stub(GnmFunc * func)152 gnm_func_load_if_stub (GnmFunc *func)
153 {
154 if (func->fn_type == GNM_FUNC_TYPE_STUB)
155 gnm_func_load_stub (func);
156 }
157
158 static char *
split_at_colon(char const * s,char ** rest)159 split_at_colon (char const *s, char **rest)
160 {
161 char *dup = g_strdup (s);
162 char *colon = strchr (dup, ':');
163 if (colon) {
164 *colon = 0;
165 if (rest) *rest = colon + 1;
166 } else {
167 if (rest) *rest = NULL;
168 }
169 return dup;
170 }
171
172 /* ------------------------------------------------------------------------- */
173
174 static void
gnm_func_group_unref(GnmFuncGroup * fn_group)175 gnm_func_group_unref (GnmFuncGroup *fn_group)
176 {
177 g_return_if_fail (fn_group != NULL);
178 g_return_if_fail (fn_group->functions == NULL);
179
180 if (fn_group->ref_count-- > 1)
181 return;
182
183 go_string_unref (fn_group->internal_name);
184 go_string_unref (fn_group->display_name);
185 g_free (fn_group);
186 }
187
188 static GnmFuncGroup *
gnm_func_group_ref(GnmFuncGroup * fn_group)189 gnm_func_group_ref (GnmFuncGroup *fn_group)
190 {
191 fn_group->ref_count++;
192 return fn_group;
193 }
194
195 GType
gnm_func_group_get_type(void)196 gnm_func_group_get_type (void)
197 {
198 static GType t = 0;
199
200 if (t == 0) {
201 t = g_boxed_type_register_static ("GnmFuncGroup",
202 (GBoxedCopyFunc)gnm_func_group_ref,
203 (GBoxedFreeFunc)gnm_func_group_unref);
204 }
205 return t;
206 }
207
208 static gint
function_category_compare(gconstpointer a,gconstpointer b)209 function_category_compare (gconstpointer a, gconstpointer b)
210 {
211 GnmFuncGroup const *cat_a = a;
212 GnmFuncGroup const *cat_b = b;
213
214 return go_string_cmp (cat_a->display_name, cat_b->display_name);
215 }
216
217 GnmFuncGroup *
gnm_func_group_fetch(char const * name,char const * translation)218 gnm_func_group_fetch (char const *name, char const *translation)
219 {
220 GnmFuncGroup *cat = NULL;
221 GList *l;
222
223 g_return_val_if_fail (name != NULL, NULL);
224
225 for (l = categories; l != NULL; l = l->next) {
226 cat = l->data;
227 if (strcmp (cat->internal_name->str, name) == 0) {
228 break;
229 }
230 }
231
232 if (l == NULL) {
233 cat = g_new (GnmFuncGroup, 1);
234 cat->internal_name = go_string_new (name);
235 cat->ref_count = 1;
236 if (translation != NULL) {
237 cat->display_name = go_string_new (translation);
238 cat->has_translation = TRUE;
239 } else {
240 cat->display_name = go_string_new (name);
241 cat->has_translation = FALSE;
242 }
243 cat->functions = NULL;
244 categories = g_list_insert_sorted (
245 categories, cat, &function_category_compare);
246 } else if (translation != NULL && translation != name &&
247 !cat->has_translation) {
248 go_string_unref (cat->display_name);
249 cat->display_name = go_string_new (translation);
250 cat->has_translation = TRUE;
251 categories = g_list_remove_link (categories, l);
252 g_list_free_1 (l);
253 categories = g_list_insert_sorted (
254 categories, cat, &function_category_compare);
255 }
256
257 return cat;
258 }
259
260 GnmFuncGroup *
gnm_func_group_get_nth(int n)261 gnm_func_group_get_nth (int n)
262 {
263 return g_list_nth_data (categories, n);
264 }
265
266 static void
gnm_func_group_add_func(GnmFuncGroup * fn_group,GnmFunc * func)267 gnm_func_group_add_func (GnmFuncGroup *fn_group, GnmFunc *func)
268 {
269 g_return_if_fail (fn_group != NULL);
270 g_return_if_fail (func != NULL);
271
272 fn_group->functions = g_slist_prepend (fn_group->functions, func);
273 }
274
275 static void
gnm_func_group_remove_func(GnmFuncGroup * fn_group,GnmFunc * func)276 gnm_func_group_remove_func (GnmFuncGroup *fn_group, GnmFunc *func)
277 {
278 g_return_if_fail (fn_group != NULL);
279 g_return_if_fail (func != NULL);
280
281 fn_group->functions = g_slist_remove (fn_group->functions, func);
282 if (fn_group->functions == NULL) {
283 categories = g_list_remove (categories, fn_group);
284 if (unknown_cat == fn_group)
285 unknown_cat = NULL;
286 gnm_func_group_unref (fn_group);
287 }
288 }
289
290 /******************************************************************************/
291
292 static void
gnm_func_create_arg_names(GnmFunc * func)293 gnm_func_create_arg_names (GnmFunc *func)
294 {
295 int i;
296 GPtrArray *ptr;
297
298 g_return_if_fail (func != NULL);
299
300 ptr = g_ptr_array_new ();
301 for (i = 0; i < func->help_count; i++) {
302 const char *s;
303 if (func->help[i].type != GNM_FUNC_HELP_ARG)
304 continue;
305
306 s = gnm_func_gettext (func, func->help[i].text);
307 g_ptr_array_add (ptr, split_at_colon (s, NULL));
308 }
309
310 func->arg_names = ptr;
311 }
312
313 gboolean
gnm_func_is_varargs(GnmFunc const * func)314 gnm_func_is_varargs (GnmFunc const *func)
315 {
316 gnm_func_load_if_stub ((GnmFunc *)func);
317 return func->fn_type == GNM_FUNC_TYPE_NODES;
318 }
319
320 gboolean
gnm_func_is_fixargs(GnmFunc const * func)321 gnm_func_is_fixargs (GnmFunc const *func)
322 {
323 gnm_func_load_if_stub ((GnmFunc *)func);
324 return func->fn_type == GNM_FUNC_TYPE_ARGS;
325 }
326
327 void
gnm_func_set_stub(GnmFunc * func)328 gnm_func_set_stub (GnmFunc *func)
329 {
330 func->fn_type = GNM_FUNC_TYPE_STUB;
331
332 g_free (func->arg_spec);
333 func->arg_spec = NULL;
334
335 g_free (func->arg_types);
336 func->arg_types = NULL;
337
338 func->min_args = func->max_args = 0;
339
340 func->nodes_func = NULL;
341 func->args_func = NULL;
342
343 gnm_func_set_help (func, NULL, 0);
344 }
345
346 /**
347 * gnm_func_set_varargs: (skip)
348 * @func: #GnmFunc
349 * @fn: evaluation function
350 * @spec: (nullable): argument type specification
351 */
352 void
gnm_func_set_varargs(GnmFunc * func,GnmFuncNodes fn,const char * spec)353 gnm_func_set_varargs (GnmFunc *func, GnmFuncNodes fn, const char *spec)
354 {
355 g_return_if_fail (GNM_IS_FUNC (func));
356 g_return_if_fail (fn != NULL);
357
358 gnm_func_set_stub (func); // Clear out stuff
359
360 func->fn_type = GNM_FUNC_TYPE_NODES;
361 func->nodes_func = fn;
362 func->arg_spec = g_strdup (spec);
363 func->min_args = 0;
364 func->max_args = G_MAXINT;
365
366 if (spec) {
367 const char *p = strchr (spec, '|');
368 const char *q = strchr (spec, '.'); // "..."
369 if (p) func->min_args = p - spec;
370 if (!q) func->min_args = strlen (spec) - (p != NULL);
371 }
372 }
373
374 /**
375 * gnm_func_set_fixargs: (skip)
376 * @func: #GnmFunc
377 * @fn: evaluation function
378 * @spec: argument type specification
379 */
380 void
gnm_func_set_fixargs(GnmFunc * func,GnmFuncArgs fn,const char * spec)381 gnm_func_set_fixargs (GnmFunc *func, GnmFuncArgs fn, const char *spec)
382 {
383 char *p;
384
385 g_return_if_fail (GNM_IS_FUNC (func));
386 g_return_if_fail (fn != NULL);
387 g_return_if_fail (spec != NULL);
388
389 gnm_func_set_stub (func); // Clear out stuff
390
391 func->fn_type = GNM_FUNC_TYPE_ARGS;
392 func->args_func = fn;
393 func->arg_spec = g_strdup (spec);
394
395 func->arg_types = g_strdup (func->arg_spec);
396 p = strchr (func->arg_types, '|');
397 if (p) {
398 func->min_args = p - func->arg_types;
399 memmove (p, p + 1, strlen (p));
400 } else
401 func->min_args = strlen (func->arg_types);
402 func->max_args = strlen (func->arg_types);
403 }
404
405 /**
406 * gnm_func_get_help:
407 * @func: #GnmFunc
408 * @n: (out) (optional): number of help items, not counting the end item
409 *
410 * Returns: (transfer none) (array length=n) (nullable): @func's help items.
411 */
412 GnmFuncHelp const *
gnm_func_get_help(GnmFunc const * func,int * n)413 gnm_func_get_help (GnmFunc const *func, int *n)
414 {
415 if (n) *n = 0;
416
417 g_return_val_if_fail (GNM_IS_FUNC (func), NULL);
418 g_return_val_if_fail (func->help, NULL);
419
420 if (n) *n = func->help_count;
421 return func->help;
422 }
423
424
425 void
gnm_func_set_help(GnmFunc * func,GnmFuncHelp const * help,int n)426 gnm_func_set_help (GnmFunc *func, GnmFuncHelp const *help, int n)
427 {
428 g_return_if_fail (GNM_IS_FUNC (func));
429 g_return_if_fail (n <= 0 || help != NULL);
430
431 if (n < 0) {
432 for (n = 0; help && help[n].type != GNM_FUNC_HELP_END; )
433 n++;
434 }
435
436 if (func->help) {
437 int i;
438 for (i = 0; i <= func->help_count; i++)
439 g_free ((char *)(func->help[i].text));
440 g_free (func->help);
441 func->help = NULL;
442 }
443
444 if (func->arg_names) {
445 g_ptr_array_foreach (func->arg_names, (GFunc)g_free, NULL);
446 g_ptr_array_free (func->arg_names, TRUE);
447 func->arg_names = NULL;
448 }
449
450 if (help) {
451 int i;
452
453 func->help = g_new (GnmFuncHelp, n + 1);
454 for (i = 0; i < n; i++) {
455 func->help[i].type = help[i].type;
456 func->help[i].text = g_strdup (help[i].text);
457 }
458 func->help[n].type = GNM_FUNC_HELP_END;
459 func->help[n].text = NULL;
460
461 func->help_count = n;
462 gnm_func_create_arg_names (func);
463 } else {
464 func->help_count = 0;
465 }
466 }
467
468
469 static void
gnm_func_set_localized_name(GnmFunc * fd,const char * lname)470 gnm_func_set_localized_name (GnmFunc *fd, const char *lname)
471 {
472 gboolean in_hashes = !(fd->flags & GNM_FUNC_IS_WORKBOOK_LOCAL);
473
474 if (g_strcmp0 (fd->localized_name, lname) == 0)
475 return;
476
477 if (in_hashes && fd->localized_name)
478 g_hash_table_remove (functions_by_localized_name, fd->localized_name);
479 g_free (fd->localized_name);
480
481 fd->localized_name = g_strdup (lname);
482 if (in_hashes && lname)
483 g_hash_table_insert (functions_by_localized_name,
484 fd->localized_name, fd);
485 }
486
487 /**
488 * gnm_func_inc_usage:
489 * @func: #GnmFunc
490 *
491 * This function increments the usage count of @func. A non-zero usage count
492 * prevents the unloading of the function.
493 *
494 * Returns: (transfer full): a new reference to @func.
495 */
496 GnmFunc *
gnm_func_inc_usage(GnmFunc * func)497 gnm_func_inc_usage (GnmFunc *func)
498 {
499 g_return_val_if_fail (func != NULL, NULL);
500
501 func->usage_count++;
502 if (func->usage_count == 1)
503 g_object_notify (G_OBJECT (func), "in-use");
504 return func;
505 }
506
507 /**
508 * gnm_func_dec_usage:
509 * @func: (transfer full): #GnmFunc
510 *
511 * This function decrements the usage count of @func. When the usage count
512 * reaches zero, the function may be unloaded, for example by unloading the
513 * plugin that defines it.
514 */
515 void
gnm_func_dec_usage(GnmFunc * func)516 gnm_func_dec_usage (GnmFunc *func)
517 {
518 g_return_if_fail (func != NULL);
519 g_return_if_fail (func->usage_count > 0);
520
521 func->usage_count--;
522 if (func->usage_count == 0)
523 g_object_notify (G_OBJECT (func), "in-use");
524 }
525
526 gboolean
gnm_func_get_in_use(GnmFunc * func)527 gnm_func_get_in_use (GnmFunc *func)
528 {
529 g_return_val_if_fail (func != NULL, FALSE);
530
531 return func->usage_count > 0;
532 }
533
534
535 /**
536 * gnm_func_lookup:
537 * @name: name of function
538 * @scope: (nullable): scope of function, %NULL for global
539 *
540 * Returns: (nullable) (transfer none): the function of that name.
541 */
542 GnmFunc *
gnm_func_lookup(char const * name,Workbook * scope)543 gnm_func_lookup (char const *name, Workbook *scope)
544 {
545 GnmFunc *fd = g_hash_table_lookup (functions_by_name, name);
546 if (fd != NULL)
547 return fd;
548 if (scope == NULL || scope->sheet_local_functions == NULL)
549 return NULL;
550 return g_hash_table_lookup (scope->sheet_local_functions, (gpointer)name);
551 }
552
553 /**
554 * gnm_func_lookup_localized:
555 * @name: localized name of function
556 * @scope: (nullable): scope of function, %NULL for global
557 *
558 * Returns: (nullable) (transfer none): the function of that name.
559 */
560 GnmFunc *
gnm_func_lookup_localized(char const * name,Workbook * scope)561 gnm_func_lookup_localized (char const *name, Workbook *scope)
562 {
563 GnmFunc *fd;
564 GHashTableIter hiter;
565 gpointer value;
566
567 /* Must localize all function names. */
568 g_hash_table_iter_init (&hiter, functions_by_name);
569 while (g_hash_table_iter_next (&hiter, NULL, &value)) {
570 GnmFunc *fd = value;
571 (void)gnm_func_get_name (fd, TRUE);
572 }
573
574 fd = g_hash_table_lookup (functions_by_localized_name, name);
575 if (fd != NULL)
576 return fd;
577 if (scope == NULL || scope->sheet_local_functions == NULL)
578 return NULL;
579 return g_hash_table_lookup (scope->sheet_local_functions, (gpointer)name);
580 }
581
582 /**
583 * gnm_func_lookup_prefix:
584 * @prefix: prefix to search for
585 * @scope:
586 * @trans: whether to search translated function names
587 *
588 * Returns: (element-type GnmFunc*) (transfer full): A list of functions
589 * whose names start with @prefix.
590 **/
591 GSList *
gnm_func_lookup_prefix(char const * prefix,Workbook * scope,gboolean trans)592 gnm_func_lookup_prefix (char const *prefix, Workbook *scope, gboolean trans)
593 {
594 GSList *res = NULL;
595 GHashTableIter hiter;
596 gpointer value;
597
598 /*
599 * Always iterate over functions_by_name as the localized name
600 * might not be set yet.
601 */
602 g_hash_table_iter_init (&hiter, functions_by_name);
603 while (g_hash_table_iter_next (&hiter, NULL, &value)) {
604 GnmFunc *fd = value;
605 if (!(fd->flags & (GNM_FUNC_IS_PLACEHOLDER | GNM_FUNC_INTERNAL))) {
606 const char *name = gnm_func_get_name (fd, trans);
607 if (g_str_has_prefix (name, prefix)) {
608 gnm_func_inc_usage (fd);
609 res = g_slist_prepend (res, fd);
610 }
611 }
612 }
613
614 return res;
615 }
616
617 /**
618 * gnm_func_get_translation_domain:
619 * @func: #GnmFunc
620 *
621 * Returns: (transfer none): the translation domain for @func's help text.
622 */
623 char const *
gnm_func_get_translation_domain(GnmFunc const * func)624 gnm_func_get_translation_domain (GnmFunc const *func)
625 {
626 g_return_val_if_fail (GNM_IS_FUNC (func), NULL);
627 return func->tdomain->str;
628 }
629
630 /**
631 * gnm_func_set_translation_domain:
632 * @func: #GnmFunc
633 * @tdomain: (nullable): Translation domain, %NULL for Gnumeric's.
634 */
635 void
gnm_func_set_translation_domain(GnmFunc * func,const char * tdomain)636 gnm_func_set_translation_domain (GnmFunc *func, const char *tdomain)
637 {
638 g_return_if_fail (GNM_IS_FUNC (func));
639
640 if (!tdomain)
641 tdomain = GETTEXT_PACKAGE;
642
643 if (g_strcmp0 (func->tdomain->str, tdomain) == 0)
644 return;
645
646 go_string_unref (func->tdomain);
647 func->tdomain = go_string_new (tdomain);
648
649 g_object_notify (G_OBJECT (func), "translation-domain");
650 }
651
652 /**
653 * gnm_func_gettext:
654 * @func: #GnmFunc
655 * @str: string to translate
656 *
657 * Returns: (transfer none): @str translated in @func's translation
658 * domain.
659 */
660 char const *
gnm_func_gettext(GnmFunc const * func,const char * str)661 gnm_func_gettext (GnmFunc const *func, const char *str)
662 {
663 g_return_val_if_fail (GNM_IS_FUNC (func), NULL);
664 g_return_val_if_fail (str != NULL, NULL);
665
666 return dgettext (func->tdomain->str, str);
667 }
668
669
670 GnmFuncFlags
gnm_func_get_flags(GnmFunc const * func)671 gnm_func_get_flags (GnmFunc const *func)
672 {
673 g_return_val_if_fail (GNM_IS_FUNC (func), GNM_FUNC_SIMPLE);
674 return func->flags;
675 }
676
677 void
gnm_func_set_flags(GnmFunc * func,GnmFuncFlags f)678 gnm_func_set_flags (GnmFunc *func, GnmFuncFlags f)
679 {
680 g_return_if_fail (GNM_IS_FUNC (func));
681 func->flags = f;
682 }
683
684 GnmFuncImplStatus
gnm_func_get_impl_status(GnmFunc const * func)685 gnm_func_get_impl_status (GnmFunc const *func)
686 {
687 g_return_val_if_fail (GNM_IS_FUNC (func), GNM_FUNC_IMPL_STATUS_UNIMPLEMENTED);
688 return func->impl_status;
689 }
690
691 void
gnm_func_set_impl_status(GnmFunc * func,GnmFuncImplStatus st)692 gnm_func_set_impl_status (GnmFunc *func, GnmFuncImplStatus st)
693 {
694 g_return_if_fail (GNM_IS_FUNC (func));
695 func->impl_status = st;
696 }
697
698
699 GnmFuncTestStatus
gnm_func_get_test_status(GnmFunc const * func)700 gnm_func_get_test_status (GnmFunc const *func)
701 {
702 g_return_val_if_fail (GNM_IS_FUNC (func), GNM_FUNC_TEST_STATUS_UNKNOWN);
703 return func->test_status;
704 }
705
706 void
gnm_func_set_test_status(GnmFunc * func,GnmFuncTestStatus st)707 gnm_func_set_test_status (GnmFunc *func, GnmFuncTestStatus st)
708 {
709 g_return_if_fail (GNM_IS_FUNC (func));
710 func->test_status = st;
711 }
712
713
714 /**
715 * gnm_func_get_function_group:
716 * @func: #GnmFunc
717 *
718 * Returns: (transfer none): the function group to which @func belongs.
719 */
720 GnmFuncGroup *
gnm_func_get_function_group(GnmFunc * func)721 gnm_func_get_function_group (GnmFunc *func)
722 {
723 g_return_val_if_fail (GNM_IS_FUNC (func), NULL);
724 return func->fn_group;
725 }
726
727
728 void
gnm_func_set_function_group(GnmFunc * func,GnmFuncGroup * group)729 gnm_func_set_function_group (GnmFunc *func, GnmFuncGroup *group)
730 {
731 g_return_if_fail (GNM_IS_FUNC (func));
732 g_return_if_fail (group != NULL);
733
734 if (func->fn_group == group)
735 return;
736
737 if (func->fn_group)
738 gnm_func_group_remove_func (func->fn_group, func);
739 func->fn_group = group;
740 gnm_func_group_add_func (group, func);
741
742 if (group == unknown_cat)
743 func->flags |= GNM_FUNC_IS_PLACEHOLDER;
744 else
745 func->flags &= ~GNM_FUNC_IS_PLACEHOLDER;
746 }
747
748 void
gnm_func_set_from_desc(GnmFunc * func,GnmFuncDescriptor const * desc)749 gnm_func_set_from_desc (GnmFunc *func, GnmFuncDescriptor const *desc)
750 {
751 //static char const valid_tokens[] = "fsbraAES?|";
752
753 g_return_if_fail (GNM_IS_FUNC (func));
754 g_return_if_fail (desc != NULL);
755
756 // Not setting name, localized_name. Also not setting things not present
757 // in desc, such as translation domain.
758
759 if (desc->fn_args != NULL) {
760 gnm_func_set_fixargs (func, desc->fn_args, desc->arg_spec);
761 } else if (desc->fn_nodes != NULL) {
762 gnm_func_set_varargs (func, desc->fn_nodes, desc->arg_spec);
763 } else {
764 gnm_func_set_stub (func);
765 return;
766 }
767
768 gnm_func_set_help (func, desc->help, -1);
769 func->flags = desc->flags;
770 func->impl_status = desc->impl_status;
771 func->test_status = desc->test_status;
772 }
773
774
775 /**
776 * gnm_func_add:
777 * @group:
778 * @descriptor:
779 * @tdomain: (nullable):
780 *
781 * Returns: (transfer full): a new #GnmFunc.
782 */
783 GnmFunc *
gnm_func_add(GnmFuncGroup * fn_group,GnmFuncDescriptor const * desc,const char * tdomain)784 gnm_func_add (GnmFuncGroup *fn_group,
785 GnmFuncDescriptor const *desc,
786 const char *tdomain)
787 {
788 GnmFunc *func;
789
790 g_return_val_if_fail (fn_group != NULL, NULL);
791 g_return_val_if_fail (desc != NULL, NULL);
792
793 func = g_object_new (GNM_FUNC_TYPE,
794 "name", desc->name,
795 NULL);
796 gnm_func_set_translation_domain (func, tdomain);
797
798 gnm_func_set_from_desc (func, desc);
799
800 if (func->fn_type == GNM_FUNC_TYPE_STUB) {
801 g_warning ("Invalid function has neither args nor nodes handler");
802 g_object_unref (func);
803 return NULL;
804 }
805
806 gnm_func_set_function_group (func, fn_group);
807
808 if (!(func->flags & GNM_FUNC_IS_WORKBOOK_LOCAL))
809 g_hash_table_insert (functions_by_name,
810 (gpointer)(func->name), func);
811
812 return func;
813 }
814
815 /* Handle unknown functions on import without losing their names */
816 static GnmValue *
unknownFunctionHandler(GnmFuncEvalInfo * ei,G_GNUC_UNUSED int argc,G_GNUC_UNUSED GnmExprConstPtr const * argv)817 unknownFunctionHandler (GnmFuncEvalInfo *ei,
818 G_GNUC_UNUSED int argc,
819 G_GNUC_UNUSED GnmExprConstPtr const *argv)
820 {
821 return value_new_error_NAME (ei->pos);
822 }
823
824 static char *
invent_name(const char * pref,GHashTable * h,const char * template)825 invent_name (const char *pref, GHashTable *h, const char *template)
826 {
827 static int count = 0;
828 char *name = g_utf8_strdown (pref, -1);
829
830 while (g_hash_table_lookup (h, name)) {
831 count++;
832 g_free (name);
833 name = g_strdup_printf (template, count);
834 }
835
836 return name;
837 }
838
839 static GnmFunc *
gnm_func_add_placeholder_full(Workbook * scope,char const * gname,char const * lname,char const * type)840 gnm_func_add_placeholder_full (Workbook *scope,
841 char const *gname, char const *lname,
842 char const *type)
843 {
844 GnmFuncDescriptor desc;
845 GnmFunc *func;
846 char const *unknown_cat_name = N_("Unknown Function");
847 gboolean copy_gname = TRUE;
848 gboolean copy_lname = TRUE;
849
850 g_return_val_if_fail (gname || lname, NULL);
851 g_return_val_if_fail (gname == NULL || gnm_func_lookup (gname, scope) == NULL, NULL);
852 g_return_val_if_fail (lname == NULL || gnm_func_lookup_localized (lname, scope) == NULL, NULL);
853
854 if (!unknown_cat)
855 unknown_cat = gnm_func_group_fetch
856 (unknown_cat_name, _(unknown_cat_name));
857
858 if (!gname) {
859 /*
860 * This is actually a bit of a problem if we don't end up
861 * with a copy of lname (because there already is a function
862 * with that name). We're likely to save a template name,
863 * but I don't see what else to do.
864 */
865 gname = invent_name (lname, functions_by_name, "unknown%d");
866 copy_gname = FALSE;
867 }
868 if (!lname) {
869 /* xgettext: This represents a made-up translated function name. */
870 lname = invent_name (gname, functions_by_localized_name, _("unknown%d"));
871 copy_lname = FALSE;
872 }
873
874 if (gnm_debug_flag ("func"))
875 g_printerr ("Adding placeholder for %s (aka %s)\n", gname, lname);
876
877 memset (&desc, 0, sizeof (GnmFuncDescriptor));
878 desc.name = gname;
879 desc.arg_spec = NULL;
880 desc.help = NULL;
881 desc.fn_args = NULL;
882 desc.fn_nodes = &unknownFunctionHandler;
883 desc.flags = GNM_FUNC_IS_PLACEHOLDER;
884 desc.impl_status = GNM_FUNC_IMPL_STATUS_EXISTS;
885 desc.test_status = GNM_FUNC_TEST_STATUS_UNKNOWN;
886
887 if (scope != NULL)
888 desc.flags |= GNM_FUNC_IS_WORKBOOK_LOCAL;
889 else {
890 #if 0
891 /* WISHLIST : it would be nice to have a log if these. */
892 g_warning ("Unknown %s function : %s", type, desc.name);
893 #endif
894 }
895
896 func = gnm_func_add (unknown_cat, &desc, NULL);
897
898 if (lname) {
899 gnm_func_set_localized_name (func, lname);
900 if (!copy_lname)
901 g_free ((char *)lname);
902 }
903
904 if (!copy_gname)
905 g_free ((char *)gname);
906
907 if (scope != NULL) {
908 if (scope->sheet_local_functions == NULL)
909 scope->sheet_local_functions = g_hash_table_new_full (
910 g_str_hash, g_str_equal,
911 NULL, g_object_unref);
912 g_hash_table_insert (scope->sheet_local_functions,
913 (gpointer)func->name, func);
914 }
915
916 return func;
917 }
918
919 /**
920 * gnm_func_add_placeholder:
921 * @scope: (nullable): scope to defined placeholder, %NULL for global
922 * @name: (nullable): function name
923 * @type:
924 *
925 * Returns: (transfer none): a placeholder with the given name.
926 */
927 GnmFunc *
gnm_func_add_placeholder(Workbook * scope,char const * name,char const * type)928 gnm_func_add_placeholder (Workbook *scope,
929 char const *name, char const *type)
930 {
931 return gnm_func_add_placeholder_full (scope, name, NULL, type);
932 }
933
934 /**
935 * gnm_func_add_placeholder_localized:
936 * @gname: (nullable): function name
937 * @lname: localized function name
938 *
939 * Returns: (transfer none): a placeholder with the given localized name.
940 */
941 GnmFunc *
gnm_func_add_placeholder_localized(char const * gname,char const * lname)942 gnm_func_add_placeholder_localized (char const *gname, char const *lname)
943 {
944 return gnm_func_add_placeholder_full (NULL, gname, lname, "?");
945 }
946
947 /**
948 * gnm_func_lookup_or_add_placeholder:
949 * @name: function name
950 *
951 * Returns: (transfer none): a #GnmFunc named @name, either an existing
952 * one or a placeholder.
953 */
954 GnmFunc *
gnm_func_lookup_or_add_placeholder(char const * name)955 gnm_func_lookup_or_add_placeholder (char const *name)
956 {
957 GnmFunc * f = gnm_func_lookup (name, NULL);
958 if (f == NULL)
959 f = gnm_func_add_placeholder (NULL, name, "");
960 return f;
961 }
962
963 /**
964 * gnm_func_get_name:
965 * @func: #GnmFunc to query
966 * @localized: if %TRUE, use localized name
967 *
968 * Returns: (transfer none): @func's name
969 */
970 char const *
gnm_func_get_name(GnmFunc const * func,gboolean localized)971 gnm_func_get_name (GnmFunc const *func, gboolean localized)
972 {
973 int i;
974 GnmFunc *fd = (GnmFunc *)func;
975
976 g_return_val_if_fail (func != NULL, NULL);
977
978 if (!localized)
979 return func->name;
980
981 if (func->localized_name)
982 return func->localized_name;
983
984 /*
985 * Deduce the translated names from the help texts. This
986 * code doesn't currently check for clashes in translated
987 * names.
988 */
989
990 gnm_func_load_if_stub (fd);
991
992 for (i = 0; func->localized_name == NULL && i < func->help_count; i++) {
993 const char *s, *sl;
994 char *U;
995 if (func->help[i].type != GNM_FUNC_HELP_NAME)
996 continue;
997
998 s = func->help[i].text;
999 sl = gnm_func_gettext (fd, s);
1000 if (s == sl) /* String not actually translated. */
1001 continue;
1002
1003 U = split_at_colon (sl, NULL);
1004 if (U) {
1005 char *lname = g_utf8_strdown (U, -1);
1006 gnm_func_set_localized_name (fd, lname);
1007 g_free (lname);
1008 }
1009 g_free (U);
1010 }
1011
1012 if (!func->localized_name)
1013 gnm_func_set_localized_name (fd, fd->name);
1014
1015 return func->localized_name;
1016 }
1017
1018 /**
1019 * gnm_func_get_description:
1020 * @func: #GnmFunc
1021 *
1022 * Returns: (transfer none): the description of the function
1023 **/
1024 char const *
gnm_func_get_description(GnmFunc const * func)1025 gnm_func_get_description (GnmFunc const *func)
1026 {
1027 gint i;
1028 g_return_val_if_fail (func != NULL, NULL);
1029
1030 gnm_func_load_if_stub ((GnmFunc *)func);
1031
1032 for (i = 0; i < func->help_count; i++) {
1033 const char *desc;
1034
1035 if (func->help[i].type != GNM_FUNC_HELP_NAME)
1036 continue;
1037
1038 desc = strchr (gnm_func_gettext (func, func->help[i].text), ':');
1039 return desc ? (desc + 1) : "";
1040 }
1041 return "";
1042 }
1043
1044 /**
1045 * gnm_func_count_args:
1046 * @func: pointer to function definition
1047 * @min: (out): location for minimum args
1048 * @max: (out): location for maximum args
1049 *
1050 * This calculates the maximum and minimum number of args that can be passed.
1051 * For a vararg function, the maximum will be set to G_MAXINT.
1052 **/
1053 void
gnm_func_count_args(GnmFunc const * func,int * min,int * max)1054 gnm_func_count_args (GnmFunc const *func, int *min, int *max)
1055 {
1056 g_return_if_fail (min != NULL);
1057 g_return_if_fail (max != NULL);
1058 g_return_if_fail (func != NULL);
1059
1060 gnm_func_load_if_stub ((GnmFunc *)func);
1061
1062 *min = func->min_args;
1063 *max = func->max_args;
1064 }
1065
1066 /**
1067 * gnm_func_get_arg_type:
1068 * @func: the fn defintion
1069 * @arg_idx: zero-based argument offset
1070 *
1071 * Returns: the type of the argument
1072 **/
1073 char
gnm_func_get_arg_type(GnmFunc const * func,int arg_idx)1074 gnm_func_get_arg_type (GnmFunc const *func, int arg_idx)
1075 {
1076 g_return_val_if_fail (func != NULL, '?');
1077
1078 gnm_func_load_if_stub ((GnmFunc *)func);
1079
1080 g_return_val_if_fail (arg_idx >= 0 && arg_idx < func->max_args, '?');
1081
1082 return func->arg_types ? func->arg_types[arg_idx] : '?';
1083 }
1084
1085 /**
1086 * gnm_func_get_arg_type_string:
1087 * @func: the fn defintion
1088 * @arg_idx: zero-based argument offset
1089 *
1090 * Return value: (transfer none): the type of the argument as a string
1091 **/
1092 char const *
gnm_func_get_arg_type_string(GnmFunc const * func,int arg_idx)1093 gnm_func_get_arg_type_string (GnmFunc const *func, int arg_idx)
1094 {
1095 switch (gnm_func_get_arg_type (func, arg_idx)) {
1096 case 'f':
1097 return _("Number");
1098 case 's':
1099 return _("String");
1100 case 'b':
1101 return _("Boolean");
1102 case 'r':
1103 return _("Cell Range");
1104 case 'A':
1105 return _("Area");
1106 case 'E':
1107 return _("Scalar, Blank, or Error");
1108 case 'S':
1109 return _("Scalar");
1110 case '?':
1111 /* Missing values will be NULL. */
1112 return _("Any");
1113
1114 default:
1115 g_warning ("Unknown arg type");
1116 return "Broken";
1117 }
1118 }
1119
1120 /**
1121 * gnm_func_get_arg_name:
1122 * @func: #GnmFunc
1123 * @arg_idx: zero-based argument offset
1124 *
1125 * Returns: (transfer full) (nullable): the name of the argument
1126 **/
1127 char *
gnm_func_get_arg_name(GnmFunc const * func,guint arg_idx)1128 gnm_func_get_arg_name (GnmFunc const *func, guint arg_idx)
1129 {
1130 g_return_val_if_fail (func != NULL, NULL);
1131
1132 gnm_func_load_if_stub ((GnmFunc *)func);
1133
1134 if (func->arg_names && arg_idx < func->arg_names->len)
1135 return g_strdup (g_ptr_array_index (func->arg_names, arg_idx));
1136 return NULL;
1137 }
1138
1139 /**
1140 * gnm_func_get_arg_description:
1141 * @func: the fn defintion
1142 * @arg_idx: zero-based argument offset
1143 *
1144 * Returns: (transfer none): the description of the argument
1145 **/
1146 char const *
gnm_func_get_arg_description(GnmFunc const * func,guint arg_idx)1147 gnm_func_get_arg_description (GnmFunc const *func, guint arg_idx)
1148 {
1149 gint i;
1150 g_return_val_if_fail (func != NULL, NULL);
1151
1152 gnm_func_load_if_stub ((GnmFunc *)func);
1153
1154 for (i = 0; i < func->help_count; i++) {
1155 gchar const *desc;
1156
1157 if (func->help[i].type != GNM_FUNC_HELP_ARG)
1158 continue;
1159 if (arg_idx--)
1160 continue;
1161
1162 desc = strchr (gnm_func_gettext (func, func->help[i].text), ':');
1163 if (!desc)
1164 return "";
1165
1166 desc++;
1167 while (g_unichar_isspace (g_utf8_get_char (desc)))
1168 desc = g_utf8_next_char (desc);
1169 return desc;
1170 }
1171
1172 return "";
1173 }
1174
1175 /**
1176 * gnm_func_convert_markup_to_pango:
1177 * @desc: the fn or arg description string
1178 * @target: target widget for the markup.
1179 *
1180 * Return value: the escaped string with @{} markup converted to
1181 * pango markup
1182 **/
1183 char *
gnm_func_convert_markup_to_pango(char const * desc,GtkWidget * target)1184 gnm_func_convert_markup_to_pango (char const *desc, GtkWidget *target)
1185 {
1186 GString *str;
1187 gchar *markup, *at;
1188 GdkRGBA link_color;
1189 PangoColor pg;
1190 char *link_color_text, *span_text;
1191 size_t span_text_len;
1192
1193 gnm_get_link_color (target, &link_color);
1194 pg.red = 65535 * link_color.red;
1195 pg.green = 65535 * link_color.green;
1196 pg.blue = 65535 * link_color.blue;
1197 link_color_text = pango_color_to_string (&pg);
1198 span_text = g_strdup_printf ("<span foreground=\"%s\">",
1199 link_color_text);
1200 span_text_len = strlen (span_text);
1201 g_free (link_color_text);
1202
1203 markup = g_markup_escape_text (desc, -1);
1204 str = g_string_new (markup);
1205 g_free (markup);
1206
1207 while ((at = strstr (str->str, "@{"))) {
1208 gint len = at - str->str;
1209 go_string_replace (str, len, 2, span_text, -1);
1210 if ((at = strstr
1211 (str->str + len + span_text_len, "}"))) {
1212 len = at - str->str;
1213 go_string_replace (str, len, 1, "</span>", -1);
1214 } else
1215 g_string_append (str, "</span>");
1216 }
1217 g_free (span_text);
1218
1219 return g_string_free (str, FALSE);
1220 }
1221
1222
1223 /* ------------------------------------------------------------------------- */
1224
1225 static inline void
free_values(GnmValue ** values,int top)1226 free_values (GnmValue **values, int top)
1227 {
1228 int i;
1229
1230 for (i = 0; i < top; i++)
1231 if (values [i])
1232 value_release (values [i]);
1233 }
1234
1235 /* ------------------------------------------------------------------------- */
1236
1237 /**
1238 * function_call_with_exprs:
1239 * @ei: EvalInfo containing valid fn_def!
1240 *
1241 * Do the guts of calling a function.
1242 *
1243 * Returns the result.
1244 **/
1245 GnmValue *
function_call_with_exprs(GnmFuncEvalInfo * ei)1246 function_call_with_exprs (GnmFuncEvalInfo *ei)
1247 {
1248 GnmFunc const *fn_def;
1249 int i, iter_count, iter_width = 0, iter_height = 0;
1250 char arg_type;
1251 GnmValue **args, *tmp = NULL;
1252 int *iter_item = NULL;
1253 int argc;
1254 GnmExprConstPtr *argv;
1255 GnmExprEvalFlags flags, pass_flags;
1256
1257 g_return_val_if_fail (ei != NULL, NULL);
1258 g_return_val_if_fail (ei->func_call != NULL, NULL);
1259
1260 flags = ei->flags;
1261
1262 argc = ei->func_call->argc;
1263 argv = ei->func_call->argv;
1264 fn_def = ei->func_call->func;
1265
1266 gnm_func_load_if_stub ((GnmFunc *)fn_def);
1267
1268 /* Functions that deal with ExprNodes */
1269 if (fn_def->fn_type == GNM_FUNC_TYPE_NODES)
1270 return fn_def->nodes_func (ei, argc, argv);
1271
1272 /* Functions that take pre-computed Values */
1273 if (argc > fn_def->max_args ||
1274 argc < fn_def->min_args)
1275 return value_new_error_NA (ei->pos);
1276
1277 args = g_alloca (sizeof (GnmValue *) * fn_def->max_args);
1278 iter_count = (eval_pos_is_array_context (ei->pos) &&
1279 (flags & GNM_EXPR_EVAL_PERMIT_NON_SCALAR))
1280 ? 0 : -1;
1281
1282 /* Optimization for IF when implicit iteration is not used. */
1283 if (ei->func_call->func == fn_if && iter_count == -1)
1284 return gnumeric_if2 (ei, argc, argv, flags);
1285
1286 pass_flags = (flags & 0); // Nothing right now.
1287
1288 for (i = 0; i < argc; i++) {
1289 char arg_type = fn_def->arg_types[i];
1290 /* expr is always non-null, missing args are encoded as
1291 * const = empty */
1292 GnmExpr const *expr = argv[i];
1293
1294 if (arg_type == 'A' || arg_type == 'r') {
1295 tmp = args[i] = gnm_expr_eval
1296 (expr, ei->pos,
1297 pass_flags |
1298 GNM_EXPR_EVAL_PERMIT_NON_SCALAR |
1299 GNM_EXPR_EVAL_WANT_REF);
1300 if (VALUE_IS_ERROR (tmp)) {
1301 free_values (args, i);
1302 return tmp;
1303 }
1304
1305 if (VALUE_IS_CELLRANGE (tmp)) {
1306 gnm_cellref_make_abs (&tmp->v_range.cell.a,
1307 &tmp->v_range.cell.a,
1308 ei->pos);
1309 gnm_cellref_make_abs (&tmp->v_range.cell.b,
1310 &tmp->v_range.cell.b,
1311 ei->pos);
1312 /* Array args accept scalars */
1313 } else if (arg_type != 'A' && !VALUE_IS_ARRAY (tmp)) {
1314 free_values (args, i + 1);
1315 return value_new_error_VALUE (ei->pos);
1316 }
1317 continue;
1318 }
1319
1320 /* force scalars whenever we are certain */
1321 tmp = args[i] = gnm_expr_eval
1322 (expr, ei->pos,
1323 pass_flags |
1324 GNM_EXPR_EVAL_PERMIT_EMPTY |
1325 (iter_count >= 0 || arg_type == '?'
1326 ? GNM_EXPR_EVAL_PERMIT_NON_SCALAR
1327 : 0));
1328
1329 if (arg_type == '?') /* '?' arguments are unrestriced */
1330 continue;
1331
1332 /* optional arguments can be blank */
1333 if (i >= fn_def->min_args && VALUE_IS_EMPTY (tmp)) {
1334 if (arg_type == 'E' && !gnm_expr_is_empty (expr)) {
1335 /* An actual argument produced empty. Make
1336 sure function sees that. */
1337 args[i] = value_new_empty ();
1338 }
1339
1340 continue;
1341 }
1342
1343 if (tmp == NULL)
1344 tmp = args[i] = value_new_empty ();
1345
1346 /* Handle implicit intersection or iteration depending on flags */
1347 if (VALUE_IS_CELLRANGE (tmp) || VALUE_IS_ARRAY (tmp)) {
1348 if (iter_count > 0) {
1349 if (iter_width != value_area_get_width (tmp, ei->pos) ||
1350 iter_height != value_area_get_height (tmp, ei->pos)) {
1351 free_values (args, i + 1);
1352 return value_new_error_VALUE (ei->pos);
1353 }
1354 } else {
1355 if (iter_count < 0) {
1356 g_warning ("Damn I thought this was impossible");
1357 iter_count = 0;
1358 }
1359 iter_item = g_alloca (sizeof (int) * argc);
1360 iter_width = value_area_get_width (tmp, ei->pos);
1361 iter_height = value_area_get_height (tmp, ei->pos);
1362 }
1363 iter_item [iter_count++] = i;
1364
1365 /* no need to check type, we would fail comparing a range against a "b, f, or s" */
1366 continue;
1367 }
1368
1369 /* All of these argument types must be scalars */
1370 switch (arg_type) {
1371 case 'b':
1372 if (VALUE_IS_STRING (tmp)) {
1373 gboolean err;
1374 gboolean b = value_get_as_bool (tmp, &err);
1375 if (err) {
1376 free_values (args, i + 1);
1377 return value_new_error_VALUE (ei->pos);
1378 }
1379 value_release (args[i]);
1380 tmp = args[i] = value_new_bool (b);
1381 break;
1382 }
1383 /* Fall through. */
1384 case 'f':
1385 if (VALUE_IS_STRING (tmp)) {
1386 tmp = format_match_number (value_peek_string (tmp), NULL,
1387 sheet_date_conv (ei->pos->sheet));
1388 if (tmp == NULL) {
1389 free_values (args, i + 1);
1390 return value_new_error_VALUE (ei->pos);
1391 }
1392 value_release (args [i]);
1393 args[i] = tmp;
1394 } else if (VALUE_IS_ERROR (tmp)) {
1395 free_values (args, i);
1396 return tmp;
1397 } else if (VALUE_IS_EMPTY (tmp)) {
1398 value_release (args [i]);
1399 tmp = args[i] = value_new_int (0);
1400 }
1401
1402 if (!VALUE_IS_NUMBER (tmp))
1403 return value_new_error_VALUE (ei->pos);
1404 break;
1405
1406 case 's':
1407 case 'S':
1408 if (VALUE_IS_ERROR (tmp)) {
1409 free_values (args, i);
1410 return tmp;
1411 }
1412 break;
1413
1414 case 'E': /* nothing necessary */
1415 break;
1416
1417 /* case '?': handled above */
1418 default:
1419 g_warning ("Unknown argument type '%c'", arg_type);
1420 break;
1421 }
1422 }
1423
1424 while (i < fn_def->max_args)
1425 args [i++] = NULL;
1426
1427 if (iter_item != NULL) {
1428 int x, y;
1429 GnmValue *res = value_new_array_empty (iter_width, iter_height);
1430 GnmValue const *elem, *err;
1431 GnmValue **iter_vals = g_alloca (sizeof (GnmValue *) * iter_count);
1432 GnmValue **iter_args = g_alloca (sizeof (GnmValue *) * iter_count);
1433
1434 /* collect the args we will iterate on */
1435 for (i = 0 ; i < iter_count; i++)
1436 iter_vals[i] = args[iter_item[i]];
1437
1438 for (x = iter_width; x-- > 0 ; )
1439 for (y = iter_height; y-- > 0 ; ) {
1440 /* marshal the args */
1441 err = NULL;
1442 for (i = 0 ; i < iter_count; i++) {
1443 elem = value_area_get_x_y (iter_vals[i], x, y, ei->pos);
1444 arg_type = fn_def->arg_types[iter_item[i]];
1445 if (arg_type == 'b' || arg_type == 'f') {
1446 if (VALUE_IS_EMPTY (elem))
1447 elem = value_zero;
1448 else if (VALUE_IS_STRING (elem)) {
1449 tmp = format_match_number (value_peek_string (elem), NULL,
1450 sheet_date_conv (ei->pos->sheet));
1451 if (tmp != NULL) {
1452 args [iter_item[i]] = iter_args [i] = tmp;
1453 continue;
1454 } else
1455 break;
1456 } else if (VALUE_IS_ERROR (elem)) {
1457 err = elem;
1458 break;
1459 } else if (!VALUE_IS_NUMBER (elem))
1460 break;
1461 } else if (arg_type == 's') {
1462 if (VALUE_IS_EMPTY (elem)) {
1463 args [iter_item[i]] = iter_args [i] = value_new_string ("");
1464 continue;
1465 } else if (VALUE_IS_ERROR (elem)) {
1466 err = elem;
1467 break;
1468 } else if (!VALUE_IS_STRING (elem))
1469 break;
1470 } else if (elem == NULL) {
1471 args [iter_item[i]] = iter_args [i] = value_new_empty ();
1472 continue;
1473 }
1474 args [iter_item[i]] = iter_args [i] = value_dup (elem);
1475 }
1476
1477 res->v_array.vals[x][y] = (i == iter_count)
1478 ? fn_def->args_func (ei, (GnmValue const * const *)args)
1479 : ((err != NULL) ? value_dup (err)
1480 : value_new_error_VALUE (ei->pos));
1481 free_values (iter_args, i);
1482 }
1483
1484 /* free the primaries, not the already freed iteration */
1485 for (i = 0 ; i < iter_count; i++)
1486 args[iter_item[i]] = iter_vals[i];
1487 tmp = res;
1488 i = fn_def->max_args;
1489 } else
1490 tmp = fn_def->args_func (ei, (GnmValue const * const *)args);
1491
1492 free_values (args, i);
1493 return tmp;
1494 }
1495
1496 /*
1497 * Use this to invoke a register function: the only drawback is that
1498 * you have to compute/expand all of the values to use this
1499 */
1500 GnmValue *
function_call_with_values(GnmEvalPos const * ep,char const * fn_name,int argc,GnmValue const * const * values)1501 function_call_with_values (GnmEvalPos const *ep, char const *fn_name,
1502 int argc, GnmValue const * const *values)
1503 {
1504 GnmFunc *fn_def;
1505
1506 g_return_val_if_fail (ep != NULL, NULL);
1507 g_return_val_if_fail (fn_name != NULL, NULL);
1508 g_return_val_if_fail (ep->sheet != NULL, NULL);
1509
1510 /* FIXME : support workbook local functions */
1511 fn_def = gnm_func_lookup (fn_name, NULL);
1512 if (fn_def == NULL)
1513 return value_new_error_NAME (ep);
1514 return function_def_call_with_values (ep, fn_def, argc, values);
1515 }
1516
1517 GnmValue *
function_def_call_with_values(GnmEvalPos const * ep,GnmFunc const * fn_def,int argc,GnmValue const * const * values)1518 function_def_call_with_values (GnmEvalPos const *ep, GnmFunc const *fn_def,
1519 int argc, GnmValue const * const *values)
1520 {
1521 GnmValue *retval;
1522 GnmExprFunction ef;
1523 GnmFuncEvalInfo fs;
1524
1525 fs.pos = ep;
1526 fs.func_call = &ef;
1527 ef.func = (GnmFunc *)fn_def;
1528
1529 gnm_func_load_if_stub (ef.func);
1530
1531 if (fn_def->fn_type == GNM_FUNC_TYPE_NODES) {
1532 /*
1533 * If function deals with ExprNodes, create some
1534 * temporary ExprNodes with constants.
1535 */
1536 GnmExprConstant *expr = g_new (GnmExprConstant, argc);
1537 GnmExprConstPtr *argv = g_new (GnmExprConstPtr, argc);
1538 int i;
1539
1540 for (i = 0; i < argc; i++) {
1541 gnm_expr_constant_init (expr + i, values[i]);
1542 argv[i] = (GnmExprConstPtr)(expr + i);
1543 }
1544 retval = fn_def->nodes_func (&fs, argc, argv);
1545 g_free (argv);
1546 g_free (expr);
1547 } else
1548 retval = fn_def->args_func (&fs, values);
1549
1550 return retval;
1551 }
1552
1553 /* ------------------------------------------------------------------------- */
1554
1555 typedef struct {
1556 FunctionIterateCB callback;
1557 void *closure;
1558 gboolean strict;
1559 gboolean ignore_subtotal;
1560 } IterateCallbackClosure;
1561
1562 /**
1563 * cb_iterate_cellrange:
1564 *
1565 * Helper routine used by the function_iterate_do_value routine.
1566 * Invoked by the sheet cell range iterator.
1567 **/
1568 static GnmValue *
cb_iterate_cellrange(GnmCellIter const * iter,gpointer user)1569 cb_iterate_cellrange (GnmCellIter const *iter, gpointer user)
1570
1571 {
1572 IterateCallbackClosure *data = user;
1573 GnmCell *cell;
1574 GnmValue *res;
1575 GnmEvalPos ep;
1576
1577 if (NULL == (cell = iter->cell)) {
1578 ep.sheet = iter->pp.sheet;
1579 ep.dep = NULL;
1580 ep.eval.col = iter->pp.eval.col;
1581 ep.eval.row = iter->pp.eval.row;
1582 return (*data->callback)(&ep, NULL, data->closure);
1583 }
1584
1585 if (data->ignore_subtotal && gnm_cell_has_expr (cell) &&
1586 gnm_expr_top_contains_subtotal (cell->base.texpr))
1587 return NULL;
1588
1589 gnm_cell_eval (cell);
1590 eval_pos_init_cell (&ep, cell);
1591
1592 /* If we encounter an error for the strict case, short-circuit here. */
1593 if (data->strict && (NULL != (res = gnm_cell_is_error (cell))))
1594 return value_new_error_str (&ep, res->v_err.mesg);
1595
1596 /* All other cases -- including error -- just call the handler. */
1597 return (*data->callback)(&ep, cell->value, data->closure);
1598 }
1599
1600 /*
1601 * function_iterate_do_value:
1602 *
1603 * Helper routine for function_iterate_argument_values.
1604 */
1605 static GnmValue *
function_iterate_do_value(GnmEvalPos const * ep,FunctionIterateCB callback,gpointer closure,GnmValue const * value,gboolean strict,CellIterFlags iter_flags)1606 function_iterate_do_value (GnmEvalPos const *ep,
1607 FunctionIterateCB callback,
1608 gpointer closure,
1609 GnmValue const *value,
1610 gboolean strict,
1611 CellIterFlags iter_flags)
1612 {
1613 GnmValue *res = NULL;
1614
1615 switch (value->v_any.type){
1616 case VALUE_ERROR:
1617 if (strict) {
1618 res = value_dup (value);
1619 break;
1620 }
1621 /* Fall through. */
1622
1623 case VALUE_EMPTY:
1624 case VALUE_BOOLEAN:
1625 case VALUE_FLOAT:
1626 case VALUE_STRING:
1627 res = (*callback)(ep, value, closure);
1628 break;
1629
1630 case VALUE_ARRAY: {
1631 int x, y;
1632
1633 /* Note the order here. */
1634 for (y = 0; y < value->v_array.y; y++) {
1635 for (x = 0; x < value->v_array.x; x++) {
1636 res = function_iterate_do_value (
1637 ep, callback, closure,
1638 value->v_array.vals [x][y],
1639 strict, CELL_ITER_IGNORE_BLANK);
1640 if (res != NULL)
1641 return res;
1642 }
1643 }
1644 break;
1645 }
1646 case VALUE_CELLRANGE: {
1647 IterateCallbackClosure data;
1648
1649 data.callback = callback;
1650 data.closure = closure;
1651 data.strict = strict;
1652 data.ignore_subtotal = (iter_flags & CELL_ITER_IGNORE_SUBTOTAL) != 0;
1653
1654 res = workbook_foreach_cell_in_range (ep, value, iter_flags,
1655 cb_iterate_cellrange,
1656 &data);
1657 }
1658 }
1659 return res;
1660 }
1661
1662 /**
1663 * function_iterate_argument_values:
1664 * @ep: The position in a workbook at which to evaluate
1665 * @callback: (scope call): The routine to be invoked for every value computed
1666 * @callback_closure: Closure for the callback.
1667 * @argc:
1668 * @argv:
1669 * @strict: If TRUE, the function is considered "strict". This means
1670 * that if an error value occurs as an argument, the iteration
1671 * will stop and that error will be returned. If FALSE, an
1672 * error will be passed on to the callback (as a GnmValue *
1673 * of type VALUE_ERROR).
1674 * @iter_flags:
1675 *
1676 * Return value:
1677 * NULL : if no errors were reported.
1678 * GnmValue * : if an error was found during strict evaluation
1679 * VALUE_TERMINATE : if the callback requested termination of the iteration.
1680 *
1681 * This routine provides a simple way for internal functions with variable
1682 * number of arguments to be written: this would iterate over a list of
1683 * expressions (expr_node_list) and will invoke the callback for every
1684 * GnmValue found on the list (this means that ranges get properly expanded).
1685 **/
1686 GnmValue *
function_iterate_argument_values(GnmEvalPos const * ep,FunctionIterateCB callback,void * callback_closure,int argc,GnmExprConstPtr const * argv,gboolean strict,CellIterFlags iter_flags)1687 function_iterate_argument_values (GnmEvalPos const *ep,
1688 FunctionIterateCB callback,
1689 void *callback_closure,
1690 int argc,
1691 GnmExprConstPtr const *argv,
1692 gboolean strict,
1693 CellIterFlags iter_flags)
1694 {
1695 GnmValue *result = NULL;
1696 int a;
1697
1698 for (a = 0; result == NULL && a < argc; a++) {
1699 GnmExpr const *expr = argv[a];
1700 GnmValue *val;
1701
1702 if (iter_flags & CELL_ITER_IGNORE_SUBTOTAL &&
1703 gnm_expr_contains_subtotal (expr))
1704 continue;
1705
1706 /* need to drill down into names to handle things like
1707 * sum(name) with name := (A:A,B:B) */
1708 while (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_NAME) {
1709 GnmExprTop const *texpr = expr->name.name->texpr;
1710 expr = texpr ? texpr->expr : NULL;
1711 if (expr == NULL) {
1712 if (strict)
1713 return value_new_error_REF (ep);
1714 break;
1715 }
1716 }
1717 if (!expr)
1718 continue;
1719
1720 /* Handle sets as a special case */
1721 if (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_SET) {
1722 result = function_iterate_argument_values
1723 (ep, callback, callback_closure,
1724 expr->set.argc, expr->set.argv,
1725 strict, iter_flags);
1726 continue;
1727 }
1728
1729 /* We need a cleaner model of what to do here.
1730 * In non-array mode
1731 * SUM(Range)
1732 * will obviously return Range
1733 *
1734 * SUM(INDIRECT(Range))
1735 * SUM(INDIRECT(Range):....)
1736 * will do implicit intersection on Range (in non-array mode),
1737 * but allow non-scalar results from indirect (no intersection)
1738 *
1739 * SUM(Range=3)
1740 * will do implicit intersection in non-array mode */
1741 if (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_CONSTANT)
1742 val = value_dup (expr->constant.value);
1743 else if (eval_pos_is_array_context (ep) ||
1744 GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_FUNCALL ||
1745 GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_RANGE_CTOR ||
1746 GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_INTERSECT)
1747 val = gnm_expr_eval (expr, ep,
1748 GNM_EXPR_EVAL_PERMIT_EMPTY | GNM_EXPR_EVAL_PERMIT_NON_SCALAR);
1749 else
1750 val = gnm_expr_eval (expr, ep, GNM_EXPR_EVAL_PERMIT_EMPTY);
1751
1752 if (val == NULL)
1753 continue;
1754
1755 if (strict && VALUE_IS_ERROR (val)) {
1756 /* Be careful not to make VALUE_TERMINATE into a real value */
1757 return val;
1758 }
1759
1760 result = function_iterate_do_value (ep, callback, callback_closure,
1761 val, strict, iter_flags);
1762 value_release (val);
1763 }
1764 return result;
1765 }
1766
1767
1768 /**
1769 * gnm_eval_info_get_func:
1770 * @ei: #GnmFuncEvalInfo
1771 *
1772 * Returns: (transfer none): the called function.
1773 */
1774 GnmFunc const *
gnm_eval_info_get_func(GnmFuncEvalInfo const * ei)1775 gnm_eval_info_get_func (GnmFuncEvalInfo const *ei)
1776 {
1777 return ei->func_call->func;
1778 }
1779
1780 int
gnm_eval_info_get_arg_count(GnmFuncEvalInfo const * ei)1781 gnm_eval_info_get_arg_count (GnmFuncEvalInfo const *ei)
1782 {
1783 return ei->func_call->argc;
1784 }
1785
1786 GnmDependentFlags
gnm_func_link_dep(GnmFunc * func,GnmFuncEvalInfo * ei,gboolean qlink)1787 gnm_func_link_dep (GnmFunc *func, GnmFuncEvalInfo *ei, gboolean qlink)
1788 {
1789 int res = DEPENDENT_NO_FLAG;
1790 g_signal_emit (func, signals[SIG_LINK_DEP], 0, ei, qlink, &res);
1791 return (GnmDependentFlags)res;
1792 }
1793
1794 /**
1795 * gnm_func_derivative:
1796 * @func: #GnmFunc
1797 * @expr: expression that calls @func
1798 * @ep: position of @expr
1799 * @info: #GnmExprDeriv
1800 *
1801 * Returns: (transfer full) (nullable): the derivative of @expr with respect to
1802 * @info.
1803 */
1804 GnmExpr const *
gnm_func_derivative(GnmFunc * func,GnmExpr const * expr,GnmEvalPos const * ep,GnmExprDeriv * info)1805 gnm_func_derivative (GnmFunc *func, GnmExpr const *expr, GnmEvalPos const *ep,
1806 GnmExprDeriv *info)
1807 {
1808 GnmExpr *res = NULL;
1809
1810 g_return_val_if_fail (GNM_IS_FUNC (func), NULL);
1811 g_signal_emit (func, signals[SIG_DERIVATIVE], 0, expr, ep, info, &res);
1812 return res;
1813 }
1814
1815 /* ------------------------------------------------------------------------- */
1816
1817 static GObjectClass *parent_class;
1818
1819 typedef struct {
1820 GObjectClass parent;
1821
1822 void (*load_stub) (GnmFunc *func);
1823 int (*link_dep) (GnmFunc *func, GnmFuncEvalInfo *ei, gboolean qlink);
1824 GnmExpr* (*derivative) (GnmFunc *func, GnmExpr const *expr, GnmEvalPos *ep, GnmExprDeriv *info);
1825 } GnmFuncClass;
1826
1827 static void
gnm_func_finalize(GObject * obj)1828 gnm_func_finalize (GObject *obj)
1829 {
1830 GnmFunc *func = GNM_FUNC (obj);
1831
1832 g_free (func->arg_types);
1833
1834 g_free ((char *)func->name);
1835
1836 go_string_unref (func->tdomain);
1837
1838 parent_class->finalize (obj);
1839 }
1840
1841 static void
gnm_func_real_dispose(GObject * obj)1842 gnm_func_real_dispose (GObject *obj)
1843 {
1844 GnmFunc *func = GNM_FUNC (obj);
1845
1846 if (func->usage_count != 0) {
1847 g_printerr ("Function %s still has a usage count of %d\n",
1848 func->name, func->usage_count);
1849 }
1850
1851 gnm_func_set_stub (func);
1852
1853 if (func->fn_group) {
1854 gnm_func_group_remove_func (func->fn_group, func);
1855 func->fn_group = NULL;
1856 }
1857
1858 gnm_func_set_localized_name (func, NULL);
1859
1860 if (!(func->flags & GNM_FUNC_IS_WORKBOOK_LOCAL)) {
1861 g_hash_table_remove (functions_by_name, func->name);
1862 }
1863
1864 parent_class->dispose (obj);
1865 }
1866
1867 void
gnm_func_dispose(GnmFunc * func)1868 gnm_func_dispose (GnmFunc *func)
1869 {
1870 g_object_run_dispose (G_OBJECT (func));
1871 }
1872
1873 static void
gnm_func_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)1874 gnm_func_get_property (GObject *object, guint property_id,
1875 GValue *value, GParamSpec *pspec)
1876 {
1877 GnmFunc *func = (GnmFunc *)object;
1878
1879 switch (property_id) {
1880 case PROP_NAME:
1881 g_value_set_string (value, func->name);
1882 break;
1883 case PROP_TRANSLATION_DOMAIN:
1884 g_value_set_string (value, func->tdomain->str);
1885 break;
1886 case PROP_IN_USE:
1887 g_value_set_boolean (value, func->usage_count > 0);
1888 break;
1889 default:
1890 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1891 break;
1892 }
1893 }
1894
1895 static void
gnm_func_set_property(GObject * object,guint property_id,GValue const * value,GParamSpec * pspec)1896 gnm_func_set_property (GObject *object, guint property_id,
1897 GValue const *value, GParamSpec *pspec)
1898 {
1899 GnmFunc *func = (GnmFunc *)object;
1900
1901 switch (property_id) {
1902 case PROP_NAME:
1903 func->name = g_value_dup_string (value);
1904 break;
1905 case PROP_TRANSLATION_DOMAIN:
1906 gnm_func_set_translation_domain (func,
1907 g_value_get_string (value));
1908 break;
1909 default:
1910 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1911 break;
1912 }
1913 }
1914
1915 static void
gnm_func_init(GnmFunc * func)1916 gnm_func_init (GnmFunc *func)
1917 {
1918 func->tdomain = go_string_new (GETTEXT_PACKAGE);
1919 func->flags = GNM_FUNC_SIMPLE;
1920 func->impl_status = GNM_FUNC_IMPL_STATUS_UNIMPLEMENTED;
1921 func->test_status = GNM_FUNC_TEST_STATUS_UNKNOWN;
1922 }
1923
1924 static void
gnm_func_class_init(GObjectClass * gobject_class)1925 gnm_func_class_init (GObjectClass *gobject_class)
1926 {
1927 parent_class = g_type_class_peek_parent (gobject_class);
1928
1929 gobject_class->finalize = gnm_func_finalize;
1930 gobject_class->dispose = gnm_func_real_dispose;
1931 gobject_class->get_property = gnm_func_get_property;
1932 gobject_class->set_property = gnm_func_set_property;
1933
1934 g_object_class_install_property (gobject_class, PROP_NAME,
1935 g_param_spec_string ("name",
1936 P_("Name"),
1937 P_("The name of the function."),
1938 NULL,
1939 GSF_PARAM_STATIC |
1940 G_PARAM_READWRITE |
1941 G_PARAM_CONSTRUCT_ONLY));
1942
1943 g_object_class_install_property (gobject_class, PROP_TRANSLATION_DOMAIN,
1944 g_param_spec_string ("translation-domain",
1945 P_("Translation Domain"),
1946 P_("The translation domain for help texts"),
1947 NULL,
1948 GSF_PARAM_STATIC |
1949 G_PARAM_READWRITE));
1950
1951 g_object_class_install_property (gobject_class, PROP_IN_USE,
1952 g_param_spec_boolean ("in-use",
1953 P_("In use"),
1954 P_("Is function being used?"),
1955 FALSE,
1956 GSF_PARAM_STATIC |
1957 G_PARAM_READABLE));
1958
1959 /**
1960 * GnmFunc::load-stub:
1961 * @func: the #GnmFunc that needs to be loaded
1962 *
1963 * Signals that @func, which is a stub, needs to be loaded now. Anyone
1964 * creating a stub function should arrange for this signal to be caught
1965 * and the function to be properly instantiated.
1966 */
1967 signals[SIG_LOAD_STUB] = g_signal_new
1968 ("load-stub",
1969 GNM_FUNC_TYPE,
1970 G_SIGNAL_RUN_LAST,
1971 G_STRUCT_OFFSET (GnmFuncClass, load_stub),
1972 NULL, NULL,
1973 g_cclosure_marshal_VOID__VOID,
1974 G_TYPE_NONE, 0);
1975
1976 /**
1977 * GnmFunc::link-dep:
1978 * @func: the #GnmFunc that is being linked or unlinked
1979 * @ei: #GnmFuncEvalInfo for the call initiating the link or unlink.
1980 * @qlink: %TRUE for link, %FALSE for unlink
1981 *
1982 * Signals that an expressions that is a call to @func is being linked
1983 * or unlinked. Most functions do not need this.
1984 *
1985 * Returns: A #GnmDependentFlags allowing arguments not be be linked if
1986 * that is appropriate.
1987 */
1988 signals[SIG_LINK_DEP] = g_signal_new
1989 ("link-dep",
1990 GNM_FUNC_TYPE,
1991 G_SIGNAL_RUN_LAST,
1992 G_STRUCT_OFFSET (GnmFuncClass, link_dep),
1993 NULL, NULL,
1994 gnm__INT__POINTER_BOOLEAN,
1995 // GnmDependentFlags ... GnmFuncEvalInfo
1996 G_TYPE_INT, 2, G_TYPE_POINTER, G_TYPE_BOOLEAN);
1997
1998 /**
1999 * GnmFunc::derivative:
2000 * @func: #GnmFunc
2001 * @expr: #GnmExpr for the call for which the derivative is sought
2002 * @ep: position f @expr
2003 * @info: #GnmExprDeriv telling which derivative is sought
2004 *
2005 * Signals that a function call's derivative should be calculated
2006 *
2007 * Returns: (transfer full) (nullable): #GnmExpr representing the
2008 * derivative, %NULL for error.
2009 */
2010 signals[SIG_DERIVATIVE] = g_signal_new
2011 ("derivative",
2012 GNM_FUNC_TYPE,
2013 G_SIGNAL_RUN_LAST,
2014 G_STRUCT_OFFSET (GnmFuncClass, derivative),
2015 NULL, NULL,
2016 gnm__BOXED__BOXED_BOXED_BOXED,
2017 gnm_expr_get_type(),
2018 3, gnm_expr_get_type(), gnm_eval_pos_get_type(), gnm_expr_deriv_info_get_type());
2019 }
2020
2021 GSF_CLASS (GnmFunc, gnm_func,
2022 gnm_func_class_init, gnm_func_init, G_TYPE_OBJECT)
2023