This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Add the Filter::Util::Call 1.04 by Paul Marquess from Filter-1.19.
[perl5.git] / ext / Filter / Util / Call.pm
CommitLineData
2c4bb738
JH
1package Filter::Util::Call ;
2
3require 5.002 ;
4require DynaLoader;
5require Exporter;
6use Carp ;
7use strict;
8use vars qw($VERSION @ISA @EXPORT) ;
9
10@ISA = qw(Exporter DynaLoader);
11@EXPORT = qw( filter_add filter_del filter_read filter_read_exact) ;
12$VERSION = "1.04" ;
13
14sub filter_read_exact($)
15{
16 my ($size) = @_ ;
17 my ($left) = $size ;
18 my ($status) ;
19
20 croak ("filter_read_exact: size parameter must be > 0")
21 unless $size > 0 ;
22
23 # try to read a block which is exactly $size bytes long
24 while ($left and ($status = filter_read($left)) > 0) {
25 $left = $size - length $_ ;
26 }
27
28 # EOF with pending data is a special case
29 return 1 if $status == 0 and length $_ ;
30
31 return $status ;
32}
33
34sub filter_add($)
35{
36 my($obj) = @_ ;
37
38 # Did we get a code reference?
39 my $coderef = (ref $obj eq 'CODE') ;
40
41 # If the parameter isn't already a reference, make it one.
42 $obj = \$obj unless ref $obj ;
43
44 $obj = bless ($obj, (caller)[0]) unless $coderef ;
45
46 # finish off the installation of the filter in C.
47 Filter::Util::Call::real_import($obj, (caller)[0], $coderef) ;
48}
49
50bootstrap Filter::Util::Call ;
51
521;
53__END__
54
55=head1 NAME
56
57Filter::Util::Call - Perl Source Filter Utility Module
58
59=head1 DESCRIPTION
60
61This module provides you with the framework to write I<Source Filters>
62in Perl.
63
64A I<Perl Source Filter> is implemented as a Perl module. The structure
65of the module can take one of two broadly similar formats. To
66distinguish between them, the first will be referred to as I<method
67filter> and the second as I<closure filter>.
68
69Here is a skeleton for the I<method filter>:
70
71 package MyFilter ;
72
73 use Filter::Util::Call ;
74
75 sub import
76 {
77 my($type, @arguments) = @_ ;
78 filter_add([]) ;
79 }
80
81 sub filter
82 {
83 my($self) = @_ ;
84 my($status) ;
85
86 $status = filter_read() ;
87 $status ;
88 }
89
90 1 ;
91
92and this is the equivalent skeleton for the I<closure filter>:
93
94 package MyFilter ;
95
96 use Filter::Util::Call ;
97
98 sub import
99 {
100 my($type, @arguments) = @_ ;
101
102 filter_add(
103 sub
104 {
105 my($status) ;
106 $status = filter_read() ;
107 $status ;
108 } )
109 }
110
111 1 ;
112
113To make use of either of the two filter modules above, place the line
114below in a Perl source file.
115
116 use MyFilter;
117
118In fact, the skeleton modules shown above are fully functional I<Source
119Filters>, albeit fairly useless ones. All they does is filter the
120source stream without modifying it at all.
121
122As you can see both modules have a broadly similar structure. They both
123make use of the C<Filter::Util::Call> module and both have an C<import>
124method. The difference between them is that the I<method filter>
125requires a I<filter> method, whereas the I<closure filter> gets the
126equivalent of a I<filter> method with the anonymous sub passed to
127I<filter_add>.
128
129To make proper use of the I<closure filter> shown above you need to
130have a good understanding of the concept of a I<closure>. See
131L<perlref> for more details on the mechanics of I<closures>.
132
133=head2 B<use Filter::Util::Call>
134
135The following functions are exported by C<Filter::Util::Call>:
136
137 filter_add()
138 filter_read()
139 filter_read_exact()
140 filter_del()
141
142=head2 B<import()>
143
144The C<import> method is used to create an instance of the filter. It is
145called indirectly by Perl when it encounters the C<use MyFilter> line
146in a source file (See L<perlfunc/import> for more details on
147C<import>).
148
149It will always have at least one parameter automatically passed by Perl
150- this corresponds to the name of the package. In the example above it
151will be C<"MyFilter">.
152
153Apart from the first parameter, import can accept an optional list of
154parameters. These can be used to pass parameters to the filter. For
155example:
156
157 use MyFilter qw(a b c) ;
158
159will result in the C<@_> array having the following values:
160
161 @_ [0] => "MyFilter"
162 @_ [1] => "a"
163 @_ [2] => "b"
164 @_ [3] => "c"
165
166Before terminating, the C<import> function must explicitly install the
167filter by calling C<filter_add>.
168
169B<filter_add()>
170
171The function, C<filter_add>, actually installs the filter. It takes one
172parameter which should be a reference. The kind of reference used will
173dictate which of the two filter types will be used.
174
175If a CODE reference is used then a I<closure filter> will be assumed.
176
177If a CODE reference is not used, a I<method filter> will be assumed.
178In a I<method filter>, the reference can be used to store context
179information. The reference will be I<blessed> into the package by
180C<filter_add>.
181
182See the filters at the end of this documents for examples of using
183context information using both I<method filters> and I<closure
184filters>.
185
186=head2 B<filter() and anonymous sub>
187
188Both the C<filter> method used with a I<method filter> and the
189anonymous sub used with a I<closure filter> is where the main
190processing for the filter is done.
191
192The big difference between the two types of filter is that the I<method
193filter> uses the object passed to the method to store any context data,
194whereas the I<closure filter> uses the lexical variables that are
195maintained by the closure.
196
197Note that the single parameter passed to the I<method filter>,
198C<$self>, is the same reference that was passed to C<filter_add>
199blessed into the filter's package. See the example filters later on for
200details of using C<$self>.
201
202Here is a list of the common features of the anonymous sub and the
203C<filter()> method.
204
205=over 5
206
207=item B<$_>
208
209Although C<$_> doesn't actually appear explicitly in the sample filters
210above, it is implicitly used in a number of places.
211
212Firstly, when either C<filter> or the anonymous sub are called, a local
213copy of C<$_> will automatically be created. It will always contain the
214empty string at this point.
215
216Next, both C<filter_read> and C<filter_read_exact> will append any
217source data that is read to the end of C<$_>.
218
219Finally, when C<filter> or the anonymous sub are finished processing,
220they are expected to return the filtered source using C<$_>.
221
222This implicit use of C<$_> greatly simplifies the filter.
223
224=item B<$status>
225
226The status value that is returned by the user's C<filter> method or
227anonymous sub and the C<filter_read> and C<read_exact> functions take
228the same set of values, namely:
229
230 < 0 Error
231 = 0 EOF
232 > 0 OK
233
234=item B<filter_read> and B<filter_read_exact>
235
236These functions are used by the filter to obtain either a line or block
237from the next filter in the chain or the actual source file if there
238aren't any other filters.
239
240The function C<filter_read> takes two forms:
241
242 $status = filter_read() ;
243 $status = filter_read($size) ;
244
245The first form is used to request a I<line>, the second requests a
246I<block>.
247
248In line mode, C<filter_read> will append the next source line to the
249end of the C<$_> scalar.
250
251In block mode, C<filter_read> will append a block of data which is <=
252C<$size> to the end of the C<$_> scalar. It is important to emphasise
253the that C<filter_read> will not necessarily read a block which is
254I<precisely> C<$size> bytes.
255
256If you need to be able to read a block which has an exact size, you can
257use the function C<filter_read_exact>. It works identically to
258C<filter_read> in block mode, except it will try to read a block which
259is exactly C<$size> bytes in length. The only circumstances when it
260will not return a block which is C<$size> bytes long is on EOF or
261error.
262
263It is I<very> important to check the value of C<$status> after I<every>
264call to C<filter_read> or C<filter_read_exact>.
265
266=item B<filter_del>
267
268The function, C<filter_del>, is used to disable the current filter. It
269does not affect the running of the filter. All it does is tell Perl not
270to call filter any more.
271
272See L<Example 4: Using filter_del> for details.
273
274=back
275
276=head1 EXAMPLES
277
278Here are a few examples which illustrate the key concepts - as such
279most of them are of little practical use.
280
281The C<examples> sub-directory has copies of all these filters
282implemented both as I<method filters> and as I<closure filters>.
283
284=head2 Example 1: A simple filter.
285
286Below is a I<method filter> which is hard-wired to replace all
287occurrences of the string C<"Joe"> to C<"Jim">. Not particularly
288Useful, but it is the first example and I wanted to keep it simple.
289
290 package Joe2Jim ;
291
292 use Filter::Util::Call ;
293
294 sub import
295 {
296 my($type) = @_ ;
297
298 filter_add(bless []) ;
299 }
300
301 sub filter
302 {
303 my($self) = @_ ;
304 my($status) ;
305
306 s/Joe/Jim/g
307 if ($status = filter_read()) > 0 ;
308 $status ;
309 }
310
311 1 ;
312
313Here is an example of using the filter:
314
315 use Joe2Jim ;
316 print "Where is Joe?\n" ;
317
318And this is what the script above will print:
319
320 Where is Jim?
321
322=head2 Example 2: Using the context
323
324The previous example was not particularly useful. To make it more
325general purpose we will make use of the context data and allow any
326arbitrary I<from> and I<to> strings to be used. This time we will use a
327I<closure filter>. To reflect its enhanced role, the filter is called
328C<Subst>.
329
330 package Subst ;
331
332 use Filter::Util::Call ;
333 use Carp ;
334
335 sub import
336 {
337 croak("usage: use Subst qw(from to)")
338 unless @_ == 3 ;
339 my ($self, $from, $to) = @_ ;
340 filter_add(
341 sub
342 {
343 my ($status) ;
344 s/$from/$to/
345 if ($status = filter_read()) > 0 ;
346 $status ;
347 })
348 }
349 1 ;
350
351and is used like this:
352
353 use Subst qw(Joe Jim) ;
354 print "Where is Joe?\n" ;
355
356
357=head2 Example 3: Using the context within the filter
358
359Here is a filter which a variation of the C<Joe2Jim> filter. As well as
360substituting all occurrences of C<"Joe"> to C<"Jim"> it keeps a count
361of the number of substitutions made in the context object.
362
363Once EOF is detected (C<$status> is zero) the filter will insert an
364extra line into the source stream. When this extra line is executed it
365will print a count of the number of substitutions actually made.
366Note that C<$status> is set to C<1> in this case.
367
368 package Count ;
369
370 use Filter::Util::Call ;
371
372 sub filter
373 {
374 my ($self) = @_ ;
375 my ($status) ;
376
377 if (($status = filter_read()) > 0 ) {
378 s/Joe/Jim/g ;
379 ++ $$self ;
380 }
381 elsif ($$self >= 0) { # EOF
382 $_ = "print q[Made ${$self} substitutions\n]" ;
383 $status = 1 ;
384 $$self = -1 ;
385 }
386
387 $status ;
388 }
389
390 sub import
391 {
392 my ($self) = @_ ;
393 my ($count) = 0 ;
394 filter_add(\$count) ;
395 }
396
397 1 ;
398
399Here is a script which uses it:
400
401 use Count ;
402 print "Hello Joe\n" ;
403 print "Where is Joe\n" ;
404
405Outputs:
406
407 Hello Jim
408 Where is Jim
409 Made 2 substitutions
410
411=head2 Example 4: Using filter_del
412
413Another variation on a theme. This time we will modify the C<Subst>
414filter to allow a starting and stopping pattern to be specified as well
415as the I<from> and I<to> patterns. If you know the I<vi> editor, it is
416the equivalent of this command:
417
418 :/start/,/stop/s/from/to/
419
420When used as a filter we want to invoke it like this:
421
422 use NewSubst qw(start stop from to) ;
423
424Here is the module.
425
426 package NewSubst ;
427
428 use Filter::Util::Call ;
429 use Carp ;
430
431 sub import
432 {
433 my ($self, $start, $stop, $from, $to) = @_ ;
434 my ($found) = 0 ;
435 croak("usage: use Subst qw(start stop from to)")
436 unless @_ == 5 ;
437
438 filter_add(
439 sub
440 {
441 my ($status) ;
442
443 if (($status = filter_read()) > 0) {
444
445 $found = 1
446 if $found == 0 and /$start/ ;
447
448 if ($found) {
449 s/$from/$to/ ;
450 filter_del() if /$stop/ ;
451 }
452
453 }
454 $status ;
455 } )
456
457 }
458
459 1 ;
460
461=head1 AUTHOR
462
463Paul Marquess
464
465=head1 DATE
466
46726th January 1996
468
469=cut
470