Icon for Dimension.orgIcon for TalentIcon for ToolsIcon for Doorways.org
Icon for ToolsIcon for Perl Tools

DoxyFilt: Source/Source.pm Source File

  • Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List

Source/Source.pm

Go to the documentation of this file.
00001 package Doxygen::Source;
00002 
00003 =head1 NAME
00004 
00005 Doxygen::Source - Perl extension for generating Doxygen documentation
00006 
00007 =head1 SYNOPSIS
00008 
00009     my  $source = new Doxygen::Source($path);
00010     
00011     $source->generate;
00012 
00013 =head1 ABSTRACT
00014 
00015 Represents a single source file to be filtered for Doxygen.
00016 
00017 A newly created instance requires a pathname, from which text is read.
00018 Zero or more parsers will be passed against the source text,
00019 storing interim state (Doxygen::Item objects) on the Source object.
00020 
00021 When the parsing is complete, use the object to generate Doxygen-enabled
00022 output.
00023 
00024 =head1 DESCRIPTION
00025 
00026 =head1 METHODS
00027 
00028 =over
00029 
00030 =cut
00031 
00032 use     5.005;  # just to pick something, but not really tested
00033 use     strict;
00034 use     warnings;
00035 use     UNIVERSAL   qw(isa);
00036 
00037 use     Doxygen::Item::File;
00038 
00039 use     base    qw(Doxygen::Item);
00040 
00041 our $VERSION = '0.01';
00042 
00043 use     constant    TYPE_ALIAS  =>  (
00044     Batch   =>  'Script',
00045     Shell   =>  'Script',
00046 );
00047 
00048 use     constant    TYPE_CHCK   =>  (
00049     Perl    =>  qr(^(?:#!/.*\bperl|package)\b)m,
00050     POD     =>  qr(^=(?:cut|head\d|item|pod))m,
00051     Shell   =>  qr(^#!/bin/(?:ba|c|k|z)?sh\b)
00052 );
00053 
00054 use     constant    TYPE_CMNT   =>  (
00055     Batch   =>  qr(^\s*rem ?(.*)$)im,
00056     Shell   =>  qr(^\s*#{2,3}(?!#) ?(.*)$)m
00057 );
00058 
00059 use     constant    TYPE_DOCS   =>  (
00060     Batch   =>  qr(\.(?:bat|cmd)$)i,
00061     Perl    =>  qr(\.(?:p[lm])$)i,
00062     POD     =>  qr(\.(?:p(?:l|m|od))$)i,
00063     Shell   =>  qr(\.(?:ba|c|k|z)?sh$)i,
00064     SQL     =>  qr(\.sql$)i
00065 );
00066 
00067 use     constant    TYPE_FLAG   =>  (
00068 );
00069 
00070 use     constant    TYPE_PASS   =>  (
00071     qr(\.doxy?$)i
00072 );
00073 
00074 use     constant    TYPE_SPAWN  =>  (
00075 #   Python  =>  /usr/local/bin/DoxyPyth.py
00076 );
00077 
00078 ###########################################################################
00079 ###########################################################################
00080 
00081 =item   C<new($class, %flags)>
00082 
00083 Constructor for Doxygen::Source objects.
00084 
00085 Takes a series of flags which initialize object fields.
00086 If the C<path> flag is set the object is immediately
00087 parsed, otherwise it must be done later.
00088 
00089 Useful flags:
00090 
00091 =over
00092 
00093 =item   C<info>
00094 
00095 If set to false will turn I<off> the
00096 generation of 'informational' ([I])
00097 log messages.
00098 
00099 =item   C<type>
00100 
00101 A hash reference that
00102 contains a series of objects that control how pathnames
00103 are processed or not processed.
00104 In general, the sub-objects specify regular expressions
00105 that are matched against pathnames.
00106 
00107 In all cases regular expressions may be replaced by
00108 simple strings that are converted into regular expressions
00109 using the following expression:
00110 
00111     qr(\.$strings$)i
00112 
00113 The following sub-flags may be specified
00114 within the C<type> hash:
00115 
00116 =over
00117 
00118 =item   C<alias>
00119 
00120 Causes specific filter names to be handled
00121 by different filters.
00122 For example, C<Batch> and C<Shell> are both
00123 handled by the instantiated C<Script> filter.
00124 There are no C<Batch> and C<Shell> filters
00125 (unless you instantiate them yourself).
00126 Each key can have a single value,
00127 new ones replace old ones, setting a key
00128 to point to itself is equivalent to
00129 removing it.
00130 
00131 =item   C<check>
00132 
00133 Specifies patterns for filters to see if files
00134 without suffixes are destined for these filters.
00135 For example, specify a pattern for the first
00136 line of a shell file (C<qr(^#!/bin/(?:ba|c|k|z)sh\b)>)
00137 which may show up without a suffix.
00138 The keys are filter names, (e.g. C<Shell>).
00139 Each key can have a single comment pattern,
00140 and a new one with the same key replaces the
00141 older one with that key.
00142 
00143 =item   C<cmnt>
00144 
00145 A hash reference to a list of keys and comment
00146 recognition patterns.
00147 The patterns must each have a single returned
00148 value (C<$1>), that is to say, they must each
00149 return the comment text found.
00150 The keys are filter names, (e.g. C<Batch>).
00151 Each key can have a single comment pattern,
00152 and a new one with the same key replaces the
00153 older one with that key.
00154 
00155 =item   C<docs>
00156 
00157 A hash reference to a list of keys and suffixes.
00158 The keys are filter names, for example C<POD>
00159 invokes C<Doxygen::POD::Filter>.
00160 Each key can have a single suffix pattern,
00161 and a new one with the same key replaces the
00162 older one with that key.
00163 
00164 =item   C<pass>
00165 
00166 An array reference to a list of suffixes that should be
00167 passed through unprocessed.
00168 Values are cumulative with the default value (C<qr(\.doxy?)i>)
00169 but can be overidden by setting C<docs>.
00170 
00171 =item   C<spawn>
00172 
00173 Hash reference from document types to command-line invocations.
00174 Define the suffix and document type in C<docs> then define
00175 the spawning command line using the document type name as the key.
00176 The command line can have C<{}> as a placeholder for the pathname
00177 of the file to be processed or it will be appended to the end.
00178 
00179 =back
00180 
00181 =item   C<path>
00182 
00183 Pathname of file to be parsed into the object.
00184 Calls C<Parse()> method with the value after
00185 other initialization.
00186 The same can be done separately.
00187 
00188 =item   C<stats>
00189 
00190 Turns statistics generation on or off.
00191 Defaults to on, set to non-true value to override.
00192 
00193 =item   C<trace>
00194 
00195 Turns on generation of tracing ([T]) and hacking
00196 ([H]) messages.
00197 
00198 =back
00199 
00200 Takes a pathname (C<$path>) as an argument.
00201 During the construction of the object parses the
00202 file thus specified using as many applicable
00203 filters are possible.
00204 
00205 If no filters apply, returns C<undef> to indicate
00206 that other action is required
00207 (the file needs to be copied through).
00208 
00209 In the latter case, if the pathname doesn't match
00210 one of the 'pass through' patterns a warning is logged.
00211 
00212 =cut
00213 
00214 sub new
00215 {
00216     my ($class, %flags) = @_;
00217     my  $self  = bless \%flags, $class;
00218     
00219     # Fixup comment type suffix patterns:
00220     
00221     my  %alias = TYPE_ALIAS;
00222     
00223     if (isa($self->{type}->{alias}, 'HASH')) {
00224         $alias{$_} = $self->{type}->{alias}->{$_}
00225             for keys %{$self->{type}->{alias}};
00226     }
00227     
00228     $self->{type}->{alias} = \%alias;
00229     
00230     # Fixup filter check patterns:
00231     
00232     my  %chck = TYPE_CHCK;
00233     
00234     if (isa($self->{type}->{chck}, 'HASH')) {
00235         $chck{$_} = _filterPattern_($self->{type}->{chck}->{$_})
00236             for keys %{$self->{type}->{chck}};
00237     }
00238 
00239     $self->{type}->{chck} = \%chck;
00240     
00241     # Fixup comment type suffix patterns:
00242     
00243     my  %cmnt = TYPE_CMNT;
00244     
00245     if (isa($self->{type}->{cmnt}, 'HASH')) {
00246         $cmnt{$_} = _suffixPattern_($self->{type}->{cmnt}->{$_})
00247             for keys %{$self->{type}->{cmnt}};
00248     }
00249 
00250     $self->{type}->{cmnt} = \%cmnt;
00251     
00252     # Fixup document type suffix patterns:
00253 
00254     my  %docs = TYPE_DOCS;
00255 
00256     if (isa($self->{type}->{docs}, 'HASH')) {
00257         $docs{$_} = _suffixPattern_($self->{type}->{docs}->{$_})
00258             for keys %{$self->{type}->{docs}};
00259     }
00260     
00261     $self->{type}->{docs} = \%docs;
00262     
00263     my  %flag = TYPE_FLAG;
00264     
00265     if (isa($self->{type}->{flag}, 'HASH')) {
00266         $flag{$_} = _flagValue_($self->{type}->{flag}->{$_})
00267             for keys %{$self->{type}->{flag}};
00268     }
00269     
00270     $self->{type}->{flag} = \%flag;
00271     
00272     # Fixup pass-through suffix patterns:
00273 
00274     my  @pass = TYPE_PASS;
00275 
00276     push @pass, map { _suffixPattern_($_) } @{$self->{type}->{pass}}
00277         if isa $self->{type}->{pass}, 'ARRAY';
00278 
00279     $self->{type}->{pass} = \@pass;
00280     
00281     # Fixup process spawn patterns:
00282     
00283     my  %spawn = TYPE_SPAWN;
00284     
00285     if (isa($self->{type}->{spawn}, 'HASH')) {
00286         $spawn{$_} = $self->{type}->{spawn}->{$_}
00287             for keys %{$self->{type}->{spawn}};
00288     }
00289     
00290     $self->{type}->{spawn} = \%spawn;
00291     
00292     $self->{stats} = 1
00293         unless exists $self->{stats};
00294     
00295     # Parse (if necessary) and return self unless parse fails:
00296     
00297     $self->{path} ? $self->parse : $self
00298 }
00299     
00300 ###########################################################################
00301 
00302 sub DESTROY     # $self
00303 {
00304     $_[0]->popLog;
00305 }
00306 
00307 ###########################################################################
00308 ###########################################################################
00309 
00310 =item   C<parse($self [ , $path ])>
00311 
00312 Parse the specified source file.
00313 
00314 Applies all appropriate parsers the the source file.
00315 Each parser is able to store information on itself
00316 or this C<Doxygen::Source> object.
00317 
00318 =cut
00319 
00320 sub parse
00321 {
00322     my  $self = shift;
00323     my  $path = shift || $self->{path};
00324     
00325     unless ($path && -f $path) {
00326         $self->log('E', 'No viable source path to be parsed!',
00327                    ($path ? "\n  $path" : ''));
00328         return undef;
00329     }
00330     
00331     for my $docType (keys %{$self->{type}->{spawn}}) {
00332         return $self->spawn($docType, $path)
00333             if isa($self->{type}->{docs}->{$docType}, 'Regexp')
00334             && $path =~ $self->{type}->{docs}->{$docType};
00335     }
00336     
00337     # Create the file object immediately:
00338     local   $/ = undef; # slurp file
00339 
00340     unless (open(SOURCE, '<', $self->{path})) {
00341         $self->log('E', "Unable to open source file:\n    ",
00342                    $self->{path}, "\n  $!\n");
00343         return undef;
00344     }
00345 
00346     my  $text = <SOURCE>;
00347     
00348     close SOURCE;
00349     
00350     unless ($text && $text =~ /\S/) {
00351         $self->log('E', "Empty source file:\n    ", $self->{path}, "\n");
00352         return undef;
00353     }
00354     
00355     # OK, the file exists,
00356     #   create the first entity to represent the file:
00357     
00358     local   $SIG{__WARN__} = sub {  $self->_warning_(shift) };
00359 
00360     $self->log('I', 'File:  ', $self->{path}, "\n")->pushLog;
00361     
00362     my  $found = 0;
00363         
00364     $self = eval {
00365         $self->{entity} = [ $self->getFile($self->{path}) ];
00366 
00367         # Check for all kinds of parsers that might match the document:
00368         
00369         for ( # all registered doc types...
00370               keys(%{$self->{type}->{docs}}),
00371               # ...and all types that have check patterns...
00372               grep {    # ...and aren't a registered doc type...
00373                 ! $self->{type}->{docs}->{$_}
00374               } keys(%{$self->{type}->{chck}}) ) {
00375             # Check to see if we have a matching document type:
00376             next
00377                 unless ($self->{type}->{docs}->{$_}      &&
00378                         $self->{path} =~ $self->{type}->{docs}->{$_})
00379                     || ($self->{path} !~ /\.[^\/\\\.]*$/ &&
00380                         $self->{type}->{chck}->{$_}      &&
00381                         $text =~ $self->{type}->{chck}->{$_});
00382             
00383             eval {
00384                 # Safely create a filter for that document type:
00385                 my  $fAlias = $self->{type}->{alias}->{$_} || $_;
00386                 my  $fClass = "Doxygen::${fAlias}::Filter";
00387                 my  $filter = eval "use $fClass; new $fClass";
00388 
00389                 $@ && die "Error loading filter:\n  $@\n";
00390                 $filter || die "Unable to load filter:\n  $@\n";
00391                 
00392                 # Set comment pattern for filter
00393                 #   (by document type, not alias name):
00394                 
00395                 $filter->{cmnt} = $self->{type}->{cmnt}->{$_}
00396                     if $self->{type}->{cmnt}->{$_};
00397                 
00398                 # Parse file with the filter for this document type:
00399                 $filter->parse($text, $self);
00400                 
00401                 $found = 1
00402                     if $self->{stats}
00403                     && $filter->statistics($self);
00404                     
00405                 $self->{filters}->{$_} = $filter;
00406             };
00407 
00408             $@ && $self->log('E', "Error parsing ", $_, " document:\n    ",
00409                              $self->{path}, "\n  $@");
00410         }
00411         
00412         unless (keys %{$self->{filters}}) {
00413             ($self->{path} =~ $_ && return undef)
00414                 for @{$self->{type}->{pass}};
00415             
00416             $self->log('W', "Don\'t know how to filter document:\n    ",
00417                             $self->{path}, "\n");
00418             
00419             return undef
00420         }
00421         
00422         $self
00423     };
00424 
00425     die $@ if $@;
00426     
00427     if ($found) {
00428         my  @lines = split /\n/, $text;
00429         
00430         $self->log('.', 'Source total(', scalar(@lines), ')');
00431     }
00432     
00433     $self
00434 }
00435 
00436 ###########################################################################
00437 
00438 =item   C<spawn($self, $doctype, $path)>
00439 
00440 Spawn a sub-process via C<system()> to execute a program to handle
00441 the current path.
00442 
00443 =cut
00444 
00445 sub spawn
00446 {
00447     my ($self, $doctype, $path) = @_;
00448     
00449     $self->{spawned} = 1;
00450     
00451     my  $command = $self->{type}->{spawn}->{$doctype};
00452     
00453     unless ($command && $command =~ /\S/) {
00454         $self->log('W', 'Empty command for ', $doctype);
00455         
00456         return undef;
00457     }
00458 
00459     $command =~ s|\{\}|$path| or $command .= " $path";
00460     
00461     $self->log('I', 'Spawn: ', $command);
00462     
00463     my  $result = system $command;
00464     
00465     if ($result < 0) {
00466         $self->log('E', 'Unable to start ', $doctype, ' command:');
00467         $self->log('+', '    ', $command);
00468         $self->log('+', '  ', $!);
00469         
00470         return undef;
00471     }
00472     
00473     my  $exitValue  = $? >>  8;
00474     my  $signalNum  = $? & 127;
00475     my  $coreDumped = $? & 128;
00476     
00477     $self->log('W', 'Exit value:  ', $exitValue) if $exitValue;
00478     $self->log('W', 'Signal num:  ', $signalNum) if $signalNum;
00479     $self->log('W', 'Core dumped!')              if $coreDumped;
00480     $self
00481 }
00482 
00483 ###########################################################################
00484 ###########################################################################
00485 
00486 =item   C<massage($self)>
00487 
00488 Massage items in file after parsing and before generating.
00489 
00490 Each filter may have a C<massage> method and/or a C<parse> method.
00491 The order of parsing and massaging is undefined except that
00492 I<all> parsing will complete prior to I<any> massaging being done.
00493 
00494 For the C<Source> object, C<massage> must iterate through the
00495 set of filters created during the C<parse> phase and call the
00496 C<massage> method on each one.
00497 
00498 =cut
00499 
00500 sub massage
00501 {
00502     my  $self = shift;
00503     
00504     return if $self->{spawned};
00505     
00506     local   $SIG{__WARN__} = sub {  $self->_warning_(shift) };
00507     
00508     # Massage all of the filters:
00509     $_->massage($self)
00510         for values %{$self->{filters}};
00511     
00512     # Massage the file:
00513     $self->getFile->massage($self);
00514 }
00515 
00516 ###########################################################################
00517 ###########################################################################
00518 
00519 =item   C<generate($self, %flags)>
00520 
00521 Generates output understandable by doxygen to standard output.
00522 
00523 Should be run after running C<massage()>.
00524 
00525 Must be overloaded by derived subclasses.
00526 
00527 =cut
00528 
00529 sub generate
00530 {
00531     my  $self = shift;
00532     
00533     return if $self->{spawned};
00534     
00535     local   $SIG{__WARN__} = sub {  $self->_warning_(shift) };
00536     
00537     $self->getFile->generate(@_, source => $self);
00538     $self->SUPER::generate  (@_, source => $self);
00539 }
00540 
00541 ###########################################################################
00542 ###########################################################################
00543 
00544 =item   C<entity($self)>
00545 
00546 Return the top node from the entity stack.
00547 
00548 The entity stack is for source entities.
00549 The stack always starts with a Doxygen::Item::File object to
00550 represent the file being parsed.
00551 Other objects that may be placed on the stack :
00552 
00553 <ul>
00554 <li>Doxygen::Item::Class
00555 <li>Doxygen::Item::Function
00556 </ul>
00557 
00558 In general a file object will be on the bottom,
00559 then a class object (if applicable) and finally
00560 a function object.
00561 
00562 =cut
00563 
00564 sub entity
00565 {
00566     $_[0]->{entity}->[0]
00567 }
00568 
00569 ###########################################################################
00570 
00571 =item   C<entityPop($self [ , $entity ] )>
00572 
00573 Pop the top entity from the entity stack.
00574 
00575 If the C<$entity> argument is defined,
00576 pop all entities down to and including that specified.
00577 
00578 =cut
00579 
00580 sub entityPop    # $self [ , $entity ]
00581 {
00582     my ($self, $entity) = @_;
00583     
00584     if ($entity) {
00585         while (my $popped = shift @{$self->{entity}}) {
00586             last if $popped == $entity;
00587         }
00588     } else {
00589         shift @{$self->{entity}};
00590     }
00591 }
00592 
00593 ###########################################################################
00594 
00595 =item   C<entityPush($self, $entity)>
00596 
00597 Push a new current entity on the stack.
00598 
00599 The stack starts with just the file object.
00600 
00601 =cut
00602 
00603 #=| \param  $entity The entity to be pushed onto the stack.
00604 
00605 sub entityPush   # $self, $entity
00606 {
00607     my  $self = shift;
00608     
00609     unshift @{$self->{entity}}, shift
00610 }
00611 
00612 ###########################################################################
00613 ###########################################################################
00614 
00615 =item   C<flag($self, $name [ , $docType ])>
00616 
00617 Return value of named flag in source context.
00618 
00619 Flags are specified at source creation.
00620 Flags are named either C<docType::flagName> or C<flagName>.
00621 The former describe flags specific to document types
00622 (filter types) and only visible to filters of the specified
00623 document type.
00624 In addition, the former, where applicable, override the latter.
00625 The latter are global to all filters and act as global flags
00626 and/or default values for specific flags.
00627 
00628 When a flag is requested by name, if a C<$docType>
00629 is specified it will be used to check for a filter-specific
00630 value first, then for the global value.
00631 The argument should be either the name of a filter class
00632 or an object of a filter class.
00633 
00634 The C<$name> argument should never specify names
00635 of the form C<docType::flagName>, as that is specified
00636 via the optional C<$docType> parameter.
00637 
00638 =cut
00639 
00640 sub flag
00641 {
00642     my ($self, $name, $doctype) = @_;
00643     
00644 #   $self->log('T', __PACKAGE__, '::flag(', $name, ', ', $doctype, ')');
00645     
00646     if ($doctype && isa($doctype, 'Doxygen::Filter')) {
00647         my  $filtype = ref($doctype) || $doctype;
00648         
00649 #       $self->log('T', 'fTyp:  ', $filtype);
00650         
00651         if ($filtype =~ /Doxygen::(.*)::Filter/) {
00652             my  $name = "$1::$name";
00653             
00654 #           $self->log('T', 'name:  ', $name);
00655 
00656             return $self->{type}->{flag}->{$name}
00657                 if exists $self->{type}->{flag}->{$name};
00658         }
00659         
00660         if (ref($doctype)) {
00661             my  $flag = $doctype->flags;
00662             
00663 #           $self->log('T', 'flag:  ', $flag);
00664 #           $self->log('T', '  ', $_, ' => ', $flag->{$_}) for keys %$flag;
00665 #           $self->log('T', 'valu:  ', $flag->{$name});
00666             
00667             return $flag->{$name}
00668                 if exists $flag->{$name};
00669         }
00670     }
00671     
00672 #   $self->log('T', 'valu=  ', $self->{type}->{flag}->{$name});
00673     
00674     $self->{type}->{flag}->{$name}
00675 }
00676 
00677 ###########################################################################
00678 ###########################################################################
00679 
00680 =item   C<focus($self)>
00681 
00682 Return the current focus for adding comment lines.
00683 
00684 Defaults to the value for the current source entity,
00685 but may be overridden by descendant classes modelling
00686 language-specific documentation entities.
00687 
00688 =cut
00689 
00690 #=| \return A doxy::Item object.
00691 
00692 sub focus
00693 {
00694     $_[0]->entity
00695 }
00696 
00697 ###########################################################################
00698 ###########################################################################
00699 
00700 =item   C<getFile($self [ , $path ] )>
00701 
00702 Get file object for this filter object,
00703 creating object if necessary.
00704 
00705     my  $file = $target->getFile($path);
00706 
00707 The file object should be created early using the path so that it can
00708 be referred to freely without the pathname later:
00709 
00710     $doc->getFile->append($text);
00711 
00712 =cut
00713 
00714 sub getFile
00715 {
00716     my  $self = shift;
00717     
00718     unless (isa($self->{file}, 'Doxygen::Item::File')) {
00719         my  $path = shift;
00720         
00721         return
00722             unless $path
00723                 && $path =~ /\S/;
00724 
00725         # This makes Doxygen::Test work,
00726         #   but it could be considered non-optimal
00727         #   (then again, why would we ever need it otherwise?):
00728         $path =~ s|\.\./||g;
00729 
00730         $self->{file} = new Doxygen::Item::File(path => $path)
00731     }
00732     
00733     $self->{file}
00734 }
00735 
00736 ###########################################################################
00737 ###########################################################################
00738 
00739 =item   C<log($self, $code, @stuff)>
00740 
00741 Formatted logging function.
00742 
00743 The C<$code> is a single-character from the following set:
00744 
00745 =over
00746 
00747 =item   I
00748 
00749 Info
00750 
00751 =item   T
00752 
00753 Trace
00754 
00755 =item   W
00756 
00757 Warning
00758 
00759 =item   E
00760 
00761 Error
00762 
00763 =back
00764 
00765 =cut
00766 
00767 sub log
00768 {
00769     my  $self = shift;
00770     my  $code = shift || 'T';
00771     
00772     return $self    # hacking and tracing messages default off
00773         if ($code eq 'H' || $code eq 'T')
00774         && ! $self->{trace};
00775     
00776     return $self    # information messages default on
00777         if $code eq 'I'
00778         && exists $self->{info}
00779         && ! $self->{info};
00780     
00781     my  $indent = isa($self->{logIndent}, 'ARRAY') && @{$self->{logIndent}}
00782                 ? $self->{logIndent}->[0]
00783                 : '';
00784     
00785     for (split(/\n/, join('', map {
00786                 defined($_) ? $_ : '<undef>'
00787             } @_, "\n"))) {
00788         print STDERR "[$code]$indent $_\n";
00789         $code = '+' unless $code eq '+';
00790     }
00791     
00792     $self
00793 }
00794 
00795 ###########################################################################
00796 
00797 =item   C<popLog($self)>
00798 
00799 Pop the last indentation level from the logging stream.
00800 
00801 =cut
00802 
00803 sub popLog      # $self
00804 {
00805     my  $self = shift;
00806     
00807     shift @{$self->{logIndent}}
00808         if isa($self->{logIndent}, 'ARRAY')
00809         && @{$self->{logIndent}};
00810     
00811     $self
00812 }
00813 
00814 ###########################################################################
00815 
00816 =item   C<pushLog($self [ , $spaces ] )>
00817 
00818 Indent the logging functionality accessible via log().
00819 
00820 Specify the C<$spaces> (as the actual indentation string) or it defaults to 2.
00821 
00822 =cut
00823 
00824 sub pushLog     # $self [ , $spaces ]
00825 {
00826     my  $self = shift;
00827     
00828     $self->{logIndent} = [ ]
00829         unless isa $self->{logIndent}, 'ARRAY';
00830     
00831     unshift @{$self->{logIndent}},
00832             ((@{$self->{logIndent}} ? $self->{logIndent}->[0] : '')
00833              . (shift || '  '));
00834     
00835     $self
00836 }
00837 
00838 ###########################################################################
00839 
00840 =item   C<_warning_($self, $stuff)>
00841 
00842 Special logging call used for trapping warnings.
00843 
00844 Breaks up standard warning text so it doesn't overwrite lines in log.
00845 
00846 =cut
00847 
00848 #=| @internal
00849 
00850 sub _warning_
00851 {
00852     my ($self, $stuff) = @_;
00853     
00854     $stuff =~ s/\b(at\s+[\w\.\\\/]+\s*line\s+\d+)/\n $1/;
00855     
00856     $self->log('W', $stuff)
00857 }
00858 
00859 ###########################################################################
00860 ###########################################################################
00861 
00862 =item   C<_commentPattern_($string)>
00863 
00864 Convert a string into a pattern for recognizing a comment.
00865 
00866 =cut
00867 
00868 #=| @todo   handle qr()im flags
00869 
00870 sub _commentPattern_
00871 {
00872     isa($_[0], 'Regexp')    ? $_[0]  :
00873     $_[0] =~ /^qr\((.*)\)$/ ? qr($1) : qr(^\s*$_[0] ?(.*)$)m
00874 }
00875 
00876 ###########################################################################
00877 
00878 =item   C<_filterPattern_($string)>
00879 
00880 Convert a string into a pattern for recognizing a comment.
00881 
00882 =cut
00883 
00884 #=| @todo   handle qr()im flags
00885 
00886 sub _filterPattern_
00887 {
00888     isa($_[0], 'Regexp')    ? $_[0]  :
00889     $_[0] =~ /^qr\((.*)\)$/ ? qr($1) : qr(^$1)
00890 }
00891 
00892 ###########################################################################
00893 
00894 =item   C<_flagValue_($string)>
00895 
00896 Evaluate a string (or pattern) representing a flag value.
00897 
00898 =cut
00899 
00900 #=| @todo   handle qr()im flags
00901 
00902 sub _flagValue_
00903 {
00904     isa($_[0], 'Regexp')    ? $_[0]    :
00905     $_[0] =~ /^qr\((.*)\)$/ ? qr(^$1$) : $_[0]
00906 }
00907 
00908 ###########################################################################
00909 
00910 =item   C<_suffixPattern_($string)>
00911 
00912 Convert a string into a pattern for recognizing a suffix.
00913 
00914 =cut
00915 
00916 #=| @todo   handle qr()i flag
00917 
00918 sub _suffixPattern_
00919 {
00920     isa($_[0], 'Regexp')    ? $_[0]  :
00921     $_[0] =~ /^qr\((.*)\)$/ ? qr($1) : qr(\.$_[0])i
00922 }
00923 
00924 ###########################################################################
00925 ###########################################################################
00926 
00927 1
00928 
00929 __END__
00930 
00931 =back
00932 
00933 =head1 SEE ALSO
00934 
00935 DoxyFilt.pl Doxygen::Filter
00936 
00937 =head1 AUTHOR
00938 
00939 Marc M. Adkins, L<mailTo:Perl@Doorways.org>
00940 
00941 =head1 COPYRIGHT AND LICENSE
00942 
00943 Copyright 2004-2010 by Marc M. Adkins
00944 
00945 This library is free software; you can redistribute it and/or modify
00946 it under the same terms as Perl itself.
00947 
00948 =cut

Generated on Mon Dec 27 2010 15:15:39 for DoxyFilt by  doxygen 1.7.1

www.dimension.org logo

(C)opyright 1998 - 2012 Dimension.org

WebMaster