Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 511 lines (456 sloc) 15.373 kb
821effd @sanko Tack on standard set of headers and include perliol.h
authored
1 #define PERL_NO_GET_CONTEXT 1
2 #include <EXTERN.h>
3 #include <perl.h>
4 #include <perliol.h>
5 #define NO_XSLOCKS /* XSUB.h will otherwise override various things we need */
6 #include <XSUB.h>
7 #define NEED_sv_2pv_flags
8 #include "patchlevel.h" /* for local_patches */
9
eb9cf26 @sanko Standard dist is now built for perl 5.12.x
authored
10 const char * VERSION = "1.5012001";
d77193d @sanko Moving the file mapping stuff from Perl to C
authored
11 static const char * NAMESPACE = "mIRC";
6d26163 @sanko Initial commit (SVN history has not been carried over)
authored
12
d77193d @sanko Moving the file mapping stuff from Perl to C
authored
13 #define BUFFER_SIZE 4096
14 #define WM_MCOMMAND WM_USER + 200
15 #define WM_MEVALUATE WM_USER + 201
6d26163 @sanko Initial commit (SVN history has not been carried over)
authored
16
17 typedef struct {
18 short major;
19 short minor;
20 } MVERSION;
21
22 typedef struct {
23 MVERSION mVersion;
0ed551f @sanko Tidy
authored
24 HWND mHwnd;
25 BOOL mKeep;
6d26163 @sanko Initial commit (SVN history has not been carried over)
authored
26 } LOADINFO;
27
0ed551f @sanko Tidy
authored
28 static PerlInterpreter * my_perl = NULL;
6d26163 @sanko Initial commit (SVN history has not been carried over)
authored
29
30 HWND mWnd;
31 BOOL loaded;
d77193d @sanko Moving the file mapping stuff from Perl to C
authored
32 HANDLE hMapFile;
33 LPSTR mData;
6d26163 @sanko Initial commit (SVN history has not been carried over)
authored
34
35 EXTERN_C void xs_init ( pTHX );
5337073 @sanko Hook into mIRC with XS-based methods
authored
36 EXTERN_C void boot_DynaLoader ( pTHX_ CV* cv );
37 EXTERN_C void boot_Win32CORE ( pTHX_ CV* cv );
38 EXTERN_C void XS_mIRC_evaluate ( pTHX_ CV* cv );
39 EXTERN_C void XS_mIRC_execute ( pTHX_ CV* cv );
6d26163 @sanko Initial commit (SVN history has not been carried over)
authored
40
41 EXTERN_C void xs_init( pTHX ) {
42 PERL_UNUSED_CONTEXT;
0ed551f @sanko Tidy
authored
43 char * file = __FILE__;
6d26163 @sanko Initial commit (SVN history has not been carried over)
authored
44 dXSUB_SYS;
45 /* DynaLoader is a special case; Win32 is a special m[h?ea?d] case */
5337073 @sanko Hook into mIRC with XS-based methods
authored
46 ( void )newXS( "DynaLoader::boot_DynaLoader", boot_DynaLoader, file );
47 ( void )newXS( "Win32CORE::bootstrap", boot_Win32CORE, file );
48 ( void )newXS( "mIRC::evaluate", XS_mIRC_evaluate, file );
49 ( void )newXS( "mIRC::execute", XS_mIRC_execute, file );
0ed551f @sanko Tidy
authored
50 }
d77193d @sanko Moving the file mapping stuff from Perl to C
authored
51
52 void
53 mIRC_execute ( const char * snippet ) {
54 wsprintf( mData, snippet );
55 SendMessage( mWnd, WM_MCOMMAND, ( WPARAM ) NULL, ( LPARAM ) NULL );
56 return;
57 }
58
59 const char *
60 mIRC_evaluate ( const char * variable ) {
61 lstrcpy( mData, variable );
62 return SendMessage( mWnd, WM_MEVALUATE, ( WPARAM ) NULL, ( LPARAM ) NULL ) ?
63 mData : "";
64 }
65
9d22530 @sanko Remind myself why various bits are there
authored
66 #ifdef PERLIO_LAYERS /* Layers available */
1064c32 @sanko Define basic PerlIOmIRC layer
authored
67
68 #include "perliol.h"
69
70 typedef struct {
71 struct _PerlIO base; /* Base "class" info */
72 SV * var;
73 SV * arg;
74 Off_t posn;
75 } PerlIOmIRC;
76
da3263e @sanko This PerlIOmIRC_write(...) is a c+p of PerlIOBasic_write(...) and may be...
authored
77 SSize_t PerlIOmIRC_read( pTHX_ PerlIO *f, void *vbuf, Size_t count ) {
78 STDCHAR *buf = ( STDCHAR * ) vbuf;
79 if ( f ) {
80 if ( !( PerlIOBase( f )->flags & PERLIO_F_CANREAD ) ) {
81 PerlIOBase( f )->flags |= PERLIO_F_ERROR;
82 SETERRNO( EBADF, SS_IVCHAN );
83 return 0;
84 }
85 while ( count > 0 ) {
86 get_cnt: {
87 SSize_t avail = PerlIO_get_cnt( f );
88 SSize_t take = 0;
89 if ( avail > 0 )
90 take = ( ( SSize_t )count < avail ) ? ( SSize_t )count : avail;
91 if ( take > 0 ) {
92 STDCHAR *ptr = PerlIO_get_ptr( f );
93 Copy( ptr, buf, take, STDCHAR );
94 PerlIO_set_ptrcnt( f, ptr + take, ( avail -= take ) );
95 count -= take;
96 buf += take;
97 if ( avail == 0 ) /* set_ptrcnt could have reset avail */
98 goto get_cnt;
99 }
100 if ( count > 0 && avail <= 0 ) {
101 if ( PerlIO_fill( f ) != 0 )
102 break;
103 }
104 }
105 }
106 return ( buf - ( STDCHAR * ) vbuf );
107 }
108 return 0;
109 }
110
df409e8 @sanko Send a signal with the appropriate file handle name to mIRC
authored
111 SSize_t PerlIOmIRC_write( pTHX_ PerlIO * f, const void *vbuf, Size_t count ) {
112 PerlIOmIRC * e = PerlIOSelf( f, PerlIOmIRC );
113 AV * av = newAV();
114 const char * fh = "UNKNOWN";
115 if ( f == PerlIO_stdin( ) )
116 fh = "STDIN"; /* Should never get write */
117 else if ( f == PerlIO_stdout( ) )
118 fh = "STDOUT";
119 else if ( f == PerlIO_stderr( ) )
120 fh = "STDERR";
12bf5dd @sanko Start the signal with a wide char in case the printed line begins with a...
authored
121 mIRC_execute( form( "/.signal -n PERL_%s %s%s", fh,
122 ( isdigit( *( const char * )vbuf ) ? " " : "" ),
123 vbuf ) );
df409e8 @sanko Send a signal with the appropriate file handle name to mIRC
authored
124 return count;
da3263e @sanko This PerlIOmIRC_write(...) is a c+p of PerlIOBasic_write(...) and may be...
authored
125 }
6d26163 @sanko Initial commit (SVN history has not been carried over)
authored
126
f776a7f @sanko Declaring new layer as PerlIO_mIRC. I think I'll only need handle read/w...
authored
127 PERLIO_FUNCS_DECL( PerlIO_mIRC ) = {
128 sizeof( PerlIO_funcs ),
129 "mIRC",
130 sizeof( PerlIOmIRC ),
131 PERLIO_K_RAW,
ef28532 @sanko PerlIOmIRC_pushed(...) I came up with was only subtly different than Per...
authored
132 PerlIOBase_pushed,
f776a7f @sanko Declaring new layer as PerlIO_mIRC. I think I'll only need handle read/w...
authored
133 PerlIOBase_popped,
134 NULL, /* PerlIOmIRC_open */
135 NULL, /* PerlIOBase_binmode */
136 NULL, /* PerlIOmIRC_arg */
137 NULL, /* PerlIOmIRC_fileno */
138 NULL, /* PerlIOBase_dup */
139 PerlIOmIRC_read,
140 NULL, /* PerlIOmIRC_unread */
141 PerlIOmIRC_write,
142 NULL, /* PerlIOmIRC_seek */
143 NULL, /* PerlIOmIRC_tell */
144 NULL, /* PerlIOBase_close */
145 NULL, /* PerlIOmIRC_flush */
146 NULL, /* PerlIOmIRC_fill */
147 NULL, /* PerlIOBase_eof */
148 NULL, /* PerlIOBase_error */
149 NULL, /* PerlIOBase_clearerr */
150 NULL, /* PerlIOBase_setlinebuf */
151 NULL, /* PerlIOmIRC_get_base */
152 NULL, /* PerlIOmIRC_bufsiz */
153 NULL, /* PerlIOmIRC_get_ptr */
154 NULL, /* PerlIOmIRC_get_cnt */
155 NULL /* PerlIOmIRC_set_ptrcnt */
156 };
1064c32 @sanko Define basic PerlIOmIRC layer
authored
157
9d22530 @sanko Remind myself why various bits are there
authored
158 #endif /* PERLIO_LAYERS */
1064c32 @sanko Define basic PerlIOmIRC layer
authored
159
62143d5 @sanko Major bug fixes, mIRC 6.3+ support
authored
160 int execute_perl( const char *function, char **args, char *data ) {
161 int count = 0, i, ret_value = 1;
162 STRLEN na;
163 SV *sv_args[0];
164 dSP;
165 PERL_SET_CONTEXT( my_perl );
166 /*
0ed551f @sanko Tidy
authored
167 * Set up the perl environment, push arguments onto the perl stack, then
168 * call the given function
62143d5 @sanko Major bug fixes, mIRC 6.3+ support
authored
169 */
170 SPAGAIN;
171 ENTER;
172 SAVETMPS;
173 PUSHMARK( sp );
174 for ( i = 0; i < ( int )sizeof( args ) - 1; i++ ) {
175 if ( args[i] != NULL ) {
176 sv_args[i] = sv_2mortal( newSVpv( args[i], 0 ) );
177 XPUSHs( sv_args[i] );
178 }
179 }
180 PUTBACK;
181 PERL_SET_CONTEXT( my_perl );
182 count = call_pv( function, G_EVAL | G_SCALAR );
183 SPAGAIN;
184 /*
0ed551f @sanko Tidy
authored
185 * Check for "die," make sure we have 1 argument, and set our return value
62143d5 @sanko Major bug fixes, mIRC 6.3+ support
authored
186 */
187 if ( SvTRUE( ERRSV ) ) {
188 sprintf( data,
189 "%sPerl function (%s) exited abnormally: %s",
190 ( loaded ? "ERR " : "" ), function, SvPV( ERRSV, na ) );
191 ( void )POPs;
192 }
193 else if ( count != 1 ) {
194 /*
0ed551f @sanko Tidy
authored
195 * This should NEVER happen. G_SCALAR ensures that we WILL have 1
196 * parameter
62143d5 @sanko Major bug fixes, mIRC 6.3+ support
authored
197 */
198 sprintf( data,
199 "%sPerl error executing '%s': expected 1 return value; received %s",
200 ( loaded ? "ERR " : "" ), function, count );
201 }
202 else {
203 sprintf( data, "%s%s", ( loaded ? "OK " : "" ), POPpx );
204 }
205 /* Check for changed arguments */
206 for ( i = 0; i < ( int )sizeof( args ) - 1; i++ ) {
207 if ( args[i] && strcmp( args[i], SvPVX( sv_args[i] ) ) ) {
208 args[i] = strdup( SvPV( sv_args[i], na ) );
209 }
210 }
211 PUTBACK;
212 FREETMPS;
213 LEAVE;
214 return ret_value;
215 }
216
6d26163 @sanko Initial commit (SVN history has not been carried over)
authored
217 // Get everything going...
12fa22e @sanko Simple error handling, magic mIRC variable setup, and trigger the PERL_O...
authored
218 int __declspec( dllexport ) __stdcall LoadDll( LOADINFO * limIRC ) {
219 mWnd = limIRC->mHwnd;
220 limIRC->mKeep = TRUE; // TODO: Set to FALSE if the inline perl fails
62143d5 @sanko Major bug fixes, mIRC 6.3+ support
authored
221
12fa22e @sanko Simple error handling, magic mIRC variable setup, and trigger the PERL_O...
authored
222 if ( my_perl == NULL ) {
223 /* Get things set for mIRC<=>perl IO */
224 hMapFile = CreateFileMapping( INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, 4096, NAMESPACE );
225 mData = ( LPSTR )MapViewOfFile( hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0 );
226 /* Create our persistant interpreter */
227 char * perl_args[] = { "", "-e", "", "0" };
228 PERL_SYS_INIT3( NULL, NULL, NULL );
229 if ( ( my_perl = perl_alloc() ) == NULL ) {
230 mIRC_execute( "/echo Failed to load DLL: No memory" ); /* TODO: make this an error message */
231 limIRC->mKeep = FALSE;
232 return 0;
233 }
234 perl_construct( my_perl );
235 PL_origalen = 1; /* Don't let $0 assignment update the proctitle or perl_args[0] */
236 perl_parse( my_perl, xs_init, 6, perl_args, NULL );
237 PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
238 perl_run( my_perl );
e0c1b6d @sanko Add the layer and apply it to STDERR and STDOUT (yay!)
authored
239 {
9d22530 @sanko Remind myself why various bits are there
authored
240 #ifdef PERLIO_LAYERS /* Layers available */
e0c1b6d @sanko Add the layer and apply it to STDERR and STDOUT (yay!)
authored
241 PerlIO_define_layer( aTHX_ PERLIO_FUNCS_CAST( &PerlIO_mIRC ) );
242 PerlIO_apply_layers( aTHX_ PerlIO_stderr( ), NULL, ":mIRC" );
243 PerlIO_apply_layers( aTHX_ PerlIO_stdout( ), NULL, ":mIRC" );
9d22530 @sanko Remind myself why various bits are there
authored
244 #endif /* PERLIO_LAYERS */
6d26163 @sanko Initial commit (SVN history has not been carried over)
authored
245 }
12fa22e @sanko Simple error handling, magic mIRC variable setup, and trigger the PERL_O...
authored
246 SV * result = eval_pv( form(
247 "use FindBin;" /* CORE */
248 "use lib qq[$FindBin::Bin/lib];" /* Search %mIRC%/lib for modules */
249 "use lib qq[$FindBin::Bin/perl];" /* Look for modules in %mIRC%/perl */
250 "my $mIRC = bless \{ }, 'mIRC';"
251 "*mIRC = *mIRC = %mIRC = $mIRC;"
252 "require mIRC;"
253 "$mIRC::VERSION = '%s'", VERSION ), FALSE );
254 if ( SvTRUE( ERRSV ) ) {
255 char * err;
256 sprintf( err, "/echo Failed to load DLL: %s", SvPVx_nolen ( ERRSV ) );/* TODO: make this an error message */
257 mIRC_execute( err );
258 limIRC->mKeep = FALSE;
259 return 0;
260 }
261 mIRC_execute( "/.signal -n PERL_ONLOAD" );
262 loaded = SvTRUE( ERRSV ) ? FALSE : TRUE;
6d26163 @sanko Initial commit (SVN history has not been carried over)
authored
263 PERL_SET_CONTEXT( my_perl );
12fa22e @sanko Simple error handling, magic mIRC variable setup, and trigger the PERL_O...
authored
264 perl_run( my_perl );
6d26163 @sanko Initial commit (SVN history has not been carried over)
authored
265 }
12fa22e @sanko Simple error handling, magic mIRC variable setup, and trigger the PERL_O...
authored
266 PERL_SET_CONTEXT( my_perl );
6d26163 @sanko Initial commit (SVN history has not been carried over)
authored
267 return 0;
268 }
1dfc55c @sanko Do not destroy the interpreter when the dll times out but clean out the ...
authored
269
6d26163 @sanko Initial commit (SVN history has not been carried over)
authored
270 int __declspec( dllexport ) __stdcall UnloadDll( int mTimeout ) {
1dfc55c @sanko Do not destroy the interpreter when the dll times out but clean out the ...
authored
271 SV* result = eval_pv( /* auto clean */
272 "foreach my $lib ( @DynaLoader::dl_modules ) {\n"
273 " if ( $lib =~ m[^mIRC::eval::\\d+$] ) {\n"
274 " $lib .= q[->deinit();];\n"
275 " eval $lib;\n"
276 " }\n" /* TODO: delete the packages? */
277 "}", FALSE );
278
279 if ( mTimeout == 0 ) { /* user called /dll -u */
280 if ( my_perl == NULL )
281 return 0;
282 PL_perl_destruct_level = 1;
283 PERL_SET_CONTEXT( my_perl );
284 perl_destruct( my_perl );
285 perl_free( my_perl );
286 my_perl = NULL;
287 mIRC_execute( "/.signal -n PERL_UNLOAD" );
288 UnmapViewOfFile( mData );
289 CloseHandle( hMapFile );
290 }
6d26163 @sanko Initial commit (SVN history has not been carried over)
authored
291 return 0;
292 }
293
c654abe @sanko Export functions in a less stupid way
authored
294 #ifdef __cplusplus
295 extern "C"
296 #endif
297 int __stdcall version (
298 HWND mWnd, HWND aWnd,
299 char * data, char * parms,
300 BOOL print, BOOL nopause
301 ) {
62143d5 @sanko Major bug fixes, mIRC 6.3+ support
authored
302 sprintf(
303 data, "perl4mIRC v%s by Sanko Robinson <sanko@cpan.org>", VERSION );
6d26163 @sanko Initial commit (SVN history has not been carried over)
authored
304 return 3;
305 }
306
c654abe @sanko Export functions in a less stupid way
authored
307 #ifdef __cplusplus
308 extern "C"
309 #endif
310 int __stdcall perl_eval_string (
311 HWND mWnd, HWND aWnd,
312 char * data, char * parms,
313 BOOL print, BOOL nopause
374d97a @sanko Restoring $perl() id usage from mIRC
authored
314 ) {
315 dSP;
316 I32 ax;
3dffa16 @sanko Don't collapse when things go awry but let the user know there was an er...
authored
317 int count, i = 0;
374d97a @sanko Restoring $perl() id usage from mIRC
authored
318 char * package;
319 SV * CODE;
320 /* ...what is this junk? Oh, it's...
0ed551f @sanko Tidy
authored
321 * mWnd - the handle to the main mIRC window.
322 * aWnd - the handle of the window in which the command is being issued,
323 * this might not be the currently active window if the command
324 * is being called by a remote script.
325 * data - the information that you wish to send to the DLL. On return,
326 * the DLL can fill this variable with the command it wants
327 * mIRC to perform if any.
328 * parms - filled by the DLL on return with parameters that it wants mIRC
329 * to use when performing the command that it returns in the
330 * data variable.
331 * Note: The data and parms variables can each hold 900 chars
332 * maximum.
333 * show - FALSE if the . prefix was specified to make the command quiet,
334 * or TRUE otherwise.
335 * nopause - TRUE if mIRC is in a critical routine and the DLL must not do
336 * anything that pauses processing in mIRC, eg. the DLL should
337 * not pop up a dialog.
338 *
339 * We basically ignore the majority of these which is just simply wrong.
340 * This WILL change in the future.
341 */
342
ecdff44 @sanko Eval'd stuff is now under the mIRC::eval:: namespace instead of perl4mIR...
authored
343 if ( my_perl == NULL )
344 return 0; /* Halt */
374d97a @sanko Restoring $perl() id usage from mIRC
authored
345 package = form( "mIRC::eval::%d", rand( ) );
6d26163 @sanko Initial commit (SVN history has not been carried over)
authored
346 PERL_SET_CONTEXT( my_perl );
374d97a @sanko Restoring $perl() id usage from mIRC
authored
347 CODE = eval_pv( form( "sub {"
348 " package %s;"
349 " my $mIRC = bless \{ }, 'mIRC';"
350 " *mIRC = *mIRC = %mIRC = $mIRC;\n"
351 "#line 1 mIRC_eval\n"
352 "%s\n"
3dffa16 @sanko Don't collapse when things go awry but let the user know there was an er...
authored
353 "}", package, data ), FALSE );
374d97a @sanko Restoring $perl() id usage from mIRC
authored
354 if ( SvTRUE( ERRSV ) ) {
355 warn( SvPVx_nolen ( ERRSV ) );
356 return 0;
357 }
358 ENTER;
359 SAVETMPS;
360 PUSHMARK( SP );
361 PUTBACK;
3dffa16 @sanko Don't collapse when things go awry but let the user know there was an er...
authored
362 count = call_sv( CODE, G_SCALAR | G_EVAL );
374d97a @sanko Restoring $perl() id usage from mIRC
authored
363 SPAGAIN;
364 SP -= count;
365 ax = ( SP - PL_stack_base ) + 1;
3dffa16 @sanko Don't collapse when things go awry but let the user know there was an er...
authored
366 if ( SvTRUE( ERRSV ) ) {/* Check the eval first */
367 warn( SvPV_nolen( ERRSV ) );
368 i++;
369 }
374d97a @sanko Restoring $perl() id usage from mIRC
authored
370 if ( count ) {
3dffa16 @sanko Don't collapse when things go awry but let the user know there was an er...
authored
371 lstrcpy( data, SvPV_nolen( ST( i ) ) );
374d97a @sanko Restoring $perl() id usage from mIRC
authored
372 PUTBACK;
373 FREETMPS;
374 LEAVE;
375 return 3; /* value */
376 }
377 PUTBACK;
378 FREETMPS;
379 LEAVE;
380 return 1; /* continue */
ecdff44 @sanko Eval'd stuff is now under the mIRC::eval:: namespace instead of perl4mIR...
authored
381
6d26163 @sanko Initial commit (SVN history has not been carried over)
authored
382 /* We can return an integer to indicate what we want mIRC to do:
0ed551f @sanko Tidy
authored
383 * 0 means that mIRC should /halt processing
384 * 1 means that mIRC should continue processing
385 * 2 means that we have filled the data variable with a command which mIRC
386 * should perform and we filled parms with the parameters to use, if any,
387 * when performing the command.
388 * 3 means that the DLL has filled the data variable with the result that
389 * $dll() as an identifier should return.
390 *
391 * For now, we always return 3. This may change in future.
392 */
393 }
394
5337073 @sanko Hook into mIRC with XS-based methods
authored
395 XS( XS_mIRC_execute );
396 XS( XS_mIRC_execute ) {
397 #ifdef dVAR
398 dVAR;
399 dXSARGS;
400 #else
401 dXSARGS;
402 #endif
403 if ( items != 2 )
404 croak( "Usage: mIRC->testing( snippet" );
405 {
406 const char * snippet = ( const char * )SvPV_nolen( ST( 1 ) );
407 mIRC_execute( snippet );
408 }
409 XSRETURN_EMPTY;
410 }
411
412 XS( XS_mIRC_evaluate );
413 XS( XS_mIRC_evaluate ) {
414 #ifdef dVAR
415 dVAR;
416 dXSARGS;
417 #else
418 dXSARGS;
419 #endif
420 if ( items != 2 )
421 croak( "Usage: mIRC->evaluate( variable" );
422 {
423 const char * RETVAL;
424 dXSTARG;
425 const char * variable = ( const char * )SvPV_nolen( ST( 1 ) );
426 RETVAL = mIRC_evaluate( variable );
427 sv_setpv( TARG, RETVAL );
428 XSprePUSH;
429 PUSHTARG;
430 }
431 XSRETURN( 1 );
432 }
433
434 XS( XS_mIRC_VERSION );
435 XS( XS_mIRC_VERSION ) {
436 #ifdef dVAR
437 dVAR;
438 dXSARGS;
439 #else
440 dXSARGS;
441 #endif
442 {
443 dXSTARG;
444 sv_setpv( TARG, VERSION );
445 XSprePUSH;
446 PUSHTARG;
447 }
448 XSRETURN( 1 );
6d26163 @sanko Initial commit (SVN history has not been carried over)
authored
449 }
450
451 /*
452
453 =pod
454
455 =head1 NAME
456
457 perl4mIRC
458
459 =head1 Synopsis
460
374d97a @sanko Restoring $perl() id usage from mIRC
authored
461 ; From mIRC's editbox
462 //echo $perl(reverse uc 'HPAJ')
463 ; Or
ab8c2cb @sanko Cleanup pod, update other docs (pre 1.0 freeze)
authored
464 /perl print 5.6 + 465
62143d5 @sanko Major bug fixes, mIRC 6.3+ support
authored
465
466 =head1 Description
467
468 Yo, dawg! We heard you like one liners so we put perl in your mIRC so
469 you can write Perl while on IRC!
470
471 =head1 To Do
472
473 ...plenty.
474
475 =over
476
477 =item Cache packages according to perlembed
478
479 =item bugfixes?
480
ab8c2cb @sanko Cleanup pod, update other docs (pre 1.0 freeze)
authored
481 =item See inline TODO comments in perl4mIRC.c
62143d5 @sanko Major bug fixes, mIRC 6.3+ support
authored
482
483 =item handle $ identifiers
6d26163 @sanko Initial commit (SVN history has not been carried over)
authored
484
62143d5 @sanko Major bug fixes, mIRC 6.3+ support
authored
485 =back
6d26163 @sanko Initial commit (SVN history has not been carried over)
authored
486
ab8c2cb @sanko Cleanup pod, update other docs (pre 1.0 freeze)
authored
487 =head1 Author
6d26163 @sanko Initial commit (SVN history has not been carried over)
authored
488
489 Sanko Robinson <sanko@cpan.org> - http://sankorobinson.com/
490
491 CPAN ID: SANKO
492
493 =head1 License and Legal
494
495 Copyright (C) 2008 by Sanko Robinson E<lt>sanko@cpan.orgE<gt>
496
497 This program is free software; you can redistribute it and/or modify
498 it under the terms of The Artistic License 2.0. See the F<LICENSE>
499 file included with this distribution or
500 http://www.perlfoundation.org/artistic_license_2_0. For
501 clarification, see http://www.perlfoundation.org/artistic_2_0_notes.
502
503 When separated from the distribution, all POD documentation is covered
504 by the Creative Commons Attribution-Share Alike 3.0 License. See
505 http://creativecommons.org/licenses/by-sa/3.0/us/legalcode. For
506 clarification, see http://creativecommons.org/licenses/by-sa/3.0/us/.
507
508 =cut
509
510 */
Something went wrong with that request. Please try again.