1 //=============================================================================
2 //
3 // File : libkviperl.cpp
4 // Creation date : Tue Jul 13 13:03:31 2004 GMT by Szymon Stefanek
5 //
6 // This file is part of the KVIrc IRC client distribution
7 // Copyright (C) 2004-2010 Szymon Stefanek (pragma at kvirc dot net)
8 //
9 // This program is FREE software. You can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; either version 2
12 // of the License, or (at your option) any later version.
13 //
14 // This program is distributed in the HOPE that it will be USEFUL,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 // See the GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with this program. If not, write to the Free Software Foundation,
21 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 //
23 //=============================================================================
24
25 #include "kvi_settings.h"
26 #include "KviModule.h"
27 #include "KviFileUtils.h"
28 #include "KviLocale.h"
29 #include "KviApplication.h"
30 #include "KviOptions.h"
31 #include "KviModuleManager.h"
32 #include "kvi_out.h"
33
34 #ifdef COMPILE_PERL_SUPPORT
35 #include "../perlcore/perlcoreinterface.h"
36
37 static KviModule * g_pPerlCoreModule = nullptr;
38 #endif // COMPILE_PERL_SUPPORT
39
40 #ifdef COMPILE_PERL_SUPPORT
41 #define KVS_CHECK_PERLCORE(_m, _c) \
42 g_pPerlCoreModule = g_pModuleManager->getModule("perlcore"); \
43 if(!g_pPerlCoreModule) \
44 { \
45 if(!_c->switches()->find('q', "quiet")) \
46 { \
47 _c->warning(__tr2qs_ctx("The perlcore module can't be loaded: Perl support not available", "perl")); \
48 _c->warning(__tr2qs_ctx("To see more details about loading failure try /perlcore.load", "perl")); \
49 return true; \
50 } \
51 }
52 #else // !COMPILE_PERL_SUPPORT
53 #define KVS_CHECK_PERLCORE(_m, _c)
54 #endif // !COMPILE_PERL_SUPPORT
55
56 #ifdef COMPILE_PERL_SUPPORT
57 #define KVS_CHECK_MODULE_STATE(_m, _c) KVS_CHECK_PERLCORE(_m, _c)
58 #else // !COMPILE_PERL_SUPPORT
59 #define KVS_CHECK_MODULE_STATE(_m, _c) \
60 if(!_c->switches()->find('q', "quiet")) \
61 _c->warning(__tr2qs_ctx("This KVIrc executable has been compiled without Perl scripting support", "perl")); \
62 return true;
63 #endif // !COMPILE_PERL_SUPPORT
64
65 /*
66 @doc: perl_and_kvs
67 @type:
68 language
69 @title:
70 Using Perl from KVS and vice-versa.
71 @short:
72 How to use Perl from KVS and KVS from Perl.
73 @body:
74 [big]Introduction[/big]
75 Starting from version 3.0.2 you can include Perl code snippets
76 in KVS code and you can use KVS commands from within Perl.
77 This feature is present only if a working Perl installation
78 has been found at build time.
79 [big]Using Perl from KVS[/big]
80 Using Perl from KVIrc is really easy - just enclose
81 your Perl code snippet inside [cmd]perl.begin[/cmd] and [cmd]perl.end[/cmd].
82 [example]
83 [cmd]perl.begin[/cmd]
84 <perl code goes here>
85 [cmd]perl.end[/cmd]
86 [/example]
87 For example:
88 [example]
89 [cmd]perl.begin[/cmd]
90 open(MYFILE,'>>myfile.txt') or die "Can't open myfile.txt!";
91 print MYFILE "foo!\n";
92 close(MYFILE);
93 [cmd]perl.end[/cmd]
94 [/example]
95 A Perl code snippet can appear anywhere a KVS code snippet can
96 with the only restriction that it must be enclosed in [cmd]perl.begin[/cmd]
97 and [cmd]perl.end[/cmd]. This means that you can write Perl code
98 in the commandline, in the aliases, the event handlers, popups...anywhere.[br]
99 If you have already encountered KVIrc's [cmd]eval[/cmd] command
100 then you probably also know how to execute a Perl code snippet from a file :)
101 [big]Using KVS from Perl[/big]
102 KVIrc exports several commands to the Perl namespace
103 that allow you to invoke KVIrc's functions from inside the Perl code snippet.[br]
104 The nicest example is KVIrc::echo():
105 [example]
106 [cmd]perl.begin[/cmd]
107 KVIrc::echo("Hello KVIrc world from Perl!");
108 [cmd]perl.end[/cmd]
109 [/example]
110 KVIrc::echo() is the counterpart of the [cmd]echo[/cmd].
111 The exact syntax is:[br]
112 [b]KVIrc::echo(<text>[,<colorset>[,<windowid>]])[/b][br]
113 <text> is obviously the text to be printed. <colorset> is
114 the equivalent of the [cmd]echo[/cmd] -i option and <windowid>
115 is the equivalent of the -w option. Both <colorset> and <windowid>
116 can be omitted (in this case KVIrc will use a default colorset and the current window).
117 [big]Perl execution contexts[/big]
118 The Perl code snippets are executed by a Perl interpreter - each
119 interpreter has its own context and thus its own variables,
120 own function namespace etc.[br]
121 [br]
122 In the example above, KVIrc creates an interpreter when [cmd]perl.begin[/cmd]
123 is invoked and destroys it at [cmd]perl.end[/cmd] parsing time.
124 In fact, KVIrc can maintain multiple persistent interpreters that will
125 allow you to preserve your context across [cmd]perl.begin[/cmd] invocations.[br]
126 [br]
127 You can invoke a specific Perl context by passing it as parameter to the [cmd]perl.begin[/cmd]
128 command:
129 [example]
130 [cmd]perl.begin("mycontext")[/cmd]
131 $myvariable = "mycontext";
132 KVIrc::echo("This Perl code is executed from ".$myvariable);
133 [cmd]perl.end[/cmd]
134 [/example]
135 The nice thing is that at a later time you can invoke this context again
136 and discover that $mycontext has preserved its value:
137 [example]
138 [cmd]perl.begin("mycontext")[/cmd]
139 KVIrc::echo("myvariable is still equal to ".$myvariable);
140 [cmd]perl.end[/cmd]
141 [/example]
142 The first time you invoke a named Perl context it is automatically created and
143 it persists until KVIrc terminates or the Perl context is explicitly destroyed
144 by [cmd]perl.destroy[/cmd].[br]
145 [br]
146 There is a third possibility to destroy a context - when the
147 perlcore module is forcibly unloaded (by the means of /perlcore.unload). This
148 is however a rare case and should be treated just like a KVIrc restart (the
149 user probably WANTS the contexts to be reinitialized).[br]
150 [br]
151 The nice thing is that not only will your variables be preserved, any Perl
152 function or class you declare in a context will persist.
153 It's just like executing a long Perl script file with pauses inside.[br]
154 [br]
155 If you omit the Perl context name in the [cmd]perl.begin[/cmd] command
156 (or if you use an empty string in its place)
157 then KVIrc will create a temporary context for the snippet execution
158 and will destroy it immediately after [cmd]perl.end[/cmd] has been called.[br]
159 [br]
160 The major side effect of keeping persistent Perl contexts is that
161 Perl's symbol table will grow, and if not used carefully, the interpreter
162 may become a memory hog. So if you're going to use persistent contexts,
163 either try to keep the symbol table clean or explicitly call [cmd]perl.destroy[/cmd]
164 once in a while to recreate the interpreter.[br]
165 If you just execute occasional Perl code snippets and don't need to keep
166 persistent variables, then just use the nameless temporary context provided
167 by [cmd]perl.begin[/cmd]("").
168 [big]Passing parameters to the Perl script[/big]
169 The easiest way to pass parameters to the perl code snippet
170 is to put them as [cmd]perl.begin[/cmd] arguments.
171 In fact the complete syntax of [cmd]perl.begin[/cmd] is:[br]
172 [b]perl.begin(<perl context>,<arg0>,<arg1>,...)[/b][br]
173 Where the <arg0>,<arg1>...<argN> parameters
174 are passed to the Perl context as elements of the $_[] array.
175 [example]
176 [cmd]perl.begin[/cmd]("","Hello world!","Now I CAN",1,2,3)
177 for($i=0;$i<5;$i++)
178 KVIrc::echo($_[i],40);
179 [cmd]perl.end[/cmd]
180 [/example]
181 [big]Accessing the KVIrc scripting context from Perl[/big]
182 KVIrc exposes the following functions that manipulate
183 variables of the KVIrc's current KVS execution context:[br]
184 [b]KVIrc::getLocal(<x>)[/b][br]
185 Returns the value of the KVIrc's local variable %x.[br]
186 [b]KVIrc::getGlobal(<Y>)[/b][br]
187 Returns the value of the KVIrc's global variable %Y.[br]
188 [b]KVIrc::setLocal(<x>,<value>)[/b][br]
189 Sets KVIrc's local variable %x to <value>[br]
190 [b]KVIrc::setGlobal(<Y>,<value>)[/b][br]
191 Sets KVIrc's global variable %Y to <value>[br]
192 The local variables referenced belong to the current KVS execution context
193 while the global variables are visible everywhere.
194 [example]
195 %pippo = test
196 %Pluto = 12345
197 [cmd]perl.begin[/cmd]
198 $mypippo = KVIrc::getLocal("pippo");
199 $mypippo =~ s/^pi/ze/g;
200 $mypluto = KVIrc::getGlobal("Pluto");
201 $mypluto =~ s/23/xx/g;
202 KVIrc::setLocal("pippo",$mypluto);
203 KVIrc::setGlobal("Pluto",$mypippo);
204 [cmd]perl.end[/cmd]
205 [cmd]echo[/cmd] "\%pippo is" %pippo
206 [cmd]echo[/cmd] "\%Pluto is" %Pluto
207 [/example]
208 [big]Executing arbitrary KVIrc commands from Perl[/big]
209 You can execute arbitrary KVS commands from Perl by means of:[br]
210 [b]KVIrc::eval(<code>)[/b][br]
211 This function behaves exactly like the ${ <code> } KVS construct -
212 it executes <code> in a child context and returns its evaluation result.[br]
213 The following two code snippets have equivalent visible effects:
214 [example]
215 [cmd]echo[/cmd] ${ return "Yeah!"; }
216 [/example]
217 [example]
218 [cmd]perl.begin[/cmd]
219 KVIrc::echo(KVIrc::eval("return \"Yeah!\""));
220 [cmd]perl.end[/cmd]
221 [/example]
222 You can [i]eval[/i] compound command sequences and variable ones.[br]
223 Remember that the Perl code snippet is evaluated in a child KVS context
224 and thus the local variables are NOT visible!
225 The following code snippets may easily fool you:
226 [example]
227 %x = 10
228 [cmd]perl.begin[/cmd]
229 KVIrc::eval("echo \"The value is %x\"");
230 [cmd]perl.end[/cmd]
231 [/example]
232 This will print [i]The value is[/i] since %x is not accessible from the eval's context.
233 If you have tried to write something like this then you probably need to rewrite it as:
234 [example]
235 %x = 10
236 [cmd]perl.begin[/cmd]
237 $x = KVIrc::getLocal("x");
238 KVIrc::eval("echo \"The value is ".$x."\"");
239 [cmd]perl.end[/cmd]
240 [/example]
241 Note also that you must either escape the $ at the beginning of KVIrc identifiers
242 or use single quotes to prevent Perl from interpreting the $ as the beginning of a variable.
243 [example]
244 [comment]# This will not work as expected[/comment]
245 [cmd]perl.begin[/cmd]
246 KVIrc::echo(KVIrc::eval("return $window.caption"));
247 [cmd]perl.end[/cmd]
248 [comment]# But these will do[/comment]
249 [cmd]perl.begin[/cmd]
250 KVIrc::echo(KVIrc::eval("return \$window.caption"));
251 KVIrc::echo(KVIrc::eval('return $window.caption'));
252 [cmd]perl.end[/cmd]
253 [/example]
254 [big]A shortcut for KVIrc::eval("/say...")[/big]
255 Since KVIrc::eval("/say...") is a common calling pattern, say has been added
256 to the KVIrc Perl namespace. You can now call
257 [example]
258 KVIrc::say("Hi all!");
259 [/example]
260 and that will mimic the behaviour of
261 [example]
262 /[cmd]say[/cmd] Hi all!
263 [/example]
264 The complete syntax for KVIrc::say() is:[br]
265 [b]KVIrc::say(<text>[,<windowid>])[/b][br]
266 and the semantics are obvious (see also /[cmd]say[/cmd]).
267 [big]Perl script return values[/big]
268 The [cmd]perl.begin[/cmd] command propagates the Perl code return
269 value to the KVIrc context (just like a [cmd]setreturn[/cmd]() would do)
270 - this makes it easier to create an alias that executes a Perl script and
271 returns its result.[br]
272 [br]
273 Without this automatic propagation, you would be forced to play with variables:
274 [ul]
275 [li]First use [b]KVIrc::setLocal("var",123)[/b] from inside the
276 perl script;[/li]
277 [li]Then, from the KVIrc script after [cmd]perl.end[/cmd], retrieve the
278 %var variable, check its value and call [cmd]setreturn[/cmd]() on it.[/li]
279 [/ul]
280 [big]Executing Perl scripts from files[/big]
281 [example]
282 [cmd]alias[/cmd](perlexec)
283 {
284 %tmp = "perl.begin(\"\",$1,$2,$3,$4,$5)";
285 %tmp .= $file.read($0);
286 %tmp .= "perl.end";
287 eval %tmp;
288 }
289 perlexec "/home/pragma/myperlscript.pl" "param1" "param2" "param3"
290 [comment]# or even[/comment]
291 [cmd]echo[/cmd] $perlexec("/home/pragma/computeprimelargerthan.pl","10000")
292 [/example]
293 [big]Other tricks[/big]
294 An interesting feature of persistent Perl contexts is that you can prepare a
295 context for later fast execution.[br]
296 The idea is to declare all Perl functions in a single Perl code snippet
297 then call single functions when fast execution is needed.[br]
298 For example you might parse the following snippet at KVIrc's startup:
299 [example]
300 [cmd]perl.begin[/cmd]("persistent")
301 sub handler_for_event_1
302 {
303 do_complex_perl_stuff_here
304 }
305 sub handler_for_event_2
306 {
307 do_complex_perl_stuff_here
308 }
309 [cmd]perl.end[/cmd]
310 [/example]
311 and later simply call:
312 [example]
313 [cmd]perl.begin[/cmd]("persistent",param1,param2)
314 handler_for_event_1($_[0],$_[1])
315 [cmd]perl.end[/cmd]
316 [/example]
317 [big]Curiosity[/big]
318 The Perl support in KVIrc is implemented as a master-slave module pair.
319 The perl.* module is the master while perlcore is the slave.
320 When Perl support isn't compiled in, the perl.* commands
321 print some warnings and exit gracefully while the perlcore module
322 refuses to be loaded. When Perl support is compiled in but
323 for some reason the libperl.so can't be found or loaded, perlcore fails
324 the dynamic loading stage, however Perl.* only fails gracefully with warning
325 messages. This trick allows scripters to check for Perl
326 support with [fnc]perl.isAvailable[/fnc] and to embed Perl code snippets
327 in KVS even if the support is missing - the snippets will be just skipped.[br]
328 [br]
329 Happy Perl hacking :)[br]
330 */
331
332 /*
333 @doc: perl.begin
334 @type:
335 command
336 @title:
337 perl.begin
338 @keyterms:
339 Including Perl code snippets in KVS
340 @short:
341 Starts a Perl code snippet
342 @syntax:
343 perl.begin [-n] [-q] [(<perl_context>[,<arg0>[,<arg1>[...]]])]
344 <perl code>
345 perl.end
346 @switches:
347 !sw: -q | --quiet
348 Prevents the command from printing any warnings.
349 !sw: -n | --no-return
350 Prevents the Perl script return value to be propagated
351 to the current context.
352 !sw: -f | --fail-on-error
353 Treat Perl errors as KVS errors and abort execution of the
354 current script. Incompatible with -q
355 @description:
356 Indicates the beginning of a snippet of Perl code.
357 The whole code part between perl.begin and perl.end
358 is executed in a Perl interpreter.
359 If perl.end is omitted then it is implicitly assumed
360 that the code from perl.begin to the end of the command
361 buffer is Perl.[br]
362 Each Perl code execution is bound to a
363 Perl context (that is in fact a particular instance
364 of a Perl interpreter). If <perl_context> is not specified
365 or it is an empty string then temporary Perl interpreter is created
366 and destroyed just after the code snippet has terminated execution.
367 If <perl_context> is specified then a Perl interpreter
368 keyed to that context is used: if it was already existing
369 then it is reused otherwise it is created.
370 Any <perl_context> is persistent: it maintains the function
371 declarations and Perl variable states until explicitly
372 destroyed with [cmd]perl.destroy[/cmd] (or the perlcore
373 module is forcibly unloaded).[br]
374 The <arg0>,<arg1>,... arguments, if present, are passed
375 to the Perl code snippet in the @_ array (accessible as $_[0],$_[1]...).[br]
376 The return value of the Perl code is propagated to the current
377 context (just like [cmd]setreturn[/cmd] was called on it) unless
378 the -n switch is used.[br]
379 The -q switch prevents from the command from printing any
380 warning.[br]
381 See the [doc:perl_and_kvs]Perl scripting documentation[/doc]
382 for more information.
383 @examples:
384 [example]
385 perl.begin
386 KVIrc::eval("echo \"Hello World from Perl!\"");
387 perl.end
388 [/example]
389 @seealso:
390 */
391
392 /*
393 @doc: perl.end
394 @type:
395 command
396 @title:
397 perl.end
398 @short:
399 Ends a Perl code snippet
400 @syntax:
401 perl.begin[(<perl_context>)]
402 <perl code>
403 perl.end
404 @description:
405 Ends a Perl code snippet. See [cmd]perl.begin[/cmd].
406 @seealso:
407 [cmd]perl.begin[/cmd]
408 */
409
perl_kvs_cmd_begin(KviKvsModuleCommandCall * c)410 static bool perl_kvs_cmd_begin(KviKvsModuleCommandCall * c)
411 {
412 // This command is somewhat special in the fact that has a dedicated
413 // parsing routine in the KVS core parser.
414 // The parser sets the perl code as the first parameter of our call,
415 // the remaining params are the context name and the arguments
416
417 QString szCode, szContext;
418 KviKvsVariantList vList;
419 KVSM_PARAMETERS_BEGIN(c)
420 KVSM_PARAMETER("code", KVS_PT_STRING, 0, szCode)
421 KVSM_PARAMETER("context", KVS_PT_STRING, KVS_PF_OPTIONAL, szContext)
422 KVSM_PARAMETER("args", KVS_PT_VARIANTLIST, KVS_PF_OPTIONAL, vList)
423 KVSM_PARAMETERS_END(c)
424
425 KVS_CHECK_MODULE_STATE(m, c)
426
427 #ifdef COMPILE_PERL_SUPPORT
428 KviPerlCoreCtrlCommand_execute ex;
429 ex.uSize = sizeof(KviPerlCoreCtrlCommand_execute);
430 ex.pKvsContext = c->context();
431 ex.szContext = szContext;
432 ex.szCode = szCode;
433 for(KviKvsVariant * v = vList.first(); v; v = vList.next())
434 {
435 QString tmp;
436 v->asString(tmp);
437 ex.lArgs.append(tmp);
438 }
439 ex.bQuiet = c->switches()->find('q', "quiet");
440
441 if(!g_pPerlCoreModule->ctrl(KVI_PERLCORECTRLCOMMAND_EXECUTE, &ex))
442 {
443 if(!c->switches()->find('q', "quiet"))
444 c->warning(__tr2qs_ctx("The perlcore module failed to execute the code: something is wrong with the Perl support", "perl"));
445 return true;
446 }
447
448 if(!ex.lWarnings.isEmpty())
449 {
450 for(auto & lWarning : ex.lWarnings)
451 c->warning(lWarning);
452 }
453
454 if(!ex.bExitOk)
455 {
456 if(!c->switches()->find('q', "quiet"))
457 {
458
459 if(c->switches()->find('f', "fail-on-error"))
460 {
461 c->warning(__tr2qs_ctx("Perl execution error:", "perl"));
462 c->warning(ex.szError);
463 return false;
464 }
465 else
466 {
467 c->warning(__tr2qs_ctx("Perl execution error:", "perl"));
468 c->error(ex.szError);
469 }
470 }
471 }
472
473 if(!c->switches()->find('n', "no-return"))
474 c->context()->returnValue()->setString(ex.szRetVal);
475
476 #endif //COMPILE_PERL_SUPPORT
477
478 return true;
479 }
480
481 /*
482 @doc: perl.destroy
483 @type:
484 command
485 @title:
486 perl.destroy
487 @short:
488 Destroys a Perl execution context
489 @syntax:
490 perl.destroy [-q] <context_name:string>
491 @description:
492 Destroys the Perl execution context <context_name>.
493 If the context does not exist then a warning is printed unless the
494 -q switch is used.[br]
495 The destruction will clear any state associated with the context
496 including the stored functions, classes and variable symbols.
497 You may want to destroy a context to re-initialize its state
498 or to simply clear its memory when it is no longer needed.
499 @seealso:
500 [cmd]perl.begin[/cmd]
501 */
502
perl_kvs_cmd_destroy(KviKvsModuleCommandCall * c)503 static bool perl_kvs_cmd_destroy(KviKvsModuleCommandCall * c)
504 {
505 QString szContext;
506 KVSM_PARAMETERS_BEGIN(c)
507 KVSM_PARAMETER("context", KVS_PT_NONEMPTYSTRING, 0, szContext)
508 KVSM_PARAMETERS_END(c)
509
510 KVS_CHECK_MODULE_STATE(m, c)
511
512 #ifdef COMPILE_PERL_SUPPORT
513 KviPerlCoreCtrlCommand_destroy ex;
514 ex.uSize = sizeof(KviPerlCoreCtrlCommand_destroy);
515 ex.szContext = szContext;
516
517 if(!g_pPerlCoreModule->ctrl(KVI_PERLCORECTRLCOMMAND_DESTROY, &ex))
518 {
519 if(!c->switches()->find('q', "quiet"))
520 c->warning(__tr2qs_ctx("The perlcore module failed to execute the code: something is wrong with the Perl support", "perl"));
521 }
522 #endif //COMPILE_PERL_SUPPORT
523
524 return true;
525 }
526
527 /*
528 @doc: perl.isAvailable
529 @type:
530 function
531 @title:
532 $perl.isAvailable
533 @short:
534 Check if Perl scripting support is available
535 @syntax:
536 $perl.isAvailable
537 @description:
538 Returns [b]1[/b] if the Perl scripting support is available and [b]0[/b] otherwise.
539 */
540
perl_kvs_fnc_isAvailable(KviKvsModuleFunctionCall * c)541 static bool perl_kvs_fnc_isAvailable(KviKvsModuleFunctionCall * c)
542 {
543 #ifdef COMPILE_PERL_SUPPORT
544 g_pPerlCoreModule = g_pModuleManager->getModule("perlcore");
545 c->returnValue()->setBoolean(g_pPerlCoreModule ? true : false);
546 #else // COMPILE_PERL_SUPPORT
547 c->returnValue()->setBoolean(false);
548 #endif // COMPILE_PERL_SUPPORT
549 return true;
550 }
551
perl_module_init(KviModule * m)552 static bool perl_module_init(KviModule * m)
553 {
554 // register the command anyway
555 KVSM_REGISTER_SIMPLE_COMMAND(m, "begin", perl_kvs_cmd_begin);
556 KVSM_REGISTER_SIMPLE_COMMAND(m, "destroy", perl_kvs_cmd_destroy);
557
558 KVSM_REGISTER_FUNCTION(m, "isAvailable", perl_kvs_fnc_isAvailable);
559
560 // FIXME: perl.isSupported()
561 #ifdef COMPILE_PERL_SUPPORT
562 g_pPerlCoreModule = g_pModuleManager->getModule("perlcore");
563 #endif // COMPILE_PERL_SUPPORT
564 return true;
565 }
566
perl_module_cleanup(KviModule *)567 static bool perl_module_cleanup(KviModule *)
568 {
569 return true;
570 }
571
572 KVIRC_MODULE(
573 "Perl", // module name
574 "4.0.0", // module version
575 "Copyright (C) 2004 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
576 "Perl scripting engine",
577 perl_module_init,
578 0,
579 0,
580 perl_module_cleanup,
581 "perl")
582