| 1 | =head1 NAME |
| 2 | |
| 3 | perlfilter - Source Filters |
| 4 | |
| 5 | =head1 DESCRIPTION |
| 6 | |
| 7 | This article is about a little-known feature of Perl called |
| 8 | I<source filters>. Source filters alter the program text of a module |
| 9 | before Perl sees it, much as a C preprocessor alters the source text of |
| 10 | a C program before the compiler sees it. This article tells you more |
| 11 | about what source filters are, how they work, and how to write your |
| 12 | own. |
| 13 | |
| 14 | The original purpose of source filters was to let you encrypt your |
| 15 | program source to prevent casual piracy. This isn't all they can do, as |
| 16 | you'll soon learn. But first, the basics. |
| 17 | |
| 18 | =head1 CONCEPTS |
| 19 | |
| 20 | Before the Perl interpreter can execute a Perl script, it must first |
| 21 | read it from a file into memory for parsing and compilation. If that |
| 22 | script itself includes other scripts with a C<use> or C<require> |
| 23 | statement, then each of those scripts will have to be read from their |
| 24 | respective files as well. |
| 25 | |
| 26 | Now think of each logical connection between the Perl parser and an |
| 27 | individual file as a I<source stream>. A source stream is created when |
| 28 | the Perl parser opens a file, it continues to exist as the source code |
| 29 | is read into memory, and it is destroyed when Perl is finished parsing |
| 30 | the file. If the parser encounters a C<require> or C<use> statement in |
| 31 | a source stream, a new and distinct stream is created just for that |
| 32 | file. |
| 33 | |
| 34 | The diagram below represents a single source stream, with the flow of |
| 35 | source from a Perl script file on the left into the Perl parser on the |
| 36 | right. This is how Perl normally operates. |
| 37 | |
| 38 | file -------> parser |
| 39 | |
| 40 | There are two important points to remember: |
| 41 | |
| 42 | =over 5 |
| 43 | |
| 44 | =item 1. |
| 45 | |
| 46 | Although there can be any number of source streams in existence at any |
| 47 | given time, only one will be active. |
| 48 | |
| 49 | =item 2. |
| 50 | |
| 51 | Every source stream is associated with only one file. |
| 52 | |
| 53 | =back |
| 54 | |
| 55 | A source filter is a special kind of Perl module that intercepts and |
| 56 | modifies a source stream before it reaches the parser. A source filter |
| 57 | changes our diagram like this: |
| 58 | |
| 59 | file ----> filter ----> parser |
| 60 | |
| 61 | If that doesn't make much sense, consider the analogy of a command |
| 62 | pipeline. Say you have a shell script stored in the compressed file |
| 63 | I<trial.gz>. The simple pipeline command below runs the script without |
| 64 | needing to create a temporary file to hold the uncompressed file. |
| 65 | |
| 66 | gunzip -c trial.gz | sh |
| 67 | |
| 68 | In this case, the data flow from the pipeline can be represented as follows: |
| 69 | |
| 70 | trial.gz ----> gunzip ----> sh |
| 71 | |
| 72 | With source filters, you can store the text of your script compressed and use a source filter to uncompress it for Perl's parser: |
| 73 | |
| 74 | compressed gunzip |
| 75 | Perl program ---> source filter ---> parser |
| 76 | |
| 77 | =head1 USING FILTERS |
| 78 | |
| 79 | So how do you use a source filter in a Perl script? Above, I said that |
| 80 | a source filter is just a special kind of module. Like all Perl |
| 81 | modules, a source filter is invoked with a use statement. |
| 82 | |
| 83 | Say you want to pass your Perl source through the C preprocessor before |
| 84 | execution. You could use the existing C<-P> command line option to do |
| 85 | this, but as it happens, the source filters distribution comes with a C |
| 86 | preprocessor filter module called Filter::cpp. Let's use that instead. |
| 87 | |
| 88 | Below is an example program, C<cpp_test>, which makes use of this filter. |
| 89 | Line numbers have been added to allow specific lines to be referenced |
| 90 | easily. |
| 91 | |
| 92 | 1: use Filter::cpp ; |
| 93 | 2: #define TRUE 1 |
| 94 | 3: $a = TRUE ; |
| 95 | 4: print "a = $a\n" ; |
| 96 | |
| 97 | When you execute this script, Perl creates a source stream for the |
| 98 | file. Before the parser processes any of the lines from the file, the |
| 99 | source stream looks like this: |
| 100 | |
| 101 | cpp_test ---------> parser |
| 102 | |
| 103 | Line 1, C<use Filter::cpp>, includes and installs the C<cpp> filter |
| 104 | module. All source filters work this way. The use statement is compiled |
| 105 | and executed at compile time, before any more of the file is read, and |
| 106 | it attaches the cpp filter to the source stream behind the scenes. Now |
| 107 | the data flow looks like this: |
| 108 | |
| 109 | cpp_test ----> cpp filter ----> parser |
| 110 | |
| 111 | As the parser reads the second and subsequent lines from the source |
| 112 | stream, it feeds those lines through the C<cpp> source filter before |
| 113 | processing them. The C<cpp> filter simply passes each line through the |
| 114 | real C preprocessor. The output from the C preprocessor is then |
| 115 | inserted back into the source stream by the filter. |
| 116 | |
| 117 | .-> cpp --. |
| 118 | | | |
| 119 | | | |
| 120 | | <-' |
| 121 | cpp_test ----> cpp filter ----> parser |
| 122 | |
| 123 | The parser then sees the following code: |
| 124 | |
| 125 | use Filter::cpp ; |
| 126 | $a = 1 ; |
| 127 | print "a = $a\n" ; |
| 128 | |
| 129 | Let's consider what happens when the filtered code includes another |
| 130 | module with use: |
| 131 | |
| 132 | 1: use Filter::cpp ; |
| 133 | 2: #define TRUE 1 |
| 134 | 3: use Fred ; |
| 135 | 4: $a = TRUE ; |
| 136 | 5: print "a = $a\n" ; |
| 137 | |
| 138 | The C<cpp> filter does not apply to the text of the Fred module, only |
| 139 | to the text of the file that used it (C<cpp_test>). Although the use |
| 140 | statement on line 3 will pass through the cpp filter, the module that |
| 141 | gets included (C<Fred>) will not. The source streams look like this |
| 142 | after line 3 has been parsed and before line 4 is parsed: |
| 143 | |
| 144 | cpp_test ---> cpp filter ---> parser (INACTIVE) |
| 145 | |
| 146 | Fred.pm ----> parser |
| 147 | |
| 148 | As you can see, a new stream has been created for reading the source |
| 149 | from C<Fred.pm>. This stream will remain active until all of C<Fred.pm> |
| 150 | has been parsed. The source stream for C<cpp_test> will still exist, |
| 151 | but is inactive. Once the parser has finished reading Fred.pm, the |
| 152 | source stream associated with it will be destroyed. The source stream |
| 153 | for C<cpp_test> then becomes active again and the parser reads line 4 |
| 154 | and subsequent lines from C<cpp_test>. |
| 155 | |
| 156 | You can use more than one source filter on a single file. Similarly, |
| 157 | you can reuse the same filter in as many files as you like. |
| 158 | |
| 159 | For example, if you have a uuencoded and compressed source file, it is |
| 160 | possible to stack a uudecode filter and an uncompression filter like |
| 161 | this: |
| 162 | |
| 163 | use Filter::uudecode ; use Filter::uncompress ; |
| 164 | M'XL(".H<US4''V9I;F%L')Q;>7/;1I;_>_I3=&E=%:F*I"T?22Q/ |
| 165 | M6]9*<IQCO*XFT"0[PL%%'Y+IG?WN^ZYN-$'J.[.JE$,20/?K=_[> |
| 166 | ... |
| 167 | |
| 168 | Once the first line has been processed, the flow will look like this: |
| 169 | |
| 170 | file ---> uudecode ---> uncompress ---> parser |
| 171 | filter filter |
| 172 | |
| 173 | Data flows through filters in the same order they appear in the source |
| 174 | file. The uudecode filter appeared before the uncompress filter, so the |
| 175 | source file will be uudecoded before it's uncompressed. |
| 176 | |
| 177 | =head1 WRITING A SOURCE FILTER |
| 178 | |
| 179 | There are three ways to write your own source filter. You can write it |
| 180 | in C, use an external program as a filter, or write the filter in Perl. |
| 181 | I won't cover the first two in any great detail, so I'll get them out |
| 182 | of the way first. Writing the filter in Perl is most convenient, so |
| 183 | I'll devote the most space to it. |
| 184 | |
| 185 | =head1 WRITING A SOURCE FILTER IN C |
| 186 | |
| 187 | The first of the three available techniques is to write the filter |
| 188 | completely in C. The external module you create interfaces directly |
| 189 | with the source filter hooks provided by Perl. |
| 190 | |
| 191 | The advantage of this technique is that you have complete control over |
| 192 | the implementation of your filter. The big disadvantage is the |
| 193 | increased complexity required to write the filter - not only do you |
| 194 | need to understand the source filter hooks, but you also need a |
| 195 | reasonable knowledge of Perl guts. One of the few times it is worth |
| 196 | going to this trouble is when writing a source scrambler. The |
| 197 | C<decrypt> filter (which unscrambles the source before Perl parses it) |
| 198 | included with the source filter distribution is an example of a C |
| 199 | source filter (see Decryption Filters, below). |
| 200 | |
| 201 | |
| 202 | =over 5 |
| 203 | |
| 204 | =item B<Decryption Filters> |
| 205 | |
| 206 | All decryption filters work on the principle of "security through |
| 207 | obscurity." Regardless of how well you write a decryption filter and |
| 208 | how strong your encryption algorithm, anyone determined enough can |
| 209 | retrieve the original source code. The reason is quite simple - once |
| 210 | the decryption filter has decrypted the source back to its original |
| 211 | form, fragments of it will be stored in the computer's memory as Perl |
| 212 | parses it. The source might only be in memory for a short period of |
| 213 | time, but anyone possessing a debugger, skill, and lots of patience can |
| 214 | eventually reconstruct your program. |
| 215 | |
| 216 | That said, there are a number of steps that can be taken to make life |
| 217 | difficult for the potential cracker. The most important: Write your |
| 218 | decryption filter in C and statically link the decryption module into |
| 219 | the Perl binary. For further tips to make life difficult for the |
| 220 | potential cracker, see the file I<decrypt.pm> in the source filters |
| 221 | module. |
| 222 | |
| 223 | =back |
| 224 | |
| 225 | =head1 CREATING A SOURCE FILTER AS A SEPARATE EXECUTABLE |
| 226 | |
| 227 | An alternative to writing the filter in C is to create a separate |
| 228 | executable in the language of your choice. The separate executable |
| 229 | reads from standard input, does whatever processing is necessary, and |
| 230 | writes the filtered data to standard output. C<Filter:cpp> is an |
| 231 | example of a source filter implemented as a separate executable - the |
| 232 | executable is the C preprocessor bundled with your C compiler. |
| 233 | |
| 234 | The source filter distribution includes two modules that simplify this |
| 235 | task: C<Filter::exec> and C<Filter::sh>. Both allow you to run any |
| 236 | external executable. Both use a coprocess to control the flow of data |
| 237 | into and out of the external executable. (For details on coprocesses, |
| 238 | see Stephens, W.R. "Advanced Programming in the UNIX Environment." |
| 239 | Addison-Wesley, ISBN 0-210-56317-7, pages 441-445.) The difference |
| 240 | between them is that C<Filter::exec> spawns the external command |
| 241 | directly, while C<Filter::sh> spawns a shell to execute the external |
| 242 | command. (Unix uses the Bourne shell; NT uses the cmd shell.) Spawning |
| 243 | a shell allows you to make use of the shell metacharacters and |
| 244 | redirection facilities. |
| 245 | |
| 246 | Here is an example script that uses C<Filter::sh>: |
| 247 | |
| 248 | use Filter::sh 'tr XYZ PQR' ; |
| 249 | $a = 1 ; |
| 250 | print "XYZ a = $a\n" ; |
| 251 | |
| 252 | The output you'll get when the script is executed: |
| 253 | |
| 254 | PQR a = 1 |
| 255 | |
| 256 | Writing a source filter as a separate executable works fine, but a |
| 257 | small performance penalty is incurred. For example, if you execute the |
| 258 | small example above, a separate subprocess will be created to run the |
| 259 | Unix C<tr> command. Each use of the filter requires its own subprocess. |
| 260 | If creating subprocesses is expensive on your system, you might want to |
| 261 | consider one of the other options for creating source filters. |
| 262 | |
| 263 | =head1 WRITING A SOURCE FILTER IN PERL |
| 264 | |
| 265 | The easiest and most portable option available for creating your own |
| 266 | source filter is to write it completely in Perl. To distinguish this |
| 267 | from the previous two techniques, I'll call it a Perl source filter. |
| 268 | |
| 269 | To help understand how to write a Perl source filter we need an example |
| 270 | to study. Here is a complete source filter that performs rot13 |
| 271 | decoding. (Rot13 is a very simple encryption scheme used in Usenet |
| 272 | postings to hide the contents of offensive posts. It moves every letter |
| 273 | forward thirteen places, so that A becomes N, B becomes O, and Z |
| 274 | becomes M.) |
| 275 | |
| 276 | |
| 277 | package Rot13 ; |
| 278 | |
| 279 | use Filter::Util::Call ; |
| 280 | |
| 281 | sub import { |
| 282 | my ($type) = @_ ; |
| 283 | my ($ref) = [] ; |
| 284 | filter_add(bless $ref) ; |
| 285 | } |
| 286 | |
| 287 | sub filter { |
| 288 | my ($self) = @_ ; |
| 289 | my ($status) ; |
| 290 | |
| 291 | tr/n-za-mN-ZA-M/a-zA-Z/ |
| 292 | if ($status = filter_read()) > 0 ; |
| 293 | $status ; |
| 294 | } |
| 295 | |
| 296 | 1; |
| 297 | |
| 298 | All Perl source filters are implemented as Perl classes and have the |
| 299 | same basic structure as the example above. |
| 300 | |
| 301 | First, we include the C<Filter::Util::Call> module, which exports a |
| 302 | number of functions into your filter's namespace. The filter shown |
| 303 | above uses two of these functions, C<filter_add()> and |
| 304 | C<filter_read()>. |
| 305 | |
| 306 | Next, we create the filter object and associate it with the source |
| 307 | stream by defining the C<import> function. If you know Perl well |
| 308 | enough, you know that C<import> is called automatically every time a |
| 309 | module is included with a use statement. This makes C<import> the ideal |
| 310 | place to both create and install a filter object. |
| 311 | |
| 312 | In the example filter, the object (C<$ref>) is blessed just like any |
| 313 | other Perl object. Our example uses an anonymous array, but this isn't |
| 314 | a requirement. Because this example doesn't need to store any context |
| 315 | information, we could have used a scalar or hash reference just as |
| 316 | well. The next section demonstrates context data. |
| 317 | |
| 318 | The association between the filter object and the source stream is made |
| 319 | with the C<filter_add()> function. This takes a filter object as a |
| 320 | parameter (C<$ref> in this case) and installs it in the source stream. |
| 321 | |
| 322 | Finally, there is the code that actually does the filtering. For this |
| 323 | type of Perl source filter, all the filtering is done in a method |
| 324 | called C<filter()>. (It is also possible to write a Perl source filter |
| 325 | using a closure. See the C<Filter::Util::Call> manual page for more |
| 326 | details.) It's called every time the Perl parser needs another line of |
| 327 | source to process. The C<filter()> method, in turn, reads lines from |
| 328 | the source stream using the C<filter_read()> function. |
| 329 | |
| 330 | If a line was available from the source stream, C<filter_read()> |
| 331 | returns a status value greater than zero and appends the line to C<$_>. |
| 332 | A status value of zero indicates end-of-file, less than zero means an |
| 333 | error. The filter function itself is expected to return its status in |
| 334 | the same way, and put the filtered line it wants written to the source |
| 335 | stream in C<$_>. The use of C<$_> accounts for the brevity of most Perl |
| 336 | source filters. |
| 337 | |
| 338 | In order to make use of the rot13 filter we need some way of encoding |
| 339 | the source file in rot13 format. The script below, C<mkrot13>, does |
| 340 | just that. |
| 341 | |
| 342 | die "usage mkrot13 filename\n" unless @ARGV ; |
| 343 | my $in = $ARGV[0] ; |
| 344 | my $out = "$in.tmp" ; |
| 345 | open(IN, "<$in") or die "Cannot open file $in: $!\n"; |
| 346 | open(OUT, ">$out") or die "Cannot open file $out: $!\n"; |
| 347 | |
| 348 | print OUT "use Rot13;\n" ; |
| 349 | while (<IN>) { |
| 350 | tr/a-zA-Z/n-za-mN-ZA-M/ ; |
| 351 | print OUT ; |
| 352 | } |
| 353 | |
| 354 | close IN; |
| 355 | close OUT; |
| 356 | unlink $in; |
| 357 | rename $out, $in; |
| 358 | |
| 359 | If we encrypt this with C<mkrot13>: |
| 360 | |
| 361 | print " hello fred \n" ; |
| 362 | |
| 363 | the result will be this: |
| 364 | |
| 365 | use Rot13; |
| 366 | cevag "uryyb serq\a" ; |
| 367 | |
| 368 | Running it produces this output: |
| 369 | |
| 370 | hello fred |
| 371 | |
| 372 | =head1 USING CONTEXT: THE DEBUG FILTER |
| 373 | |
| 374 | The rot13 example was a trivial example. Here's another demonstration |
| 375 | that shows off a few more features. |
| 376 | |
| 377 | Say you wanted to include a lot of debugging code in your Perl script |
| 378 | during development, but you didn't want it available in the released |
| 379 | product. Source filters offer a solution. In order to keep the example |
| 380 | simple, let's say you wanted the debugging output to be controlled by |
| 381 | an environment variable, C<DEBUG>. Debugging code is enabled if the |
| 382 | variable exists, otherwise it is disabled. |
| 383 | |
| 384 | Two special marker lines will bracket debugging code, like this: |
| 385 | |
| 386 | ## DEBUG_BEGIN |
| 387 | if ($year > 1999) { |
| 388 | warn "Debug: millennium bug in year $year\n" ; |
| 389 | } |
| 390 | ## DEBUG_END |
| 391 | |
| 392 | When the C<DEBUG> environment variable exists, the filter ensures that |
| 393 | Perl parses only the code between the C<DEBUG_BEGIN> and C<DEBUG_END> |
| 394 | markers. That means that when C<DEBUG> does exist, the code above |
| 395 | should be passed through the filter unchanged. The marker lines can |
| 396 | also be passed through as-is, because the Perl parser will see them as |
| 397 | comment lines. When C<DEBUG> isn't set, we need a way to disable the |
| 398 | debug code. A simple way to achieve that is to convert the lines |
| 399 | between the two markers into comments: |
| 400 | |
| 401 | ## DEBUG_BEGIN |
| 402 | #if ($year > 1999) { |
| 403 | # warn "Debug: millennium bug in year $year\n" ; |
| 404 | #} |
| 405 | ## DEBUG_END |
| 406 | |
| 407 | Here is the complete Debug filter: |
| 408 | |
| 409 | package Debug; |
| 410 | |
| 411 | use strict; |
| 412 | use warnings; |
| 413 | use Filter::Util::Call ; |
| 414 | |
| 415 | use constant TRUE => 1 ; |
| 416 | use constant FALSE => 0 ; |
| 417 | |
| 418 | sub import { |
| 419 | my ($type) = @_ ; |
| 420 | my (%context) = ( |
| 421 | Enabled => defined $ENV{DEBUG}, |
| 422 | InTraceBlock => FALSE, |
| 423 | Filename => (caller)[1], |
| 424 | LineNo => 0, |
| 425 | LastBegin => 0, |
| 426 | ) ; |
| 427 | filter_add(bless \%context) ; |
| 428 | } |
| 429 | |
| 430 | sub Die { |
| 431 | my ($self) = shift ; |
| 432 | my ($message) = shift ; |
| 433 | my ($line_no) = shift || $self->{LastBegin} ; |
| 434 | die "$message at $self->{Filename} line $line_no.\n" |
| 435 | } |
| 436 | |
| 437 | sub filter { |
| 438 | my ($self) = @_ ; |
| 439 | my ($status) ; |
| 440 | $status = filter_read() ; |
| 441 | ++ $self->{LineNo} ; |
| 442 | |
| 443 | # deal with EOF/error first |
| 444 | if ($status <= 0) { |
| 445 | $self->Die("DEBUG_BEGIN has no DEBUG_END") |
| 446 | if $self->{InTraceBlock} ; |
| 447 | return $status ; |
| 448 | } |
| 449 | |
| 450 | if ($self->{InTraceBlock}) { |
| 451 | if (/^\s*##\s*DEBUG_BEGIN/ ) { |
| 452 | $self->Die("Nested DEBUG_BEGIN", $self->{LineNo}) |
| 453 | } elsif (/^\s*##\s*DEBUG_END/) { |
| 454 | $self->{InTraceBlock} = FALSE ; |
| 455 | } |
| 456 | |
| 457 | # comment out the debug lines when the filter is disabled |
| 458 | s/^/#/ if ! $self->{Enabled} ; |
| 459 | } elsif ( /^\s*##\s*DEBUG_BEGIN/ ) { |
| 460 | $self->{InTraceBlock} = TRUE ; |
| 461 | $self->{LastBegin} = $self->{LineNo} ; |
| 462 | } elsif ( /^\s*##\s*DEBUG_END/ ) { |
| 463 | $self->Die("DEBUG_END has no DEBUG_BEGIN", $self->{LineNo}); |
| 464 | } |
| 465 | return $status ; |
| 466 | } |
| 467 | |
| 468 | 1 ; |
| 469 | |
| 470 | The big difference between this filter and the previous example is the |
| 471 | use of context data in the filter object. The filter object is based on |
| 472 | a hash reference, and is used to keep various pieces of context |
| 473 | information between calls to the filter function. All but two of the |
| 474 | hash fields are used for error reporting. The first of those two, |
| 475 | Enabled, is used by the filter to determine whether the debugging code |
| 476 | should be given to the Perl parser. The second, InTraceBlock, is true |
| 477 | when the filter has encountered a C<DEBUG_BEGIN> line, but has not yet |
| 478 | encountered the following C<DEBUG_END> line. |
| 479 | |
| 480 | If you ignore all the error checking that most of the code does, the |
| 481 | essence of the filter is as follows: |
| 482 | |
| 483 | sub filter { |
| 484 | my ($self) = @_ ; |
| 485 | my ($status) ; |
| 486 | $status = filter_read() ; |
| 487 | |
| 488 | # deal with EOF/error first |
| 489 | return $status if $status <= 0 ; |
| 490 | if ($self->{InTraceBlock}) { |
| 491 | if (/^\s*##\s*DEBUG_END/) { |
| 492 | $self->{InTraceBlock} = FALSE |
| 493 | } |
| 494 | |
| 495 | # comment out debug lines when the filter is disabled |
| 496 | s/^/#/ if ! $self->{Enabled} ; |
| 497 | } elsif ( /^\s*##\s*DEBUG_BEGIN/ ) { |
| 498 | $self->{InTraceBlock} = TRUE ; |
| 499 | } |
| 500 | return $status ; |
| 501 | } |
| 502 | |
| 503 | Be warned: just as the C-preprocessor doesn't know C, the Debug filter |
| 504 | doesn't know Perl. It can be fooled quite easily: |
| 505 | |
| 506 | print <<EOM; |
| 507 | ##DEBUG_BEGIN |
| 508 | EOM |
| 509 | |
| 510 | Such things aside, you can see that a lot can be achieved with a modest |
| 511 | amount of code. |
| 512 | |
| 513 | =head1 CONCLUSION |
| 514 | |
| 515 | You now have better understanding of what a source filter is, and you |
| 516 | might even have a possible use for them. If you feel like playing with |
| 517 | source filters but need a bit of inspiration, here are some extra |
| 518 | features you could add to the Debug filter. |
| 519 | |
| 520 | First, an easy one. Rather than having debugging code that is |
| 521 | all-or-nothing, it would be much more useful to be able to control |
| 522 | which specific blocks of debugging code get included. Try extending the |
| 523 | syntax for debug blocks to allow each to be identified. The contents of |
| 524 | the C<DEBUG> environment variable can then be used to control which |
| 525 | blocks get included. |
| 526 | |
| 527 | Once you can identify individual blocks, try allowing them to be |
| 528 | nested. That isn't difficult either. |
| 529 | |
| 530 | Here is an interesting idea that doesn't involve the Debug filter. |
| 531 | Currently Perl subroutines have fairly limited support for formal |
| 532 | parameter lists. You can specify the number of parameters and their |
| 533 | type, but you still have to manually take them out of the C<@_> array |
| 534 | yourself. Write a source filter that allows you to have a named |
| 535 | parameter list. Such a filter would turn this: |
| 536 | |
| 537 | sub MySub ($first, $second, @rest) { ... } |
| 538 | |
| 539 | into this: |
| 540 | |
| 541 | sub MySub($$@) { |
| 542 | my ($first) = shift ; |
| 543 | my ($second) = shift ; |
| 544 | my (@rest) = @_ ; |
| 545 | ... |
| 546 | } |
| 547 | |
| 548 | Finally, if you feel like a real challenge, have a go at writing a |
| 549 | full-blown Perl macro preprocessor as a source filter. Borrow the |
| 550 | useful features from the C preprocessor and any other macro processors |
| 551 | you know. The tricky bit will be choosing how much knowledge of Perl's |
| 552 | syntax you want your filter to have. |
| 553 | |
| 554 | =head1 THINGS TO LOOK OUT FOR |
| 555 | |
| 556 | =over 5 |
| 557 | |
| 558 | =item Some Filters Clobber the C<DATA> Handle |
| 559 | |
| 560 | Some source filters use the C<DATA> handle to read the calling program. |
| 561 | When using these source filters you cannot rely on this handle, nor expect |
| 562 | any particular kind of behavior when operating on it. Filters based on |
| 563 | Filter::Util::Call (and therefore Filter::Simple) do not alter the C<DATA> |
| 564 | filehandle. |
| 565 | |
| 566 | =back |
| 567 | |
| 568 | =head1 REQUIREMENTS |
| 569 | |
| 570 | The Source Filters distribution is available on CPAN, in |
| 571 | |
| 572 | CPAN/modules/by-module/Filter |
| 573 | |
| 574 | Starting from Perl 5.8 Filter::Util::Call (the core part of the |
| 575 | Source Filters distribution) is part of the standard Perl distribution. |
| 576 | Also included is a friendlier interface called Filter::Simple, by |
| 577 | Damian Conway. |
| 578 | |
| 579 | =head1 AUTHOR |
| 580 | |
| 581 | Paul Marquess E<lt>Paul.Marquess@btinternet.comE<gt> |
| 582 | |
| 583 | =head1 Copyrights |
| 584 | |
| 585 | This article originally appeared in The Perl Journal #11, and is |
| 586 | copyright 1998 The Perl Journal. It appears courtesy of Jon Orwant and |
| 587 | The Perl Journal. This document may be distributed under the same terms |
| 588 | as Perl itself. |