3 #include "perl-gnumeric.h"
5 #define _perl_dirty dirty
8 #include <gnumeric-config.h>
9 #include "perl-loader.h"
12 #include <application.h>
13 #include <workbook-view.h>
18 #include <gnm-plugin.h>
20 #include <goffice/goffice.h>
21 #include <goffice/app/module-plugin-defs.h>
22 #include <gsf/gsf-impl-utils.h>
24 #include <glib/gi18n-lib.h>
27 #define TYPE_GNM_PERL_PLUGIN_LOADER (gnm_perl_plugin_loader_get_type ())
28 #define GNM_PERL_PLUGIN_LOADER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TYPE_GNM_PERL_PLUGIN_LOADER, GnmPerlPluginLoader))
29 #define GNM_IS_PERL_PLUGIN_LOADER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TYPE_GNM_PERL_PLUGIN_LOADER))
31 #define dirty _perl_dirty
34 extern void xs_init(pTHX
);
36 static PerlInterpreter
* gnm_perl_interp
;
37 static PerlInterpreter
* my_perl
;
42 } GnmPerlPluginLoader
;
43 typedef GObjectClass GnmPerlPluginLoaderClass
;
46 call_perl_function_args (GnmFuncEvalInfo
*ei
, GnmValue
const * const *args
)
49 gint min_n_args
, max_n_args
, n_args
;
55 fndef
= gnm_expr_get_func_def ((GnmExpr
*)(ei
->func_call
));
56 perl_func
= g_strconcat ("func_", fndef
->name
, NULL
);
58 gnm_func_count_args (fndef
, &min_n_args
, &max_n_args
);
59 for (n_args
= min_n_args
; n_args
< max_n_args
&& args
[n_args
] != NULL
; n_args
++);
64 for (i
= 0; i
< n_args
; i
++) {
65 SV
* sv
= value2perl (args
[i
]);
66 XPUSHs(sv_2mortal(sv
));
69 call_pv (perl_func
, G_EVAL
| G_SCALAR
);
72 if (SvTRUE(ERRSV
)) { /* Error handling */
75 errmsg
= g_strconcat (_("Perl error: "), SvPV (ERRSV
, n_a
), NULL
);
78 result
= value_new_error (ei
->pos
, errmsg
);
81 result
= perl2value (POPs
);
94 init_help_consts (void)
96 /* Export our constants as global variables. */
101 { "GNM_FUNC_HELP_NAME", GNM_FUNC_HELP_NAME
},
102 { "GNM_FUNC_HELP_ARG", GNM_FUNC_HELP_ARG
},
103 { "GNM_FUNC_HELP_DESCRIPTION", GNM_FUNC_HELP_DESCRIPTION
},
104 { "GNM_FUNC_HELP_NOTE", GNM_FUNC_HELP_NOTE
},
105 { "GNM_FUNC_HELP_EXAMPLES", GNM_FUNC_HELP_EXAMPLES
},
106 { "GNM_FUNC_HELP_SEEALSO", GNM_FUNC_HELP_SEEALSO
},
107 { "GNM_FUNC_HELP_EXTREF", GNM_FUNC_HELP_EXTREF
},
108 { "GNM_FUNC_HELP_EXCEL", GNM_FUNC_HELP_EXCEL
},
109 { "GNM_FUNC_HELP_ODF", GNM_FUNC_HELP_ODF
}
113 for (ui
= 0; ui
< G_N_ELEMENTS (consts
); ui
++) {
114 SV
* x
= get_sv (consts
[ui
].name
, TRUE
);
115 sv_setiv (x
, consts
[ui
].value
);
119 static const char help_template_text
[] =
120 "This Perl function hasn't been documented.";
122 static const GnmFuncHelp help_template
[] = {
123 { GNM_FUNC_HELP_NAME
, NULL
},
124 { GNM_FUNC_HELP_DESCRIPTION
, NULL
},
125 { GNM_FUNC_HELP_END
}
129 default_gnm_help(const char *name
)
131 GnmFuncHelp
*help
= g_new0 (GnmFuncHelp
, 3);
134 for (i
= 0; i
< 3; i
++)
135 help
[i
] = help_template
[i
];
136 help
[0].text
= g_strdup_printf ("%s:", name
);
137 help
[1].text
= g_strdup (help_template_text
);
143 make_gnm_help (const char *name
, int count
, SV
**SP
)
145 GnmFuncHelp
*help
= NULL
;
146 /* We assume that the description is a Perl array of the form
147 (key, text, key, text, ...). */
148 int n
= count
/ 2, m
= 0, k
, type
= GNM_FUNC_HELP_END
;
149 GnmFuncHelp
*helptmp
= g_new0 (GnmFuncHelp
, n
+ 1);
150 if (count
% 2) POPs
, count
--;
151 for (k
= n
; k
-- > 0; ) {
156 tmp
= SvPV(sv
, size
);
157 helptmp
[k
].text
= g_strndup (tmp
, size
);
159 helptmp
[k
].text
= NULL
;
162 if (SvIOK(sv
)) type
= SvIV(sv
);
163 if (helptmp
[k
].text
&&
164 type
>= GNM_FUNC_HELP_NAME
&& GNM_FUNC_HELP_ODF
) {
165 helptmp
[k
].type
= type
; m
++;
167 helptmp
[k
].type
= GNM_FUNC_HELP_END
;
169 g_free ((char*)helptmp
[k
].text
);
170 helptmp
[k
].text
= NULL
;
174 /* No valid entries. */
177 /* Collect all valid entries in a new array. */
182 help
= g_new (GnmFuncHelp
, m
+1);
183 for (i
= 0, k
= 0; k
< n
; k
++)
184 if (helptmp
[k
].type
!= GNM_FUNC_HELP_END
&&
186 help
[i
++] = helptmp
[k
];
189 help
[m
].type
= GNM_FUNC_HELP_END
;
192 if (!help
) /* Provide a reasonable default. */
193 help
= default_gnm_help (name
);
195 gnm_perl_loader_free_later (help
);
196 for (n
= 0; help
[n
].type
!= GNM_FUNC_HELP_END
; n
++)
197 gnm_perl_loader_free_later (help
[n
].text
);
203 gplp_func_desc_load (GOPluginService
*service
,
205 GnmFuncDescriptor
*res
)
207 char *args
[] = { NULL
};
208 gchar
*help_perl_func
= g_strconcat ("help_", name
, NULL
);
209 gchar
*desc_perl_func
= g_strconcat ("desc_", name
, NULL
);
210 GnmFuncHelp
*help
= NULL
;
211 gchar
*arg_spec
= NULL
;
219 count
= call_argv (help_perl_func
, G_EVAL
| G_ARRAY
| G_NOARGS
, args
);
222 if (SvTRUE(ERRSV
)) { /* Error handling */
224 g_print ( _("Perl error: %s\n"), SvPV (ERRSV
, n_a
));
225 while (count
-- > 0) POPs
;
227 help
= make_gnm_help(name
, count
, SP
);
238 call_argv (desc_perl_func
, G_EVAL
| G_ARRAY
| G_NOARGS
, args
);
241 if (SvTRUE(ERRSV
)) { /* Error handling */
243 g_print ( _("Perl error: %s\n"), SvPV (ERRSV
, n_a
));
246 arg_spec
= g_strdup (POPp
);
247 gnm_perl_loader_free_later (arg_spec
);
254 g_free (help_perl_func
);
255 g_free (desc_perl_func
);
257 res
->name
= g_strdup(name
);
258 res
->arg_spec
= arg_spec
;
262 res
->fn_args
= &call_perl_function_args
;
263 res
->fn_nodes
= NULL
;
265 res
->impl_status
= GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC
;
266 res
->test_status
= GNM_FUNC_TEST_STATUS_UNKNOWN
;
272 gplp_set_attributes (GOPluginLoader
*loader
, GHashTable
*attrs
, GOErrorInfo
**ret_error
)
274 GnmPerlPluginLoader
*loader_perl
= GNM_PERL_PLUGIN_LOADER (loader
);
276 gchar
*module_name
= NULL
;
278 GO_INIT_RET_ERROR_INFO (ret_error
);
279 module_name
= g_hash_table_lookup (attrs
, "module_name");
281 loader_perl
->module_name
= g_strdup (module_name
);
283 *ret_error
= go_error_info_new_str (
284 _("Module name not given."));
289 gplp_load_base (GOPluginLoader
*loader
, GOErrorInfo
**ret_error
)
291 char *argv
[] = { (char*)"", NULL
, NULL
, NULL
};
295 arg
= go_plugin_get_dir_name (go_plugin_loader_get_plugin (loader
));
296 argv
[1] = g_strconcat ("-I", arg
, NULL
);
297 argv
[2] = g_build_filename (arg
, "perl_func.pl", NULL
);
300 if (g_file_test (argv
[2], G_FILE_TEST_EXISTS
)) {
301 PERL_SYS_INIT3 (&argc
, (char ***)&argv
, NULL
);
302 gnm_perl_interp
= perl_alloc ();
303 perl_construct (gnm_perl_interp
);
304 perl_parse (gnm_perl_interp
, xs_init
, 3, argv
, NULL
);
305 my_perl
= gnm_perl_interp
;
307 #ifdef PERL_EXIT_DESTRUCT_END
308 PL_exit_flags
|= PERL_EXIT_DESTRUCT_END
;
311 *ret_error
= go_error_info_new_printf (
312 _("perl_func.pl doesn't exist."));
320 gplp_load_service_function_group (GOPluginLoader
*loader
,
321 GOPluginService
*service
,
322 GOErrorInfo
**ret_error
)
324 GnmPluginServiceFunctionGroupCallbacks
*cbs
;
326 g_return_if_fail (GNM_IS_PLUGIN_SERVICE_FUNCTION_GROUP (service
));
328 GO_INIT_RET_ERROR_INFO (ret_error
);
330 cbs
= go_plugin_service_get_cbs (service
);
331 cbs
->func_desc_load
= &gplp_func_desc_load
;
335 gplp_service_load (GOPluginLoader
*l
, GOPluginService
*s
, GOErrorInfo
**err
)
337 if (GNM_IS_PLUGIN_SERVICE_FUNCTION_GROUP (s
))
338 gplp_load_service_function_group (l
, s
, err
);
345 gplp_service_unload (GOPluginLoader
*l
, GOPluginService
*s
, GOErrorInfo
**err
)
347 if (GNM_IS_PLUGIN_SERVICE_FUNCTION_GROUP (s
))
355 gplp_finalize (GObject
*obj
)
357 GnmPerlPluginLoader
*loader_perl
= GNM_PERL_PLUGIN_LOADER (obj
);
359 g_free (loader_perl
->module_name
);
360 loader_perl
->module_name
= NULL
;
362 G_OBJECT_CLASS (g_type_class_peek (G_TYPE_OBJECT
))->finalize (obj
);
366 go_plugin_loader_init (GOPluginLoaderClass
*iface
)
368 iface
->set_attributes
= gplp_set_attributes
;
369 iface
->load_base
= gplp_load_base
;
371 iface
->service_load
= gplp_service_load
;
372 iface
->service_unload
= gplp_service_unload
;
376 gplp_class_init (GObjectClass
*gobject_class
)
378 gobject_class
->finalize
= gplp_finalize
;
382 gplp_init (GnmPerlPluginLoader
*loader_perl
)
384 g_return_if_fail (GNM_IS_PERL_PLUGIN_LOADER (loader_perl
));
386 loader_perl
->module_name
= NULL
;
389 GSF_DYNAMIC_CLASS_FULL (GnmPerlPluginLoader
, gnm_perl_plugin_loader
,
390 NULL
, NULL
, gplp_class_init
, NULL
,
391 gplp_init
, G_TYPE_OBJECT
, 0,
392 GSF_INTERFACE_FULL (gnm_perl_plugin_loader_type
, go_plugin_loader_init
, GO_TYPE_PLUGIN_LOADER
))