File Coverage

blib/lib/HTML/CMTemplate.pm
Criterion Covered Total %
statement 845 1002 84.3
branch 135 222 60.8
condition 49 89 55.0
subroutine 101 118 85.5
pod 0 9 0.0
total 1130 1440 78.4


line stmt bran cond sub pod time code
1             package HTML::CMTemplate;
2              
3 8     8   14745 use strict;
  8         19  
  8         371  
4 8     8   47 use vars qw($VERSION);
  8         15  
  8         520  
5              
6             $VERSION = '0.4.0';
7              
8 8     8   48 use vars qw($DEBUG $DEBUG_FILE_NAME $DEBUG_FUNCTION_REF);
  8         14  
  8         1709  
9             $DEBUG = 0;
10             $DEBUG_FILE_NAME = '';
11             $DEBUG_FUNCTION_REF = undef;
12              
13             =head1 NAME
14              
15             HTML::CMTemplate.pm - Generate text-based content from templates.
16              
17             =head1 SYNOPSIS
18              
19             use HTML::CMTemplate;
20              
21             $t = new HTML::CMTemplate( path => [ '/path1', '/longer/path2' ] );
22              
23             $t->import_template(
24             filename => 'file.html.ctpl', # in the paths above
25             packagename => 'theTemplate',
26             importrefs => { myvar => 'hello' },
27             importclean => { myclean => 'clean!' },
28             );
29              
30             theTemplate::cleanup_namespace();
31              
32             print "Content-type: text/html\n\n";
33             print theTemplate::output();
34              
35             # Template syntax is described below -- see that section to get the real
36             # details on how to use this sucker.
37              
38             =head1 DESCRIPTION
39              
40             HTML::CMTemplate 0.4.0
41              
42             A class for generating text-based content from a simple template language.
43             It was inspired by the (as far as I'm concerned, incomplete) HTML::Template
44             module, and was designed to make template output extremely fast by
45             converting a text/html template into a dynamic perl module and then running
46             code from that module. Since the parsing happens only once and the template
47             is converted into Perl code, the output of the template is very fast.
48              
49             It was designed to work with mod_perl and FastCGI and has been the basis
50             for all of the dynamic content on the Orangatango site
51             (http://www.orangatango.com).
52              
53             First release (version 0.1) was February 15, 2001 and was I quiet
54             because it was a proprietary version.
55              
56             As of version 0.2, it is released under the Artistic License. It's a much
57             more feature-rich version as well as being Open Source!
58             For a copy of the Artistic License, see the files that came with your
59             Perl distribution.
60              
61             The code was developed during my time at Orangatango. It has been released
62             as open source with the blessing of the controlling entities there.
63              
64             =head1 AUTHOR
65              
66             Chris Monson, shiblon@yahoo.com
67              
68             =head2 DEBUG OUTPUT
69              
70             You can coerce the template engine into spitting out debugging
71             information for every step of the parsing process. This behavior can be
72             controlled by the following variables:
73              
74             $HTML::CMTemplate::DEBUG = 1; # Do this, and debugging will be turned on
75             $HTML::CMTemplate::DEBUG_FILE_NAME = 'filename'; # Defaults to STDERR
76             $HTML::CMTemplate::DEBUG_FUNCTION_REF = $ref;
77              
78             The debug function reference is used for every debug step. It is passed
79             three parameters: the name of the function being debugged, a string,
80             and an array ref. If the array is non-empty, it
81             contains the arguments to a function that is being debugged.
82             If the string is non-empty, it contains a message.
83              
84             Note that this is of dubious utility. The debug functions are mostly for
85             my own internal use to see where the template parser goes wrong. They
86             do not detect bad template syntax, and they will be of no use to people
87             just making use of the template parser. Really. My advice is to leave the
88             debug parameters alone. You don't need them.
89              
90             =head2 TEMPLATE SYNTAX
91              
92             The template syntax that this parser recognizes has a few tags that look
93             a little like php or xml syntax, except that they are different. The tags
94             all start with . If the next character after ?> is a
95             newline, it is also eaten up with the tag, just like in PHP. This gives you
96             very fine grained control over the actual template output, and is especially
97             important when using loops to generate output.
98              
99             Note that if you want to actually output those symbols in your code, or you
100             want to access them inside of a tag, I have created two global variables that
101             contain those strings: $START_SYM and $END_SYM. So, to print something
102             like inside of your template, you would do this:
103              
104             hello
105              
106             Or, if you use the shortcut (all explained below), you would do this:
107              
108             hello
109              
110             An explanation follows of the different constructs that the engine uses.
111              
112             I
113              
114             The I construct is just a single tag. The whole tag is eaten
115             by the template engine and is never seen again. This simply serves
116             as a comment in the template itself.
117              
118            
119              
120             I
121              
122             The I construct supports two tags:
123              
124            
125            
126              
127             The second tag is a handy shortcut for the first, and works like its
128             corresponding PHP tag. Both are replaced with the value of the evaluated
129             expression. This is by far the most used construct, since usually the
130             result of an expression simply needs to be inserted into the appropriate place.
131              
132             Example:
133              
134             ...
135             <?=$document_title?>
136             ...
137              
138             This could also be written as
139              
140             ...
141             <?=echo $document_title?>
142             ...
143              
144             Both will replace the tag with the contents of the $document_title variable.
145              
146             But, where does $document_title come from? Going back to the synopsis, if
147             you do something like this in your perl script:
148              
149             $t->import_template(
150             filename => 'thetemplate.html.ctpl',
151             packagename => 'theTemplate',
152             );
153              
154             Then you can set the variable in the newly-created package (There is no
155             need to do a 'use' or a 'require' or anything. The package is created
156             when you call the import_template function and is thereafter available).
157              
158             You create the variable thus:
159              
160             $theTemplate::document_title = "My Document Title";
161              
162             Then to output the template, you would do something like this:
163              
164             print "Content-type: text/html\n";
165             print "\n";
166             print theTemplate::output();
167              
168             Note that the import_template function does not import the template again
169             if it detects that the template or any of its includes (see below) have not
170             changed. This is an optimization to reduce needless parsing, since once
171             the template is in memory, you can use it over and over again with new
172             variables by just changing the variable values in the package namespace.
173              
174             NOTE: This behavior can be changed by setting the
175             $t->{checkmode} variable to $HTML::CMTemplate::CHECK_NONE.
176              
177             So, if I wanted to output the template again with a new title, I could simply
178             do the following:
179              
180             $theTemplate::document_title = "My NEW Document Title";
181             print "Content-type: text/html\n";
182             print "\n";
183             print theTemplate::output();
184              
185             Note that an import_template was not necessary again, since the template
186             was converted into code and all we wanted to do was change a variable.
187              
188             Again, if you do call import_template on the same object ($t in the examples)
189             more than once, it will only actually parse the template once, unless you
190             change it on disk in between import_template calls.
191              
192             I
193              
194             The I construct supports several tags, some of which are reused in the
195             I construct:
196              
197            
198            
199            
200            
201              
202             These tags do basically what you would expect them to do. Note that none
203             of the expressions require surrounding parentheses. They do require terminating
204             colons, however. Whitespace is not important except between the tag name ('if')
205             and the expression.
206              
207             So, as an example of how you might do things:
208              
209            
210             TESTVAR set!
211            
212             TESTVAR NOT set!
213            
214              
215             The I tag works just like an elsif in Perl.
216              
217             I
218              
219             The I contruct supports several tags, as well. It works like Python's
220             I loop construct and has a similar syntax. In fact, all of these tags
221             borrowed some of their syntax from Python.
222              
223             The supported tags are as follows:
224              
225            
226            
227            
228            
229            
230              
231             These tags, with the exception of the 'else' tag (since it doesn't exist) do
232             what you would expect them to do in Perl. The 'for' and 'else' tags deserve
233             a little extra explanation since they are not real Perl syntax.
234              
235             The --varname-- is the name of a variable that will be assigned the value
236             of the current list item. The --list expression-- is an expression that
237             evaluates to a real Perl array (NOT an arrayref). Each item in the array will
238             be assigned to --varname-- in order. Here is an example. Assume for the sake
239             of this example that an array of integers 1 thru 10 named '@list' exists in
240             the package's namespace:
241              
242            
243            
244             Note that you can use either 'i' or '$i' here.
245             They are equivalent in the for tag. The echo tag
246             MUST use '$i' because it is outputting a perl
247             expression and is not specially parsed at all.
248             ?>
249            
250            
Number
251            
252            
Completed normally
253            
254            
255              
256             Note that you don't have to output HTML. Any kind of text can be output,
257             but HTML is what this was originally designed for.
258              
259             This will loop on the elements of @list, which contains the numbers 1 thru 10
260             in order. It will output the following code:
261              
262            
263            
Number 1
264            
Number 2
265            
Number 3
266            
Number 4
267            
Number 5
268            
Number 6
269            
Number 7
270            
Number 8
271            
Number 9
272            
Number 10
273            
Completed Normally
274            
275              
276             Note the extra table element at the end that says "Completed Normally". This
277             is inserted because of the I tag after the for block. Like in Python, the
278             code in the else tag is executed if the I loop is not terminated with a
279             I tag. If the for loop is terminated with a I tag, then the
280             I block will not execute.
281              
282             The I and I tags work as you would expect the corresponding
283             'last' and 'next' keywords to work in Perl.
284              
285             There are several functions to ease your way in I loops. They are listed
286             here:
287              
288             for_list( $depth )
289             for_index( $depth )
290             for_count( $depth )
291             for_is_first( $depth )
292             for_is_last( $depth )
293              
294             The for_list function gives you access to an arrayref of the list over which
295             the loop (or one of its containing loops, if $depth > 0) is iterating.
296              
297             The for_index function gives you a number from 0 to len-1, depending on where
298             you are in the actual loop.
299              
300             The for_count function gives you the number of elements over which you are
301             iterating.
302              
303             The for_is_first function tells you whether this is the first element, and the
304             for_is_last function tells you whether this is the last one.
305              
306             Note that all of these functions give you the ability to specify a depth. If
307             you have nested 'for' tags and you want to access the index, count, or list of
308             a containing 'for' loop, you can do that by specifying a depth parameter in the
309             function. No depth parameter or a value of 0 indicates that you want the
310             values for the current loop. A value of 1 would indicate that you want the
311             values for the immediately enclosing loop, etc.
312              
313             Example:
314             Suppose @xlist = (1, 2, 3) and @ylist = (2, 4, 6):
315              
316            
317            
318             , :: ,
319            
320            
321              
322             prints:
323             1,2 :: 0,0
324             1,4 :: 0,1
325             1,6 :: 0,2
326             2,2 :: 1,0
327             2,4 :: 1,1
328             2,6 :: 1,2
329             3,2 :: 2,0
330             3,4 :: 2,1
331             3,6 :: 2,2
332              
333             We can also tell if the current element is the first or last. Rather than
334             give an example for that simple case, it is left as an exercise for the reader.
335             A hint, however, is that you should use for_is_first and for_is_last (functions
336             that can also take a depth argument).
337              
338             As a side note, here, I should mention that tabbing loop and conditional
339             constructs does not work the way that you think it might inside of a template.
340             Since the only thing that is eaten up in a template is the tag itself, not
341             the preceding whitespace, usually you want the loop constructs and other
342             kinds of block constructs to be located all the way to the left side. This
343             will ensure that your spacing is really what you think it should be.
344              
345             I
346              
347             The tags this loop uses are as follows:
348              
349            
350            
351              
352             The I construct is a very simple loop that works like a standard
353             while loop in Perl. This is useful when you are potentially outputting a large
354             loop and don't want to get the entire contents of it into memory. The
355             expression in the while loop works just as you would expect it to. A true
356             value means to keep going, and a false one means to stop.
357              
358             As with all other block structures, you can put anything you like in the
359             body of a while construct.
360              
361             Example (assuming you have created appropriate function references):
362              
363             ():?>
364             ():?>
365            
366              
367             I
368              
369             The I construct is a very powerful little tool. It corresponds loosely
370             to Python's def in that it defines a sort of "template function" which can
371             be "called". An example will best illustrate this.
372              
373             By the way, the tags that are used by this construct are the following:
374              
375            
376            
377            
378              
379             Here is that promised example:
380              
381            
382             a =
383              
384             b =
385              
386             c =
387              
388            
389            
390            
391              
392             This will print the following:
393              
394             a = 1
395             b = 2
396             c = 3
397             a = 4
398             b = 5
399             c = 6
400              
401             I think it's pretty self-explanatory. Note that you can embed any number of
402             recursive constructs inside of not only the I tags, but also I and
403             I tags, along with their corresponding inner tags.
404              
405             B: No matter where a template subroutine is defined (def tag), the
406             subroutine ends up in the global package scope. All defs are global. Period.
407             This is by design and actually required a large amount of work to do, so
408             don't you go thinking that it's because I'm lazy ;-).
409              
410             The reasoning behind this is to keep namespace clashes from happening when
411             one template includes another. If the functions are treated differently
412             from other constructs (since Perl treats them differently anyway), namespace
413             collisions can be detected. Additionally, if one module includes two others,
414             each of which include the same module, the functions from that last module
415             are the same. Functions in the global scope keep these from wrongly stomping
416             on each other.
417              
418             I
419              
420             This one is somewhat dangerous, and should be used with great care.
421             It allows you to execute arbitrary Perl code inside of the tag.
422              
423            
424             $a = 1;
425             $b = 2;
426             $c = $a + $b;
427             print STDERR "Debug this output function!";
428             ?>
429              
430             This will set the variables just as you think it will, but it will
431             do it in a somewhat strange scope and you might get a bit confused. Look at
432             the code that is generated (by calling $t->output_perl()) to see
433             exactly what goes on.
434              
435             Note that the package that is created from this template explicitly declares
436             no strict 'vars', so the exec tag above will actually create global variables
437             in the package's namespace. You can also create 'my' variables, which is
438             really useful inside of loops.
439              
440             The best uses I have found for this tag are as follows:
441              
442             * Creating temporary variables or aliases to complicated variables.
443             * Creating 'my' variables inside of loops to improve efficiency.
444             * Outputing debug code using print STDERR "stuff" constructs.
445              
446             Beyond this, I have serious misgivings about the tag. Just be careful. Your
447             code will be inserted as is into the template code. Don't forget semicolons,
448             etc.
449              
450             I
451              
452             This includes another template where the tag is located. It tests for
453             infinite recursion and does not allow it. Also, note that this does NOT
454             take an arbitrary perl expression as a filename. It only takes strings.
455             The filename can be quoted with either single or double quotes.
456              
457             This parses the file just like any other template, looking for tags. If you
458             don't want the file parsed, use 'rawinc' instead.
459              
460             I
461              
462             Just like 'inc', but it doesn't parse the file. Simple.
463              
464             =head2 IMPORTED UTILITIES
465              
466             You have access to several functions. Most of the time you will only use
467             a couple of them, but there are several there for the sake of completeness and
468             sanity.
469              
470             I
471              
472             This is used to output the code given the current namespace. Simple. It
473             returns a string.
474              
475             I
476              
477             This is extremely useful for importing the variables from another namespace.
478             I routinely do the following:
479              
480             use CMCONFIG;
481             ...
482             theTemplate::import_hashref( \%CMCONFIG:: );
483              
484             You can also set up your own hashref of variables. This is useful for getting
485             form elements from CGI stuff:
486              
487             theTemplate::import_hashref( \%FORM );
488             theTemplate::import_hashref( { myvar => 'value' } );
489              
490             That would set all of the FORM data to be global variables (PHP style) in
491             the package, and it would additionally set $myvar to be 'value'.
492              
493             Note that you can pass an extra parameter (1 or 0) to indicate that you want
494             the variables imported into the 'clean' namespace. More on this later.
495              
496             I
497              
498             This deletes all variables from the package's namespace except those that
499             are designated 'clean'. Clean variables are the functions that are
500             automatically defined and the globals that are used by the package before
501             anything is done to it. They are also variables that have been imported and
502             marked 'clean'.
503              
504             This function is really important, especially in cases where the template is
505             being generated with fastcgi or mod_perl, since the modules will have their
506             variables maintained across page loads. That means that the previous user's
507             password (for example) could be available in the page. Bad, bad things happen
508             at that point.
509              
510             So, it is useful to call cleanup_namespace before using the template. It is
511             also useful to import things like system-wide configuration parameters into
512             the clean namespace, since these aren't sensitive to change and can take a
513             little extra time to import.
514              
515             I
516              
517             If you import a ton of variables and want to mark some of them clean, use this
518             function.
519              
520             =cut
521              
522 8     8   7313 use FileHandle;
  8         111138  
  8         52  
523 8     8   13673 use File::stat;
  8         66103  
  8         71  
524              
525             BEGIN {
526 8     8   24069 $HTML::CMTemplate::debugline = 1;
527             }
528              
529             package _NODE_;
530             $_NODE_::prepend = ' ';
531             $_NODE_::defprepend = 'ORANTEMPLATE_';
532              
533             sub new {
534 105     105   226 my $class = shift;
535 105         173 my $self = {};
536 105         229 bless $self, $class;
537 105         5417 $self->__init__(@_);
538 105         404 return $self;
539             }
540              
541             sub __prepend__ {
542 96     96   116 my $self = shift;
543 96   100     207 my $depth = shift || 0;
544 96         1328 return ($_NODE_::prepend x $depth);
545             }
546              
547             sub __init__ {
548 0     0   0 my $self = shift;
549 0         0 $self->parent( shift() );
550 0         0 $self->type( 'UNKNOWN' );
551             }
552              
553             sub __var__ {
554             # Performance critical, so we don't actually
555             # shift anything off. We also don't copy values around.
556             # Just check the length of the argument list. If it is
557             # longer than 2, then we have a value and we set stuff.
558             # 0 => self
559             # 1 => varname
560             # 2 => new value (if specified)
561 944 100   944   3764 $_[0]->{$_[1]} = $_[2] if @_==3;
562             # Return the value in either case
563 944         3102 $_[0]->{$_[1]}
564             }
565              
566             sub AUTOLOAD {
567 944 50   944   2477 return if $_NODE_::AUTOLOAD =~ /DESTROY$/o;
568             # Treat undefined functions as accessors.
569 944 100       1863 if (@_ > 1) {
570 456         1079 return $_[0]->__var__( $_NODE_::AUTOLOAD, $_[1] );
571             }
572             else {
573 488         1017 return $_[0]->__var__( $_NODE_::AUTOLOAD );
574             }
575             }
576              
577             package _TPL_;
578             @_TPL_::ISA = qw(_NODE_);
579             sub __init__ {
580 68     68   88 my $self = shift;
581 68         557 $self->parent( shift() );
582 68         325 $self->type( 'TPL' );
583 68         284 $self->text( '' );
584             # UNDEFINED:
585             # blk, tpl
586             }
587              
588             sub output_perl {
589 59     59   85 my $self = shift;
590 59         142 my %args = @_;
591 59   50     221 my $depth = $args{'depth'} || 0;
592 59         196 my $prepend = $self->__prepend__( $depth );
593 59         118 my $result = '';
594              
595 59         242 my $text = $self->text;
596 59         250 my $blk = $self->blk;
597 59         227 my $tpl = $self->tpl;
598 59         106 $text =~ s/\\/\\\\/g; # backslash all backslashes
599 59         78 $text =~ s/'/\\'/g; # backslash all single ticks
600 59 100 66     303 if (defined($text) && $text ne '') {
601 20         80 $result .= $prepend . "\$\$_RESULT_ .= '" . $text . "';\n";
602             }
603 59 100       138 if ($blk) {
604 30         100 $result .= $blk->output_perl( @_ );
605             }
606 59 100       283 if ($tpl) {
607 31         262 $result .= $tpl->output_perl( @_ );
608             }
609              
610 59         2691 return $result;
611             }
612              
613             package _IF_;
614             @_IF_::ISA = qw(_NODE_);
615             sub __init__ {
616 6     6   9 my $self = shift;
617 6         34 $self->parent( shift() );
618 6         31 $self->type( 'blkIF' );
619 6         33 $self->expr( '' );
620 6         600 $self->tpl( _TPL_->new( $self->parent ) );
621             # UNDEFINED
622             # nextif
623             }
624              
625             sub output_perl {
626 6     6   138 my $self = shift;
627 6         15 my %args = @_;
628 6   50     24 my $depth = $args{'depth'} || 0;
629 6         26 my $prepend = $self->__prepend__( $depth );
630 6         11 my $result = '';
631              
632 6         104 my $nextif = $self->nextif;
633 6         28 $result .= $prepend . "if (" . $self->expr . ") {\n"
634             . $self->tpl->output_perl( depth => $depth + 1 ) . "$prepend}\n";
635              
636 6 100       19 if ($nextif) {
637 3         10 $result .= $nextif->output_perl( @_ );
638             }
639              
640 6         19 return $result;
641             }
642              
643             package _ELIF_;
644             @_ELIF_::ISA = qw(_NODE_);
645             sub __init__ {
646 2     2   3 my $self = shift;
647 2         13 $self->parent( shift() );
648 2         12 $self->type( 'blkELIF' );
649 2         10 $self->expr( '' );
650 2         9 $self->tpl( _TPL_->new( $self->parent ) );
651             # UNDEFINED
652             # nextif
653             }
654              
655             sub output_perl {
656 2     2   9 my $self = shift;
657 2         5 my %args = @_;
658 2   50     9 my $depth = $args{'depth'} || 0;
659 2         10 my $prepend = $self->__prepend__( $depth );
660 2         6 my $result = '';
661              
662 2         12 my $nextif = $self->nextif;
663 2         15 $result .= $prepend . "elsif (" . $self->expr . ") {\n" .
664             $self->tpl->output_perl( depth => $depth + 1 ) . "$prepend}\n";
665              
666 2 50       8 if ($nextif) {
667 2         6 $result .= $nextif->output_perl( @_ );
668             }
669              
670 2         7 return $result;
671             }
672              
673             package _ELSE_;
674             @_ELSE_::ISA = qw(_NODE_);
675             sub __init__ {
676 5     5   8 my $self = shift;
677 5         39 $self->parent( shift() );
678 5         32 $self->type( 'blkELSE' );
679 5         22 $self->tpl( _TPL_->new( $self->parent ) );
680             }
681              
682             sub output_perl {
683 3     3   5 my $self = shift;
684 3         6 my %args = @_;
685 3   50     9 my $depth = $args{'depth'} || 0;
686             # If this is not an 'if' block, we need to only print out the
687             # template, not the surrounding context.
688 3         12 my $prepend = $self->__prepend__( $depth );
689 3         9 my $result = '';
690              
691 3         17 my $nextif = $self->nextif;
692 3         16 $result .= $prepend . "else {\n" .
693             $self->tpl->output_perl( depth => $depth + 1 ) . "$prepend}\n";
694              
695 3         10 return $result;
696             }
697              
698             package _FOR_;
699             @_FOR_::ISA = qw(_NODE_);
700             sub __init__ {
701 3     3   6 my $self = shift;
702 3         18 $self->parent( shift() );
703 3         16 $self->type( 'blkFOR' );
704 3         18 $self->varname( '' );
705 3         14 $self->listexpr( '' );
706 3         13 $self->tpl( _TPL_->new( $self->parent ) );
707             # UNDEFINED
708             # default
709             }
710              
711             sub output_perl {
712 3     3   4 my $self = shift;
713 3         8 my %args = @_;
714 3   50     9 my $depth = $args{'depth'} || 0;
715 3         9 my $prepend = $self->__prepend__( $depth );
716 3         9 my $result = '';
717              
718 3         12 my $varname = $self->varname;
719 3         11 my $listexpr = $self->listexpr;
720 3         12 my $default = $self->default;
721              
722 3         10 $result .= $prepend . "push \@for_list, [$listexpr];\n";
723 3         6 $result .= $prepend . "push \@for_count, scalar(\@{\$for_list[\$#for_list]});\n";
724 3         7 $result .= $prepend . "push \@for_index, 0;\n";
725 3         5 $result .= $prepend . "TMPLLOOPBLK: {\n"; # only the loop goes in here
726 3         15 $result .= $prepend .
727             "foreach my \$$varname (\@{\$for_list[\$#for_list]}) {\n";
728 3         13 $result .= $self->tpl->output_perl( depth => $depth + 1 );
729 3         8 $result .= $prepend . "\$for_index[\$#for_index]++;\n";
730 3         4 $result .= $prepend . "}\n";
731              
732 3 100       9 if ($default) {
733             # Print out the 'else' block's template, not the else block itself.
734             # It is guaranteed to have a template.
735 2         9 $result .= $default->tpl->output_perl( @_ );
736             }
737 3         7 $result .= $prepend . "}\n"; # end the block first, then do other stuff
738 3         31 $result .= $prepend . "pop \@for_list;\n";
739 3         7 $result .= $prepend . "pop \@for_count;\n";
740 3         5 $result .= $prepend . "pop \@for_index;\n";
741              
742 3         10 return $result;
743             }
744              
745             package _WHILE_;
746             @_WHILE_::ISA = qw(_NODE_);
747             sub __init__ {
748 1     1   2 my $self = shift;
749 1         10 $self->parent( shift() );
750 1         12 $self->type( 'blkWHILE' );
751 1         11 $self->expr( '' );
752 1         4 $self->tpl( _TPL_->new( $self->parent ) );
753             }
754              
755             sub output_perl {
756 1     1   2 my $self = shift;
757 1         3 my %args = @_;
758 1   50     4 my $depth = $args{'depth'} || 0;
759 1         6 my $prepend = $self->__prepend__( $depth );
760 1         5 my $result = '';
761              
762 1         5 my $expr = $self->expr;
763              
764 1         4 $result .= $prepend . "TMPLLOOPBLK: {\n"; # only the loop goes in here
765 1         3 $result .= $prepend . "while ($expr) {\n";
766 1         5 $result .= $self->tpl->output_perl( depth => $depth + 1 );
767 1         3 $result .= $prepend . "}\n";
768 1         2 $result .= $prepend . "}\n";
769              
770 1         3 return $result;
771             }
772              
773             package _DEF_;
774             @_DEF_::ISA = qw(_NODE_);
775             sub __init__ {
776 1     1   3 my $self = shift;
777 1         8 $self->parent( shift() );
778 1         7 $self->type( 'blkDEF' );
779 1         31 $self->name( '' );
780 1         6 $self->argnames( [] );
781 1         4 $self->tpl( _TPL_->new( $self->parent ) );
782             }
783              
784             sub output_perl {
785 1     1   2 my $self = shift;
786 1         2 my %args = @_;
787 1   50     6 my $depth = $args{'depth'} || 0;
788 1         23 my $prepend = $self->__prepend__( $depth );
789 1         4 my $prepend2 = $self->__prepend__( $depth + 1 );
790 1         2 my $result = '';
791              
792 1         5 my $name = $self->name;
793 1         4 my $argnames = $self->argnames;
794              
795             # Create a function name that is not entirely intuitive and easy
796             # to confuse with others.
797 1         3 my $funcname = "$_NODE_::defprepend$name";
798              
799             # Create the code.
800 1         3 $result .= $prepend . "sub $funcname {\n";
801 1         3 $result .= $prepend2 . "my \$_RESULT_ = shift;\n";
802 1         6 foreach my $vname (@$argnames) {
803 3         9 $result .= $prepend2 . "my \$$vname = shift;\n";
804             }
805              
806             # Now print out the template stuff.
807 1         8 $result .= $self->tpl->output_perl( depth => $depth + 1 );
808 1         7 $result .= $prepend . "}\n";
809             }
810              
811             package _CALL_;
812             @_CALL_::ISA = qw(_NODE_);
813             sub __init__ {
814 2     2   3 my $self = shift;
815 2         16 $self->parent( shift() );
816 2         14 $self->type( 'blkCALL' );
817 2         10 $self->name( '' );
818 2         10 $self->argexpr( '' );
819             }
820              
821             sub output_perl {
822 2     2   4 my $self = shift;
823 2         8 my %args = @_;
824 2   50     7 my $depth = $args{'depth'} || 0;
825 2         12 my $prepend = $self->__prepend__( $depth );
826 2         10 my $result = '';
827              
828 2         12 my $name = $self->name;
829 2         12 my $argexpr = $self->argexpr;
830              
831 2         17 $result .= $prepend .
832             "$_NODE_::defprepend$name( \$_RESULT_,$argexpr);\n";
833             }
834              
835             package _BREAK_;
836             @_BREAK_::ISA = qw(_NODE_);
837             sub __init__ {
838 2     2   3 my $self = shift;
839 2         15 $self->parent( shift() );
840 2         15 $self->type( 'blkBREAK' );
841             }
842              
843             sub output_perl {
844 2     2   3 my $self = shift;
845 2         5 my %args = @_;
846 2   50     6 my $depth = $args{'depth'} || 0;
847 2         6 my $prepend = $self->__prepend__( $depth );
848 2         4 my $result = $prepend . "last TMPLLOOPBLK;\n";
849 2         5 return $result;
850             }
851              
852             package _CONTINUE_;
853             @_CONTINUE_::ISA = qw(_NODE_);
854             sub __init__ {
855 1     1   3 my $self = shift;
856 1         8 $self->parent( shift() );
857 1         7 $self->type( 'blkCONTINUE' );
858             }
859              
860             sub output_perl {
861 1     1   3 my $self = shift;
862 1         2 my %args = @_;
863 1   50     4 my $depth = $args{'depth'} || 0;
864 1         6 my $prepend = $self->__prepend__( $depth );
865 1         3 my $result = $prepend . "next;\n";
866 1         3 return $result;
867             }
868              
869             package _ECHO_;
870             @_ECHO_::ISA = qw(_NODE_);
871             sub __init__ {
872 12     12   18 my $self = shift;
873 12         194 $self->parent( shift() );
874 12         62 $self->type( 'blkECHO' );
875 12         73 $self->expr( '' );
876             }
877              
878             sub output_perl {
879 12     12   34 my $self = shift;
880 12         39 my %args = @_;
881 12   50     39 my $depth = $args{'depth'} || 0;
882 12         48 my $prepend = $self->__prepend__( $depth );
883 12         68 my $result = $prepend . "\$\$_RESULT_ .= (" . $self->expr . ");\n";
884 12         46 return $result;
885             }
886              
887             package _EXEC_;
888             @_EXEC_::ISA = qw(_NODE_);
889             sub __init__ {
890 1     1   1 my $self = shift;
891 1         14 $self->parent( shift() );
892 1         6 $self->type( 'blkEXEC' );
893 1         14 $self->expr( '' );
894             }
895              
896             sub output_perl {
897 1     1   2 my $self = shift;
898 1         2 my %args = @_;
899 1   50     3 my $depth = $args{'depth'} || 0;
900 1         5 my $prepend = $self->__prepend__( $depth );
901 1         3 my $prepend2 = $self->__prepend__( $depth + 1 );
902 1         3 my $result = $prepend . "# EXEC BLOCK -- COULD BE DANGEROUS\n";
903 1         4 $result .= $prepend2 . $self->expr . "\n";
904 1         3 $result .= $prepend . "# END EXEC BLOCK\n";
905 1         3 return $result;
906             }
907              
908             package _INC_;
909             @_INC_::ISA = qw(_NODE_);
910             sub __init__ {
911 1     1   2 my $self = shift;
912 1         8 $self->parent( shift() );
913 1         8 $self->type( 'blkINC' );
914 1         7 $self->filename( '' );
915             }
916              
917             sub output_perl {
918 1     1   1 my $self = shift;
919 1         3 my %args = @_;
920 1   50     4 my $depth = $args{'depth'} || 0;
921 1         6 my $prepend = $self->__prepend__( $depth );
922              
923             # Get the template from the global parsed table. Output the code,
924             # but only output the part without functions.
925 1         4 my $template = $self->parent->__get_parsed__( $self->filename );
926             # Don't do the full output_perl function, which adds a package and
927             # context. Just output the code (remember, we are accessing a
928             # template here, not a node).
929 1         5 return $template->output_perl_code( depth => $depth );
930             }
931              
932             #-------------------------------------------------------------------------------
933             # INIT
934             #-------------------------------------------------------------------------------
935             # Get back into the template package.
936             package HTML::CMTemplate;
937 8     8   101 use File::Spec;
  8         19  
  8         220  
938 8     8   59 use Cwd;
  8         22  
  8         100079  
939              
940             =pod
941              
942             =head2 FUNCTIONS
943              
944             I
945              
946             Creates an instance of the HTML::CMTemplate class. Potentially takes several
947             parameters.
948              
949             parent: Template which immediately "owns" this template. Should only be
950             used internally.
951              
952             root: Template at the top of the tree. Also internal use only.
953              
954             NOTE: NEVER use parent or root. NEVER do it! Don't! Jerk.
955              
956             path: An array ref of file paths. These paths will be searched when
957             non-absolute template filenames are given. Note that if a string
958             is passed in instead of an arrayref, it will be treated as a single
959             file path, not as a ':' or ';' delimited list of paths. If it has
960             illegal characters, the search will simply not work.
961              
962             NOTE that you do NOT need to include '.' explicitly. It will always
963             be checked FIRST before the listed directories.
964              
965             nocwd: 1 or 0. Tells the path parser to leave cwd out of it.
966              
967             =cut
968              
969             sub new {
970 9     9 0 8024 my $class = shift;
971 9         243 my $self = {};
972 9         33 bless $self, $class;
973 9         50 $self->__debug__;
974 9         39 $self->__init__(@_);
975 9         140 return $self;
976             }
977              
978             $HTML::CMTemplate::tagStart = '
979             $HTML::CMTemplate::tagEnd = '?>';
980             $HTML::CMTemplate::tagNameDefault = 'echo';
981              
982             $HTML::CMTemplate::tagStartLen = length($HTML::CMTemplate::tagStart);
983             $HTML::CMTemplate::tagEndLen = length($HTML::CMTemplate::tagEnd);
984              
985             $HTML::CMTemplate::CHECK_NONE = 0;
986             $HTML::CMTemplate::CHECK_STAT = 1;
987             # others should be added as necessary
988              
989             sub __init__ {
990 9     9   18 my $self = shift;
991 9         24 $self->__debug__;
992             # If this is the root template, it should NOT be passed a parent.
993             # Ever. Period. Don't ever, ever call the new function with a parent
994             # parameter. Let this module do that for includes only. You have been
995             # warned. Same goes for root.
996 9         149 my %args = @_;
997 9         61 $self->{parent} = $args{parent};
998 9         21 $self->{root} = $args{root};
999 9         53 $self->__set_path__( $args{path}, $args{nocwd} );
1000              
1001             # Make the path canonical (get rid of duplicates, make sure it is
1002             # not just a string, add the current working directory, etc).
1003              
1004             # This hashref holds the templates, indexed by module name. This allows
1005             # the module to determine whether a template is up to date or not.
1006             # If the template is not up to date, then it needs to be reloaded.
1007             # Otherwise, it should not be reloaded.
1008              
1009             # Note that the behavior of the reload function can be determined by setting
1010             # a variable in the object. By default, it checks the stat of the file
1011             # every time a call is made to import_template.
1012 9         170 $self->{imported} = {};
1013 9         43 $self->{checkmode} = $HTML::CMTemplate::CHECK_STAT; # check file mod date
1014              
1015             # Reset temporary variables (make sure they exist)
1016 9         83 $self->__reset_temp__;
1017             }
1018              
1019             # Make sure all paths are absolute and exist. Eliminate duplicates. Add cwd.
1020             sub __set_path__ {
1021 9     9   19 my $self = shift;
1022 9         26 my $path = shift;
1023 9   100     76 my $nocwd = shift || 0;
1024              
1025 9         26 my $r = ref( $path );
1026 9 100       52 if ($r ne 'ARRAY') {
1027 8 50       42 $path = (defined($path)) ? [$path] : [];
1028             }
1029              
1030             # Now we have an arrayref.
1031             # Go through each entry, making sure all pathnames are absolute. Ignore
1032             # any that are not. TODO: Do we die if they aren't?
1033             # Make sure the directories exist, dying if not (TODO: Should we die?)
1034             # Ignore duplicates (definitely do NOT die on duplicates).
1035             # Push the current working directory onto the front of the list.
1036              
1037             # Remember that
1038             # "There is a difference between knowing the path and walking the path."
1039             # - Morpheus
1040              
1041 9         20 my $rh_used = {}; # used path names
1042 9 100       30 unless ($nocwd) {
1043             # add the current working directory at the front.
1044 8         47249 unshift @$path, cwd();
1045             }
1046              
1047             # Add the paths if they make sense.
1048 9         302 foreach my $d (@$path) {
1049             # Ignore relative paths
1050 9         363 my $canondir = File::Spec->canonpath( $d );
1051 9 50       636 unless (File::Spec->file_name_is_absolute( $canondir )) {
1052 0         0 warn "Path $canondir is not absolute: Ignoring";
1053 0         0 next;
1054             }
1055             # Force existence
1056 9 50       473 unless (-d $canondir) {
1057 0         0 die "Path $canondir (in path list) is not found. Aborting.";
1058             }
1059             # ignore duplicates
1060 9 50       102 unless ($rh_used->{$canondir}) {
1061             # Add to the path list
1062 9         56 push @{$self->{path}}, $canondir;
  9         151  
1063 9         149 $rh_used->{$canondir} = 1;
1064             }
1065             }
1066             }
1067              
1068             sub __reset_temp__ {
1069 18     18   46 my $self = shift;
1070 18         166 $self->__debug__;
1071              
1072             # Tokenizing stuff
1073 18         143 $self->{strbuf} = '';
1074 18         79 $self->{parserintag} = 0;
1075 18         57 $self->{bufstart} = 0;
1076 18         43 $self->{buflen} = 0;
1077 18         46 $self->{tagstart} = 0;
1078              
1079             # Parsing stuff
1080 18         393 $self->{parentnode} = _TPL_->new( $self );
1081 18         272 $self->__push__( $self->{parentnode} );
1082 18         46 $self->{clean_defs} = [];
1083             # table of def tag parse trees. Since all defs are in the global
1084             # scope, we put them into a table rather than just leaving
1085             # them in the tree.
1086             # This table is local to each template.
1087 18         89 $self->{deftable} = {};
1088             # global list of all def names
1089 18         47 $self->{deftableglobal} = {};
1090             # table of parsed templates. Global and only accessed via __root__
1091 18         37 $self->{parsedtable} = {};
1092              
1093             # File stuff
1094 18         174 $self->{filename} = '';
1095 18         58 $self->{filemodtime} = '';
1096             }
1097              
1098             sub __reset_vars__ {
1099 0     0   0 my $self = shift;
1100 0         0 $self->{vars} = {};
1101             }
1102              
1103             sub __exists_file_package__ {
1104 8     8   19 my $self = shift;
1105 8         30 $self->__debug__(\@_);
1106 8         21 my ($file, $package) = @_;
1107 8         40 $self->__debug__(
1108             "File Package Index: " . __file_package_index__( $file, $package ) );
1109 8         16 while (my ($key, $val) = each( %{$self->{imported}} )) {
  8         122  
1110 0         0 $self->__debug__( "$key = $val" );
1111             }
1112 8         34 return $self->{imported}->{__file_package_index__($file, $package)};
1113             }
1114              
1115             sub __add_file_package__ {
1116 8     8   18 my $self = shift;
1117 8         39 $self->__debug__(\@_);
1118 8         24 my ($file, $package, $includes, $mtime) = @_;
1119 8         83 $self->{imported}->{__file_package_index__( $file, $package )} =
1120             {mtime => $mtime, includes => $includes};
1121             }
1122              
1123             sub __file_package_index__ {
1124 24     24   48 my ($filename, $packagename) = @_;
1125 24         265 return "$filename:-:$packagename";
1126             }
1127              
1128             sub __file_package_rec__ {
1129 0     0   0 my $self = shift;
1130 0         0 my ($file, $package) = @_;
1131              
1132 0         0 return $self->{imported}->{__file_package_index__($file, $package)};
1133             }
1134              
1135             sub __file_package_includes__ {
1136 0     0   0 my $self = shift;
1137 0         0 my ($file, $package) = @_;
1138 0         0 my $rec = $self->__file_package_rec__($file, $package)->{includes};
1139             }
1140              
1141             sub __file_package_mtime__ {
1142 0     0   0 my $self = shift;
1143 0         0 my ($file, $package) = @_;
1144              
1145 0         0 my $rec = $self->{imported}->{__file_package_index__($file, $package)};
1146 0         0 return $rec->{mtime};
1147             }
1148              
1149             # Get the mtime of an included template file
1150             sub __file_package_include_mtime__ {
1151 0     0   0 my $self = shift;
1152 0         0 my ($file, $package, $includefile) = @_;
1153              
1154 0         0 my $rec = $self->{imported}->{__file_package_index__($file, $package)};
1155 0         0 return $rec->{includes}->{$includefile};
1156             }
1157              
1158             sub __add_clean_defs__ {
1159 1     1   1 my $self = shift;
1160 1         3 my $ra_names = shift;
1161 1         1 my $r = ref($ra_names);
1162 1 50       9 if (!$r) {
    0          
1163 1         3 $ra_names = [$ra_names];
1164             }
1165             elsif ($r ne "ARRAY") {
1166 0         0 $self->__debug__( "BAD ref: " . $r );
1167 0         0 die "BAD ref in __add_clean_defs__";
1168             }
1169 1         5 foreach my $n (@$ra_names) {
1170 1         2 push @{$self->{clean_defs}}, "$_NODE_::defprepend$n";
  1         6  
1171             }
1172             }
1173              
1174             # Return the full path for this file, using the search path to find it.
1175             sub __full_path__ {
1176 19     19   38 my $self = shift;
1177 19         31 my $filename = shift;
1178              
1179             # If this is an absolute path, just see if it exists. Otherwise, try
1180             # to find it in the path.
1181 19 100       165 if (File::Spec->file_name_is_absolute( $filename )) {
1182 9 50       224 die "File $filename does not exist" unless -f $filename;
1183 9         26 return $filename;
1184             }
1185             # Find the file. If it isn't in the path, it doesn't exist and we
1186             # die horrible deaths.
1187 10         64 my $fullpath = '';
1188 10         20 my $total_search_path = [@{$self->{path}}, @{$self->{temporary_path}}];
  10         23  
  10         32  
1189 10         46 foreach my $d (@$total_search_path) {
1190 10         484 my $curpath = File::Spec->catfile( $d, $filename );
1191 10 50       312 if (-f $curpath) {
1192 10         39 $fullpath = $curpath;
1193 10         41 last;
1194             }
1195             }
1196 10 50       61 if (!$fullpath) {
1197 0         0 die "File $filename not found in path: ".join(":",@$total_search_path);
1198             }
1199 10         39 return $fullpath;
1200             }
1201              
1202             # This creates a secondary path (a temporary one that is easily overwritten).
1203             # Note that we don't have to clean it up because it is just plain set,
1204             # not added to.
1205             sub __temporary_path__ {
1206 9     9   24 my $self = shift;
1207 9   100     153 my $path = shift || [];
1208 9 50       62 $path = [$path] unless (ref($path) eq "ARRAY");
1209 9         78 $self->{temporary_path} = $path;
1210             }
1211              
1212             # Removes surrounding quotes. Note that inner quotes need not be escaped.
1213             sub __unquote_filename__ {
1214 2     2   3 my $self = shift;
1215 2         4 my $contents = shift;
1216 2 50       20 if ($contents =~ /^".*"$/) {
    50          
1217 0         0 $contents =~ s/^"(.*)"$/$1/; #remove surrounding quotes
1218             }
1219             elsif ($contents =~ /^'.*'$/) {
1220 2         14 $contents =~ s/^'(.*)'$/$1/; # remove surrounding quotes
1221             }
1222 2         10 return $contents;
1223             }
1224              
1225             # This checks to see if there is a circular dependency. The theory here
1226             # is that if one of the parents of this node is the same as this node, we
1227             # have a circular dependency. Simple. The root node always returns FALSE
1228             # since it HAS no parents.
1229             sub __is_included__ {
1230 1     1   2 my $self = shift;
1231 1         4 $self->__debug__(\@_);
1232 1         2 my $filename = shift;
1233              
1234 1 50       13 if ($self->{filename} eq $filename) {
    50          
1235 0         0 $self->__debug__( "Self matches!" );
1236 0         0 return 1;
1237             }
1238             elsif ($self->__is_root__) {
1239 1         3 $self->__debug__( "No match and root node. No more searching." );
1240 1         7 return 0;
1241             }
1242             else {
1243 0         0 $self->__debug__( "$filename not found, searching upward" );
1244 0         0 return $self->__parent__->__is_included__( $filename );
1245             }
1246             }
1247              
1248             sub __debug__ {
1249 972     972   1173 my $self = shift;
1250 972 50       2288 if ($DEBUG) {
1251 0         0 my $str = shift;
1252 0 0       0 $str = '*' unless defined($str);
1253              
1254 0         0 my $args = [];
1255              
1256 0 0       0 if (ref($str) eq "ARRAY") {
1257 0         0 $args = $str;
1258 0         0 $str = '';
1259             }
1260             # Find the stack depth - 1
1261 0         0 my $i = 0;
1262 0         0 while (my @a = caller(++$i)) {}
1263 0         0 $i -= 2; # remove the outside scope altogether ('use' at top level)
1264 0         0 my ($a,$b,$c,$funcname) = caller(1);
1265              
1266             # If a debug function ref has been specified, we just call that hook
1267             # and don't do anything else.
1268 0 0       0 if ($DEBUG_FUNCTION_REF) {
1269 0         0 $DEBUG_FUNCTION_REF->($funcname, $str, $args);
1270 0         0 return;
1271             }
1272             # Now we do default handling
1273             # If passed an array reference, this should display arguments.
1274 0 0       0 if (ref($str) eq "ARRAY") {
1275 0         0 $str = "Args: " . join( ", ", @$str );
1276             }
1277 0 0       0 if ($DEBUG_FILE_NAME) {
1278 0         0 open DEBUG_FILE, ">>" . $DEBUG_FILE_NAME;
1279             }
1280             else {
1281 0         0 *DEBUG_FILE = *STDERR;
1282             }
1283 0         0 print DEBUG_FILE (
1284             sprintf("%05d: ", $HTML::CMTemplate::debugline++) .
1285             ". "x$i . "$funcname: " . $str . "\n"
1286             );
1287 0 0       0 if ($DEBUG_FILE_NAME) {
1288 0         0 close DEBUG_FILE;
1289             }
1290             }
1291             }
1292              
1293             # Stack manipulation for parsing
1294             sub __top__ {
1295 153     153   186 my $self = shift;
1296 153         519 return $self->{nodestack}->[$self->{curframe}];
1297             }
1298              
1299             sub __size__ {
1300 40     40   56 my $self = shift;
1301 40         194 return $self->{curframe} + 1;
1302             }
1303              
1304             sub __pop__ {
1305 48     48   64 my $self = shift;
1306 48         50 pop @{$self->{nodestack}};
  48         331  
1307 48         82 my $ra_stack = $self->{nodestack};
1308             # make the current frame lookup faster. This way the calculation is only
1309             # done once and the tricky reference manipulation is also done once.
1310 48         96 $self->{curframe} = $#$ra_stack;
1311             }
1312              
1313             sub __push__ {
1314 85     85   119 my $self = shift;
1315 85         110 my ($node) = @_;
1316 85         93 $self->{curframe} = push( @{$self->{nodestack}}, $node ) - 1;
  85         400  
1317             }
1318              
1319             sub __is_empty__ {
1320 19     19   24 my $self = shift;
1321 19         153 return $self->{curframe} < 0;
1322             }
1323              
1324             sub __end_block__ {
1325 31     31   60 my $self = shift;
1326 31         57 $self->__debug__;
1327 31         52 my $node = $self->__top__;
1328 31         88 $node->tpl(_TPL_->new( $self ));
1329 31         121 $self->__push__( $node->tpl );
1330             }
1331              
1332             # This is a subroutine so that we can avoid self-referential structures.
1333             # We don't want the hassle of dealing with the root template pointing to
1334             # itself, because that will kill the reference counting memory management,
1335             # which is a BAD THING (tm).
1336             # So, if the parent is undef, we return self. Returning is safe. Storing
1337             # is not. Remember that. Return = Safe. Store = Not.
1338             sub __parent__ {
1339 0     0   0 my $self = shift;
1340 0   0     0 return $self->{parent} || $self;
1341             }
1342              
1343             # Similar to __parent__
1344             sub __root__ {
1345 8     8   10 my $self = shift;
1346 8   33     92 return $self->{root} || $self;
1347             }
1348              
1349             # Is this the root template?
1350             sub __is_root__ {
1351 1     1   15 return !defined( shift()->{parent} );
1352             }
1353              
1354             # Handles the deftable stuff
1355             sub __push_def__ {
1356 1     1   2 my $self = shift;
1357 1         1 my $defnode = shift;
1358 1         4 $self->{deftable}->{$defnode->name} = $defnode;
1359 1         3 $self->__root__->{deftableglobal}->{$defnode->name} = 1;
1360             }
1361              
1362             sub __exists_def__ {
1363 1     1   2 my $self = shift;
1364 1         7 my $defname = shift;
1365 1 50       14 return ($self->{deftable}->{$defname}) ? 1 : 0;
1366             }
1367              
1368             sub __exists_def_global__ {
1369 1     1   2 my $self = shift;
1370 1         1 my $defname = shift;
1371 1         4 return $self->__root__->{deftableglobal}->{$defname};
1372             }
1373              
1374             sub __get_def__ {
1375 0     0   0 my $self = shift;
1376 0         0 my $defname = shift;
1377 0         0 return $self->{deftable}->{$defname};
1378             }
1379              
1380             # Handles raw include stuff
1381             sub __add_raw__ {
1382 1     1   1 my $self = shift;
1383 1         2 my $filename = shift;
1384 1         2 my $text = shift;
1385 1   50     5 my $mtime = shift || 0;
1386              
1387 1         9 $self->__root__->{rawtable}->{$filename} = {text => $text, mtime => $mtime};
1388             }
1389              
1390             sub __exists_raw__ {
1391 1     1   3 my $self = shift;
1392 1         2 my $filename = shift;
1393 1 50       3 return ($self->__root__->{rawtable}->{$filename}) ? 1 : 0;
1394             }
1395              
1396             sub __get_raw__ {
1397 0     0   0 my $self = shift;
1398 0         0 my $filename = shift;
1399 0         0 return $self->__root__->{rawtable}->{$filename};
1400             }
1401             # Handles the parsed table stuff
1402             sub __add_parsed__ {
1403 1     1   2 my $self = shift;
1404 1         2 my $filename = shift;
1405 1         1 my $template = shift;
1406              
1407 1         4 $self->__root__->{parsedtable}->{$filename} = $template;
1408             }
1409              
1410             sub __exists_parsed__ {
1411 1     1   1 my $self = shift;
1412 1         6 my $filename = shift;
1413 1 50       11 return ($self->__root__->{parsedtable}->{$filename}) ? 1 : 0;
1414             }
1415              
1416             sub __get_parsed__ {
1417 1     1   2 my $self = shift;
1418 1         2 my $filename = shift;
1419 1         3 return $self->__root__->{parsedtable}->{$filename};
1420             }
1421              
1422             # Returns the top node. If it is not a template node, it dies with
1423             # an error. This is useful for requiring the top node to be a template
1424             # node. The type that is being added is sent in the argument list.
1425             sub __top_TPL__ {
1426 50     50   64 my $self = shift;
1427 50   50     165 my $nodetype = shift || 'UNKNOWN';
1428 50         106 $self->__debug__;
1429 50         93 my $node = $self->__top__;
1430 50 50       443 return $node if $node->type eq 'TPL';
1431              
1432 0         0 my $errormessage = "$nodetype: TPL expected, but " . $node->type .
1433             " found\n";
1434 0         0 $self->__debug__( $errormessage );
1435 0         0 die( $errormessage );
1436             }
1437              
1438             # The next two functions are real work horses. They do the actual parsing.
1439             # The __process_block__ function is what does the tokenizing. These guys build
1440             # the parse tree as the tokens come in.
1441             sub __process_tag__ {
1442 52     52   71 my $self = shift;
1443 52         130 $self->__debug__(\@_);
1444 52         133 my ($name, $contents) = @_;
1445            
1446             SWITCH: {
1447 52 100       69 'if' eq $name && do {
  52         122  
1448 6         18 $self->__onIF__( $contents );
1449 6         21 last SWITCH;
1450             };
1451 46 100       98 'elif' eq $name && do {
1452 2         7 $self->__onELIF__( $contents );
1453 2         7 last SWITCH;
1454             };
1455 44 100       92 'else' eq $name && do {
1456 5         28 $self->__onELSE__( $contents );
1457 5         18 last SWITCH;
1458             };
1459 39 100       132 'endif' eq $name && do {
1460 6         26 $self->__onENDIF__( $contents );
1461 6         18 last SWITCH;
1462             };
1463 33 100       66 'for' eq $name && do {
1464 3         16 $self->__onFOR__( $contents );
1465 3         14 last SWITCH;
1466             };
1467 30 100       131 'endfor' eq $name && do {
1468 3         20 $self->__onENDFOR__( $contents );
1469 3         10 last SWITCH;
1470             };
1471 27 100       60 'while' eq $name && do {
1472 1         11 $self->__onWHILE__( $contents );
1473 1         8 last SWITCH;
1474             };
1475 26 100       63 'endwhile' eq $name && do {
1476 1         7 $self->__onENDWHILE__( $contents );
1477 1         4 last SWITCH;
1478             };
1479 25 100       58 'def' eq $name && do {
1480 1         6 $self->__onDEF__( $contents );
1481 1         6 last SWITCH;
1482             };
1483 24 100       48 'enddef' eq $name && do {
1484 1         7 $self->__onENDDEF__( $contents );
1485 1         2 last SWITCH;
1486             };
1487 23 100       53 'call' eq $name && do {
1488 2         9 $self->__onCALL__( $contents );
1489 2         6 last SWITCH;
1490             };
1491 21 100       44 'inc' eq $name && do {
1492 1         16 $self->__onINC__( $contents );
1493 1         7 last SWITCH;
1494             };
1495 20 100       60 'rawinc' eq $name && do {
1496 1         5 $self->__onRAWINC__( $contents );
1497 1         4 last SWITCH;
1498             };
1499 19 100       42 'echo' eq $name && do {
1500 12         54 $self->__onECHO__( $contents );
1501 12         54 last SWITCH;
1502             };
1503 7 100       23 'break' eq $name && do {
1504 2         7 $self->__onBREAK__( $contents );
1505 2         7 last SWITCH;
1506             };
1507 5 100       15 'continue' eq $name && do {
1508 1         4 $self->__onCONTINUE__( $contents );
1509 1         4 last SWITCH;
1510             };
1511 4 100       11 'exec' eq $name && do {
1512 1         4 $self->__onEXEC__( $contents );
1513 1         5 last SWITCH;
1514             };
1515 3 50       8 'comment' eq $name && do {
1516 3         11 $self->__onCOMMENT__( $contents );
1517 3         13 last SWITCH;
1518             };
1519 0         0 $self->__debug__( "Unrecognized tag name: $name" );
1520             #XXX: Do we want to make the tags default to an echo expression,
1521             # or do we want to die with an unrecognized tag? Probably better
1522             # to make the programmer disambiguate it.
1523             # $self->__debug__( "Treating $name as an 'echo' expression..." );
1524             # do {
1525             # $self->__onECHO__( $contents );
1526             # last SWITCH;
1527             # };
1528 0         0 die( "Unrecognized tag: $name\n" );
1529             }
1530             }
1531              
1532             sub __onIF__ {
1533 6     6   11 my $self = shift;
1534 6         27 $self->__debug__(\@_);
1535 6         12 my $contents = shift;
1536              
1537 6         56 my $has_colon = $contents =~ /^(.*):$/s;
1538 6         13 my $expr = $1;
1539 6         20 my $has_contents = $expr =~ /\S/;
1540 6 50       16 if (!$has_colon) {
1541 0         0 $self->__debug__(
1542             "Invalid contents for an IF block (missing colon): $contents" );
1543 0         0 die "Invalid contents for an IF block (missing colon?): '$contents'\n";
1544             }
1545 6 50       18 if (!$has_contents) {
1546 0         0 $self->__debug__(
1547             "Invalid contents for an IF block (missing expr): $contents" );
1548 0         0 die "Invalid contents for an IF block (missing expr?): '$contents'\n";
1549             }
1550              
1551             # When we run into one of these, we really need to be inside of
1552             # a template since it is a beginning block type.
1553 6         44 my $node = $self->__top_TPL__( 'IF' );
1554              
1555             # Create an IF block and stick it in there. Create a template as well.
1556 6         52 my $ifnode = _IF_->new( $self );
1557             # Fill it up with stuff.
1558 6         28 $ifnode->expr( $expr );
1559             # Add it to the current node:
1560 6         120 $node->blk( $ifnode );
1561             # Push both nodes onto the stack.
1562 6         15 $self->__push__( $ifnode );
1563 6         24 $self->__push__( $ifnode->tpl );
1564             # Thus we leave expecting a template.
1565 6         34 $self->__debug__( "IF Block added successfully. Stack size: " .
1566             $self->__size__ );
1567             }
1568              
1569             sub __onELIF__ {
1570 2     2   3 my $self = shift;
1571 2         5 $self->__debug__(\@_);
1572 2         4 my $contents = shift;
1573              
1574 2         8 my $has_colon = $contents =~ /^(.*):$/s;
1575 2         4 my $expr = $1;
1576 2         10 my $has_contents = $expr =~ /\S/;
1577 2 50       6 if (!$has_colon) {
1578 0         0 $self->__debug__(
1579             "Invalid contents for an ELIF block (missing colon): $contents" );
1580 0         0 die "Invalid contents for an ELIF block (missing colon?): '$contents'\n";
1581             }
1582 2 50       14 if (!$has_contents) {
1583 0         0 $self->__debug__(
1584             "Invalid contents for an ELIF block (missing expr): $contents" );
1585 0         0 die "Invalid contents for an ELIF block (missing expr?): '$contents'\n";
1586             }
1587             # When this tag comes in, we should be inside of a template.
1588             # The way that things are set up, we could be inside of multiple levels
1589             # of templates, so we need to pop them off until we get to the parent IF
1590             # block. If we get through all of the templates and find that we are not
1591             # inside of an IF block, it is an error.
1592              
1593             # Pop off all templates. There should always be at least one.
1594 2         5 my $node = $self->__top__;
1595 2   66     6 while( !$self->__is_empty__ && ($node->type eq 'TPL') ) {
1596 2         6 $self->__pop__;
1597 2         5 $node = $self->__top__;
1598             }
1599              
1600             # If the node that is left over is not an IF block (or an ELIF),
1601             # we have a problem.
1602             # Otherwise, go ahead and process this elif as a nextif.
1603 2 50 33     9 if ($node->type eq 'blkIF' || $node->type eq 'blkELIF') {
1604 2         17 my $elifnode = _ELIF_->new( $self );
1605             # Fill it up with stuff
1606 2         7 $elifnode->expr( $expr );
1607             # Add it to the current node.
1608 2         9 $node->nextif( $elifnode );
1609             # Push both nodes onto the stack.
1610 2         5 $self->__push__( $elifnode );
1611 2         7 $self->__push__( $elifnode->tpl );
1612 2         5 $self->__debug__( "ELIF Block added successfully. Stack size: " .
1613             $self->__size__ );
1614             }
1615             else {
1616 0         0 $self->__debug__(
1617             'ELIF found with wrong parent block: ' . $node->type);
1618 0         0 die( 'ELIF found with wrong parent block: '. $node->type . "\n");
1619             }
1620             }
1621              
1622             sub __onELSE__ {
1623 5     5   8 my $self = shift;
1624 5         13 $self->__debug__(\@_);
1625 5         10 my $contents = shift;
1626              
1627             # TODO: Throw an error if there is an expression in this.
1628              
1629 5 50       34 unless ($contents =~ /^(\s*):(\s*)$/s ) {
1630 0         0 $self->__debug__('Invalid contents for an ELSE block (missing colon?)');
1631 0         0 die "Invalid contents for an ELSE block (missing colon?):" .
1632             "'$contents'\n";
1633             }
1634             # When this tag comes in, we should be inside of a template.
1635             # This template's direct or indirect parent should be an IF, ELIF, or
1636             # FOR block (since else can come after for). We pop off all templates
1637             # until we reach one of these.
1638              
1639             # Pop off all templates. There should always be at least one.
1640 5         16 my $node = $self->__top__;
1641 5   66     19 while( !$self->__is_empty__ && ($node->type eq 'TPL') ) {
1642 10         27 $self->__pop__;
1643 10         30 $node = $self->__top__;
1644             }
1645              
1646             # If the node that is left over is not an IF, ELIF, or FOR block,
1647             # we have a problem. Otherwise, go ahead and process this else
1648             # appropriately.
1649              
1650 5 100 100     22 if ($node->type eq 'blkIF' || $node->type eq 'blkELIF') {
    50          
1651 3         8 $self->__debug__( 'ELSE block inside of IF type block' );
1652 3         24 my $elsenode = _ELSE_->new( $self );
1653             # Add it to the current node.
1654 3         24 $node->nextif( $elsenode );
1655             # Push both nodes onto the stack.
1656 3         7 $self->__push__( $elsenode );
1657 3         13 $self->__push__( $elsenode->tpl );
1658 3         7 $self->__debug__( "ELSE Block added to IF. Stack size: " .
1659             $self->__size__ );
1660             }
1661             elsif ($node->type eq 'blkFOR') {
1662 2         20 $self->__debug__( 'ELSE block inside of FOR type block' );
1663 2         22 my $elsenode = _ELSE_->new( $self );
1664             # Add it to the current node.
1665 2         27 $node->default( $elsenode );
1666             # Push both nodes onto the stack.
1667 2         6 $self->__push__( $elsenode );
1668 2         11 $self->__push__( $elsenode->tpl );
1669 2         6 $self->__debug__( "ELSE Block added to FOR. Stack size: " .
1670             $self->__size__ );
1671             }
1672             else {
1673 0         0 $self->__debug__(
1674             'ELSE found with wrong parent block: ' . $node->type);
1675 0         0 die( 'ELSE found with wrong parent block: ' . $node->type . "\n");
1676             }
1677             }
1678              
1679             sub __onENDIF__ {
1680 6     6   10 my $self = shift;
1681 6         16 $self->__debug__(\@_);
1682 6         16 my $contents = shift;
1683              
1684             # TODO: Throw an error if there are contents.
1685              
1686             # We should be in a template here. However, ultimately there should
1687             # be a blkIF parent. We just pop stuff off the stack until we get to the
1688             # parent of that IF block.
1689              
1690 6         16 $self->__debug__( "Stack size before removing TPL, blkELSE, and blkELIF: " .
1691             $self->__size__ );
1692 6         18 my $type = $self->__top__()->type;
1693 6   100     27 while( $type eq 'TPL' || $type eq 'blkELSE' || $type eq 'blkELIF' ) {
      100        
1694 14         30 $self->__pop__;
1695 14         29 $type = $self->__top__()->type;
1696             }
1697 6         17 $self->__debug__( "Stack size after removal: " . $self->__size__ );
1698              
1699             # Now we should be inside of an IF block. Pop it off and return.
1700 6 50       21 if ($type eq 'blkIF') {
1701 6         15 $self->__debug__( "Found and removed the parent IF block: expr=" .
1702             $self->__top__->expr );
1703 6         22 $self->__pop__;
1704             # Now we have stripped it down to the parent template. This template
1705             # might already have text in it, so we need to add another template
1706             # to it. Since the template definition is TEXT + BLK + TPL, and
1707             # we just finished a block, we add another template and move stuff
1708             # up.
1709 6         15 $self->__end_block__;
1710             }
1711             else {
1712 0         0 $self->__debug__( "ENDIF: Popped all templates and internal IF blocks ".
1713             "and found a $type block instead of an IF block." );
1714 0         0 die( "ENDIF: No enclosing IF block found. $type found instead.\n" );
1715             }
1716             }
1717              
1718             sub __onFOR__ {
1719 3     3   4 my $self = shift;
1720 3         10 $self->__debug__(\@_);
1721 3         6 my $contents = shift;
1722              
1723             # We need to check the contents against the definition of a FOR block.
1724             # If they are not of the form in then we can't use it.
1725              
1726 3 50       21 unless( $contents =~ /^\$?(\w+)\s+in\s+(.*):$/s ) {
1727 0         0 $self->__debug__( "Invalid contents for a FOR block: $contents" );
1728 0         0 die( "Invalid contents for a FOR block (missing 'in'?): $contents\n" );
1729             }
1730 3         8 my ($varname, $listexpr) = ($1, $2);
1731 3         21 $self->__debug__(
1732             "Found correct contents: varname=$varname, list=$listexpr" );
1733              
1734             # When we run into one of these, we really need to be inside of
1735             # a template since it is a beginning block type.
1736 3         8 my $node = $self->__top_TPL__( 'FOR' );
1737             # Create a FOR block and stick it in there. Create a template as well.
1738 3         32 my $fornode = _FOR_->new( $self );
1739             # Fill it up with stuff.
1740 3         23 $fornode->varname( $varname );
1741 3         13 $fornode->listexpr( $listexpr );
1742             # Add it to the current node:
1743 3         14 $node->blk( $fornode );
1744             # Push both nodes onto the stack.
1745 3         8 $self->__push__( $fornode );
1746 3         11 $self->__push__( $fornode->tpl );
1747             # Thus we leave expecting a template.
1748 3         7 $self->__debug__( "FOR block successfully added. New stack size: " .
1749             $self->__size__ );
1750             }
1751              
1752             sub __onENDFOR__ {
1753 3     3   4 my $self = shift;
1754 3         9 $self->__debug__(\@_);
1755 3         11 my $contents = shift;
1756              
1757             # TODO: Throw an error if there are contents.
1758              
1759             # We need to pop off all templates and ELSE blocks. When we are
1760             # done, we should have reached a FOR block. If not, it's an error.
1761 3         9 $self->__debug__( "Stack size before removing TPL, and blkELSE: " .
1762             $self->__size__ );
1763 3         8 my $type = $self->__top__()->type;
1764 3   100     17 while( $type eq 'TPL' || $type eq 'blkELSE' ) {
1765 6         16 $self->__pop__;
1766 6         13 $type = $self->__top__()->type;
1767             }
1768 3         7 $self->__debug__( "Stack size after removal: " . $self->__size__ );
1769              
1770             # Now we should be inside of a FOR block. Pop it off and return.
1771 3 50       7 if ($type eq 'blkFOR') {
1772 3         8 $self->__debug__( "Found and removed the parent FOR block: " .
1773             "varname=" . $self->__top__->varname . " list=" .
1774             $self->__top__->listexpr );
1775 3         9 $self->__pop__;
1776             # Now we have stripped it down to the parent template. This template
1777             # might already have text in it, so we need to add another template
1778             # to it. Since the template definition is TEXT + BLK + TPL, and
1779             # we just finished a block, we add another template and move stuff
1780             # up.
1781 3         26 $self->__end_block__;
1782             }
1783             else {
1784 0         0 $self->__debug__( "ENDFOR: Popped all templates and ELSE blocks ".
1785             "and found a $type block instead of a FOR block." );
1786 0         0 die( "ENDFOR: No enclosing FOR block found. $type found instead.\n" );
1787             }
1788             }
1789              
1790             sub __onWHILE__ {
1791 1     1   1 my $self = shift;
1792 1         6 $self->__debug__(\@_);
1793 1         2 my $contents = shift;
1794              
1795             # We need to check the contents against the definition of a FOR block.
1796             # If they are not of the form in then we can't use it.
1797              
1798 1 50       9 unless( $contents =~ /^(.*):$/s ) {
1799 0         0 $self->__debug__( 'Invalid contents for a WHILE block' );
1800 0         0 die( "Invalid contents for a WHILE block: '$contents'\n" );
1801             }
1802              
1803 1         4 my $expr = $1;
1804 1         5 $self->__debug__( "Found correct contents: expr=$expr" );
1805              
1806             # When we run into one of these, we really need to be inside of
1807             # a template since it is a beginning block type.
1808 1         5 my $node = $self->__top_TPL__( 'WHILE' );
1809             # Create a WHILE block and stick it in there. Create a template as well.
1810 1         20 my $whilenode = _WHILE_->new( $self );
1811             # Fill it up with stuff.
1812 1         5 $whilenode->expr( $expr );
1813             # Add it to the current node:
1814 1         7 $node->blk( $whilenode );
1815             # Push both nodes onto the stack.
1816 1         3 $self->__push__( $whilenode );
1817 1         5 $self->__push__( $whilenode->tpl );
1818             # Thus we leave expecting a template.
1819 1         4 $self->__debug__( "WHILE block successfully added. New stack size: " .
1820             $self->__size__ );
1821             }
1822              
1823             sub __onENDWHILE__ {
1824 1     1   1 my $self = shift;
1825 1         4 $self->__debug__(\@_);
1826 1         2 my $contents = shift;
1827              
1828             # TODO: Throw an error if there are contents.
1829              
1830             # We need to pop off all templates and ELSE blocks. When we are
1831             # done, we should have reached a FOR block. If not, it's an error.
1832 1         2 $self->__debug__( "Stack size before removing TPL: " . $self->__size__ );
1833 1         3 my $type = $self->__top__()->type;
1834 1         11 while( $type eq 'TPL' ) {
1835 1         4 $self->__pop__;
1836 1         2 $type = $self->__top__()->type;
1837             }
1838 1         3 $self->__debug__( "Stack size after removal: " . $self->__size__ );
1839              
1840             # Now we should be inside of a WHILE block. Pop it off and return.
1841 1 50       3 if ($type eq 'blkWHILE') {
1842 1         3 $self->__debug__( "Found and removed the parent WHILE block: " .
1843             "expr=" . $self->__top__->expr );
1844 1         3 $self->__pop__;
1845             # Now we have stripped it down to the parent template. This template
1846             # might already have text in it, so we need to add another template
1847             # to it. Since the template definition is TEXT + BLK + TPL, and
1848             # we just finished a block, we add another template and move stuff
1849             # up.
1850 1         4 $self->__end_block__;
1851             }
1852             else {
1853 0         0 $self->__debug__( "ENDWHILE: Popped all templates".
1854             "and found a $type block instead of a WHILE block." );
1855 0         0 die "ENDWHILE: No enclosing WHILE block found. $type found instead.\n";
1856             }
1857             }
1858              
1859             sub __onDEF__ {
1860 1     1   2 my $self = shift;
1861 1         2 $self->__debug__(\@_);
1862 1         2 my $contents = shift;
1863              
1864 1 50       11 unless( $contents =~ /^(\w+)\s*\((.*)\)\s*:$/s ) {
1865 0         0 $self->__debug__( 'Invalid contents for a DEF block (needs to be "' .
1866             'name (arglist):")');
1867 0         0 die "Invalid contents for a DEF block (should be 'name (arglist)'): " .
1868             "'$contents'\n";
1869             }
1870 1         2 my ($name, $argexpr) = ($1, $2);
1871             # Get the argument list into an appropriate format.
1872 1         4 my @args = split( ",", $argexpr );
1873 1         4 foreach my $arg (@args) {
1874 3         16 $arg =~ s/^\s*(\w+)\s*$/$1/;
1875             }
1876             # When we run into one of these, we really need to be inside of
1877             # a template since it is a beginning block type.
1878 1         8 my $node = $self->__top_TPL__( 'DEF' );
1879              
1880             # Create a DEF block and stick it in there. Create a template as well.
1881 1         21 my $defnode = _DEF_->new( $self );
1882             # Fill it up with stuff.
1883 1         6 $defnode->name( $name );
1884 1         5 $defnode->argnames( \@args );
1885             # Add it to the current node:
1886 1         8 $node->blk( $defnode );
1887             # Push both nodes onto the stack.
1888 1         2 $self->__push__( $defnode );
1889 1         5 $self->__push__( $defnode->tpl );
1890             # make sure that we add this to the clean names list.
1891 1         4 $self->__add_clean_defs__( $name );
1892             # Thus we leave expecting a template.
1893 1         3 $self->__debug__( "DEF Block added successfully. Stack size: " .
1894             $self->__size__ );
1895             }
1896              
1897             sub __onENDDEF__ {
1898 1     1   2 my $self = shift;
1899 1         3 $self->__debug__(\@_);
1900 1         1 my $contents = shift;
1901              
1902             # TODO: Throw an error if there are contents.
1903              
1904             # TRICKY STUFF AHEAD!!
1905             # When se see an enddef tag, we not only pop off all of the templates,
1906             # but we also remove this subtree from the main parse tree and place
1907             # it into the local def table. That keeps the defs separate from the
1908             # rest of the code, which is as it should be.
1909              
1910             # We need to pop off all templates. When we are
1911             # done, we should have reached a DEF block. If not, it's an error.
1912 1         3 $self->__debug__( "Stack size before removing TPL: " . $self->__size__ );
1913 1         3 my $type = $self->__top__()->type;
1914 1         14 while( $type eq 'TPL' ) {
1915 4         9 $self->__pop__;
1916 4         6 $type = $self->__top__()->type;
1917             }
1918 1         8 $self->__debug__( "Stack size after removal: " . $self->__size__ );
1919              
1920             # Now we should be inside of a DEF block. Pop it off, remove
1921             # it from the tree, and place it in the deftable.
1922 1 50       4 if ($type eq 'blkDEF') {
1923 1         3 $self->__debug__( "Found and removed the parent DEF block: " .
1924             "name=" . $self->__top__->name . " argnames=" .
1925 1         2 join( ", ", @{$self->__top__->argnames} ) );
1926 1         4 $self->__pop__;
1927             # Now we have the parent node of the def. The def block is the 'blk'
1928             # parameter of this template node. Since we don't want defs inside
1929             # of the main code, we remove the def block and its subtree and
1930             # place it into the defs table.
1931 1         2 my $defblk = $self->__top__->blk;
1932             # remove the subtree (undefine it)
1933 1         3 $self->__top__->blk( undef );
1934 1 50       3 if ($self->__exists_def__( $defblk->name )) {
    50          
1935 0         0 $self->__debug__( "DEF " . $defblk->name .
1936             " already exists in this template! Aborting.");
1937 0         0 die "Attempted to redefine def '" . $defblk->name .
1938             "' inside of its own template. Giving up.\n";
1939             }
1940             elsif ($self->__exists_def_global__( $defblk->name )) {
1941 0         0 $self->__debug__( "DEF " . $defblk->name .
1942             " already exists in another template! Aborting.");
1943 0         0 die "Attempted to redefine def '" . $defblk->name .
1944             "' inside of " . $self->{filename} . ". Bad programmer!\n";
1945             }
1946 1         4 $self->__push_def__( $defblk );
1947            
1948             # Now we have stripped it down to the parent template. This template
1949             # might already have text in it, so we need to add another template
1950             # to it. Since the template definition is TEXT + BLK + TPL, and
1951             # we just finished a block, we add another template and move stuff
1952             # up.
1953 1         4 $self->__end_block__;
1954             }
1955             else {
1956 0         0 $self->__debug__( "ENDDEF: Popped all templates ".
1957             "and found a $type block instead of a DEF block." );
1958 0         0 die( "ENDDEF: No enclosing DEF block found. $type found instead.\n" );
1959             }
1960             }
1961              
1962             sub __onCALL__ {
1963 2     2   2 my $self = shift;
1964 2         5 $self->__debug__(\@_);
1965 2         3 my $contents = shift;
1966              
1967 2 50       9 unless( $contents =~ /^(\w+)\s*\((.*)\)\s*$/s ) {
1968 0         0 $self->__debug__( "CALL: Improperly formed contents: $contents" );
1969 0         0 die( "CALL: Improperly formed contents: $contents\n" );
1970             }
1971 2         5 my ($name, $argexpr) = ($1, $2);
1972              
1973             # NOTE: Since this is both a beginning AND ending block, we don't
1974             # push it onto the stack at all. We DO, however, push a new template
1975             # onto the stack, so we call __end_block__.
1976              
1977             # We should be in a template here. If not, there is a problem.
1978 2         4 my $node = $self->__top_TPL__( 'CALL' );
1979             # Create a new node and add it to the tree.
1980 2         18 my $callnode = _CALL_->new( $self );
1981 2         8 $callnode->name( $name );
1982 2         6 $callnode->argexpr( $argexpr );
1983 2         5 $node->blk( $callnode );
1984             # DO NOT push it onto the stack. Simply call __end_block__ since
1985             # this tag both begins and ends a block.
1986 2         4 $self->__end_block__;
1987             }
1988              
1989             sub __onINC__ {
1990 1     1   2 my $self = shift;
1991 1         4 $self->__debug__(\@_);
1992 1         4 my $filename = $self->__full_path__($self->__unquote_filename__(shift()));
1993              
1994             # Is this file included by its collective ancestry? If so, die horribly.
1995 1 50       6 if ($self->__is_included__($filename)) {
1996 0         0 die "Recursive inclusion detected: $filename eventually"
1997             . " includes itself\n";
1998             }
1999              
2000             # Create the include structure and insert it into the tree.
2001 1         11 my $node = $self->__top_TPL__( 'INC' );
2002 1         23 my $incnode = _INC_->new( $self );
2003 1         5 $incnode->filename( $filename );
2004 1         10 $node->blk( $incnode );
2005 1         5 $self->__end_block__; # both beginning and ending tag.
2006              
2007             # Now we check for it already being parsed.
2008             # If the template has already been parsed, we don't do that again.
2009             # Otherwise we go ahead and parse it.
2010 1 50       7 unless ($self->__exists_parsed__( $filename )) {
2011 1         4 my $t = new HTML::CMTemplate(
2012             parent => $self,
2013             root => $self->__root__,
2014             path => $self->{path},
2015             nocwd => 1, # no need to find cwd again
2016             );
2017 1         8 $t->open_file( $filename, $self->{temporary_path} );
2018             # Add it so we don't do it again.
2019 1         6 $self->__add_parsed__( $filename, $t );
2020             }
2021              
2022             # This node has a filename, which is enough to get at the parsed template,
2023             # so we are finished, now.
2024             }
2025              
2026             sub __onRAWINC__ {
2027 1     1   2 my $self = shift;
2028 1         3 $self->__debug__(\@_);
2029 1         3 my $filename = $self->__full_path__($self->__unquote_filename__(shift()));
2030              
2031             # Note that because this is a raw file and no includes are parsed,
2032             # we can just open it, suck out the text, and close it up. All of it
2033             # should go into a text tag.
2034              
2035             # Create the include structure and insert it into the tree.
2036 1         7 my $node = $self->__top_TPL__( 'RAWINC' );
2037 1         5 my $rawnode = _TPL_->new( $self );
2038              
2039 1         2 my $text = '';
2040 1         3 my $mtime = 0;
2041 1 50       4 if ($self->__exists_raw__( $filename )) {
2042 0         0 $self->__debug__( 'Raw file $filename already exists: getting it' );
2043 0         0 my $rawrec = $self->__get_raw__( $filename );
2044 0         0 $text = $rawrec->{text};
2045 0         0 $mtime = $rawrec->{mtime};
2046             }
2047             else {
2048 1         16 $self->__debug__( 'Raw file $filename has not been read: getting it' );
2049             # Get the mtime of this file for future reference.
2050 1         3 my $filestat = stat($filename);
2051 1         145 $mtime = $filestat->mtime;
2052             # Open and suck the text out.
2053 1         7 local( *FILE );
2054 1   33     43 open FILE, "<$filename" || do {
2055             $self->__debug__( 'Failed to open raw file $filename: $!' );
2056             die "Failed to open raw include: $filename\n";
2057             };
2058 1         4 local $/;
2059 1         3 undef $/;
2060 1         28 $text = ;
2061 1         14 close FILE;
2062             }
2063              
2064 1         5 $rawnode->text( $text );
2065 1         6 $node->blk( $rawnode );
2066             # Note that I didn't push anything onto the stack. This block is
2067             # just a template with text in it. That is legal, though unusual (this
2068             # is the only case where that happens). I COULD just add to the existing
2069             # text in the current template node, but I opted to create a separate
2070             # block and treat it like any other tag for completeness and generality's
2071             # sake.
2072             # The __end_block__ thing here inserts a new empty template into this
2073             # template's tpl variable, enabling us to start looking for text once
2074             # again.
2075 1         3 $self->__end_block__; # both beginning and ending tag.
2076             # Keep track of this and only open it again if needed.
2077 1         5 $self->__add_raw__( $filename, $text, $mtime );
2078             }
2079              
2080             sub __onECHO__ {
2081 12     12   20 my $self = shift;
2082 12         36 $self->__debug__(\@_);
2083 12         23 my $contents = shift;
2084              
2085 12         33 my $node = $self->__top_TPL__( 'ECHO' );
2086 12         113 my $echonode = _ECHO_->new( $self );
2087 12         48 $echonode->expr( $contents );
2088 12         59 $node->blk( $echonode );
2089 12         40 $self->__end_block__;
2090             }
2091              
2092             sub __onBREAK__ {
2093 2     2   4 my $self = shift;
2094 2         6 $self->__debug__(\@_);
2095 2         4 my $contents = shift;
2096              
2097 2         5 my $node = $self->__top_TPL__( 'BREAK' );
2098 2         20 my $breaknode = _BREAK_->new( $self );
2099 2         9 $node->blk( $breaknode );
2100 2         6 $self->__end_block__;
2101             }
2102              
2103             sub __onCONTINUE__ {
2104 1     1   3 my $self = shift;
2105 1         4 $self->__debug__(\@_);
2106 1         2 my $contents = shift;
2107              
2108 1         3 my $node = $self->__top_TPL__( 'CONTINUE' );
2109 1         16 my $continuenode = _CONTINUE_->new( $self );
2110 1         13 $node->blk( $continuenode );
2111 1         3 $self->__end_block__;
2112             }
2113              
2114             sub __onEXEC__ {
2115 1     1   1 my $self = shift;
2116 1         3 $self->__debug__(\@_);
2117 1         1 my $contents = shift;
2118            
2119 1         7 my $node = $self->__top_TPL__( 'EXEC' );
2120 1         13 my $execnode = _EXEC_->new( $self );
2121 1         4 $execnode->expr( $contents );
2122 1         9 $node->blk( $execnode );
2123 1         7 $self->__end_block__;
2124             }
2125              
2126             sub __onCOMMENT__ {
2127 3     3   5 my $self = shift;
2128 3         5 $self->__debug__(\@_);
2129 3         6 my $contents = shift;
2130              
2131             # NOP: Just eat the tag
2132             }
2133              
2134             sub __process_cdata__ {
2135 19     19   26 my $self = shift;
2136 19         45 $self->__debug__(\@_);
2137 19         49 my ($cdata) = @_;
2138              
2139             # If we are in a TPL node, then we should just add the text to the current
2140             # text in that node. Otherwise, something went wrong. We should always
2141             # be prepared to receive text when it comes.
2142 19         41 my $node = $self->__top_TPL__( 'text' );
2143 19         86 $node->text( $node->text . $cdata );
2144 19         163 $self->__debug__( "New CDATA length: " . length( $node->text ) );
2145             }
2146              
2147             # This function takes a chunk of text and decides what to do with it. It works
2148             # in a similar fashion to expat, which will take text until you quit giving it
2149             # to it. It simply looks for tags and data in between. When a complete tag is
2150             # found, it passes the information off to a function to have it processed.
2151             # When cdata is found (character data) it dumps it out. Note that there is
2152             # no guarantee that the cdata will come back all at once. This function does
2153             # not do any output buffering on cdata. If it isn't in a tag, it gives you
2154             # everything that it currently has, whether it is the entire set of text
2155             # or not.
2156             sub __process_block__ {
2157 68     68   87 my $self = shift;
2158 68         159 $self->__debug__(\@_);
2159 68         113 my $str = shift;
2160              
2161             # This function only looks for tokens and keeps track of whether or not
2162             # it is inside of a tag. Once a complete tag has been found, it will
2163             # send the name of that tag and all remaining text inside of it to the
2164             # appropriate function.
2165             # If it reaches the end of a buffer and is not inside of a tag, it
2166             # accumulates all text and sends it out to the cdata function.
2167              
2168             # Append to the buffer and continue where we left off.
2169 68         136 $self->{strbuf} .= $str;
2170              
2171             # Note that if we are already inside of a tag, we search from a few
2172             # characters before the boundary. Otherwise, we search from the beginning
2173             # of the unprocessed buffer.
2174 68 100       503 my $curpos = ($self->{parserintag}) ?
2175             $self->{buflen} - $HTML::CMTemplate::tagEndLen + 1:
2176             $self->{bufstart};
2177 68         207 $self->__debug__( "Curpos: $curpos" );
2178              
2179 68         133 $self->{buflen} += length($str);
2180 68         199 $self->__debug__( "New Buflen: " . $self->{buflen} );
2181 68         193 while ($curpos < $self->{buflen}) {
2182             # In a tag. Get the rest of it, if possible, and send it out for
2183             # processing.
2184 123 100       443 if ($self->{parserintag}) {
2185 55         111 $self->__debug__( 'STATE: inside of a tag' );
2186             # Try to find the end of the tag.
2187 55         145 my $pos = index( $self->{strbuf}, $HTML::CMTemplate::tagEnd, $curpos );
2188 55         178 $self->__debug__( "End tag position: $pos" );
2189             # If we found it, we get all of the stuff inside of the tag and dump
2190             # it into a function.
2191 55 100       113 if ($pos > -1) {
2192             # Found the end tag. Send it on its way.
2193             # Get the internals of the tag:
2194 52         91 my $start = $self->{tagstart} + $HTML::CMTemplate::tagStartLen;
2195 52         118 my $tag = substr( $self->{strbuf}, $start, $pos - $start );
2196 52 100       522 if ($tag =~ m/^(\w+)(\s+(.*?)\s*)?$/s) {
    100          
2197             # $1 contains the name of the tag
2198             # $3 contains the rest of the tag's text, if there is any.
2199             # TODO: Make the function call configurable by a hash or
2200             # something.
2201 38 100       284 $self->__process_tag__($1, (defined($3))?$3:'');
2202             # Once the tag is processed, we are no longer in a tag.
2203             # Move the current position to where we left off and
2204             # continue the loop.
2205             }
2206             # Special case for block tags with no expression, like 'else'
2207             elsif ($tag =~ m/^(\w+)\s*:\s*$/s) {
2208 5         16 $self->__debug__(
2209             "Found an expressionless block tag: $tag" );
2210 5         14 $self->__process_tag__($1, ':');
2211             }
2212             else {
2213             # The tag was not of the format
2214             # So, we take everything inside of the and
2215             # treat it like it was the expression for the default tag.
2216             # The default tag is set up to be 'echo' by default.
2217 9         30 $self->__debug__( "Found a shortcut tag: $tag" );
2218 9         21 $self->__process_tag__(
2219             $HTML::CMTemplate::tagNameDefault, $tag);
2220             }
2221 52         93 $self->{parserintag} = 0;
2222 52         69 $curpos = $pos + $HTML::CMTemplate::tagEndLen;
2223             # Check that the next character is not an endline. If it is,
2224             # we need to eat it.
2225             # TODO: What happens on Windows? Do we need to move it two?
2226 52 100       186 $curpos++ if (substr($self->{strbuf}, $curpos, 1) eq "\n");
2227             # Important to move up the bufstart flag. We have, after all,
2228             # used up the buffer to this point.
2229 52         191 $self->{bufstart} = $curpos;
2230             }
2231             else {
2232             # No ending tag found. We need to continue accumulating buffer.
2233 3         4 last;
2234             }
2235             }
2236             # Not in a tag. Search for a starting tag or something that looks
2237             # like it might be one. Send out all text. If a tag is found,
2238             # we need to put ourselves into a tag state and set the tagstart
2239             # index.
2240             else {
2241 68         135 $self->__debug__( "STATE: Not in a tag" );
2242             # NOTE: There is a tricky boundary case here. If the start tag
2243             # is spanning buffer boundaries (this usually won't happen,
2244             # especially if the file is read in one line at a time, but it
2245             # will definitely happen if it is read in arbitrary sized chunks)
2246             # it could get missed by the parser. (A full substring match will
2247             # fail until the entire tag is seen.) So, when getting ready
2248             # to spit out text, we need to check back a few characters for
2249             # the first character of a start tag. If it is there and it is
2250             # not escaped somehow, we only send out the text up to that
2251             # character. We then defer searching for the start tag until
2252             # the next section of buffer is read in.
2253 68         147 my $pos = index( $self->{strbuf}, $HTML::CMTemplate::tagStart, $curpos);
2254 68         184 $self->__debug__( "Start tag position: $pos" );
2255             # If we found a start tag, we need to dump the text out and
2256             # set the tag state. TODO: Check for escaped tags!
2257 68 100       177 if ($pos > -1) {
2258             # Found the start tag. Change state and get out.
2259 52         82 $self->{parserintag} = 1;
2260 52         79 $self->{tagstart} = $pos;
2261 52 100       139 if ($pos > $curpos) {
2262 3         14 $self->__process_cdata__(
2263             substr( $self->{strbuf}, $curpos, $pos - $curpos )
2264             );
2265 3         6 $curpos = $pos;
2266             }
2267             # exhausted our buffer to this point.
2268 52         160 $self->{bufstart} = $curpos;
2269             }
2270             else {
2271             # No start tag found. Double check that the first character
2272             # of the tag is not in the end of the buffer somewhere. If it
2273             # is, then send out the text up to that character. Otherwise,
2274             # send everything out as text.
2275 16         46 my $firstchar = substr( $HTML::CMTemplate::tagEnd, 0, 1 );
2276 16         48 my $fpos = index(
2277             $self->{strbuf},
2278             $firstchar,
2279             $self->{buflen} - $HTML::CMTemplate::tagEndLen + 1
2280             );
2281             # If nothing like a tag was found, set the position to be
2282             # the character after the end of the buffer. Otherwise,
2283             # use the position of the tag character.
2284 16 50       51 $fpos = ($fpos > -1) ? $fpos : $self->{buflen};
2285 16         69 $self->__process_cdata__(
2286             substr( $self->{strbuf}, $curpos, $fpos - $curpos )
2287             );
2288 16         37 $curpos = $fpos;
2289 16         56 $self->{bufstart} = $curpos;
2290             }
2291             }
2292             }
2293              
2294             # We need to do some boundary checking here. If, for example, the bufstart
2295             # flag is beyond the end of the buffer, we should just erase the buffer.
2296             # It's utility is exhausted.
2297             # Otherwise, we need to determine whether it makes sense to kill off part
2298             # of the buffer.
2299 68 100       172 if ($self->{bufstart} > 0) {
2300 65         143 $self->__debug__( "Start of buffer not at the beginning. Reducing." );
2301 65 50       153 if ($self->{bufstart} >= $self->{buflen}) {
2302 65         133 $self->__debug__( "Buffer completely exhausted. Resetting." );
2303             # Buffer is exhausted. Reset everyone.
2304 65         93 $self->{bufstart} = 0;
2305 65         100 $self->{strbuf} = '';
2306 65         87 $self->{tagstart} = 0;
2307 65         266 $self->{buflen} = 0;
2308             }
2309             else {
2310 0         0 $self->__debug__( "Buffer partially exhausted. Resetting." );
2311             # Buffer is at least partially exhausted. No point in keeping
2312             # the unused portions around. XXX: Do we need to hold off on this
2313             # case? Should we only kill it if the remaining portion is smaller
2314             # than the unused portion? What kind of metric should determine
2315             # this?
2316 0         0 my $start = $self->{bufstart};
2317 0         0 $self->{bufstart} = 0;
2318 0         0 $self->{buflen} -= ($start + 1);
2319 0         0 $self->{tagstart} -= $start;
2320 0         0 $self->{strbuf} = substr( $self->{strbuf}, $start );
2321 0         0 $self->__debug__( "New buffer length: " . $self->{buflen} );
2322             }
2323             }
2324             }
2325             #-------------------------------------------------------------------------------
2326             #-------------------------------------------------------------------------------
2327             #-------------------------------------------------------------------------------
2328             # USER SPACE STUFF
2329             #-------------------------------------------------------------------------------
2330             #-------------------------------------------------------------------------------
2331             #-------------------------------------------------------------------------------
2332             =pod
2333              
2334             I
2335              
2336             Returns an arrayref of included files.
2337              
2338             =cut
2339              
2340             sub get_includes() {
2341 0     0 0 0 my $self = shift;
2342 0         0 my @includes = (keys(%{$self->{parsedtable}}), keys(%{$self->{rawtable}}));
  0         0  
  0         0  
2343 0         0 return \@includes;
2344             }
2345              
2346             =pod
2347              
2348             I
2349              
2350             Takes one or two parameters.
2351             This function looks for the indicated file and parses it
2352             into an internal structure. Once this is done, it is capable of outputting
2353             perl code or importing an indicated package with said code in the output
2354             function. The file is looked for in the path specified during template
2355             creation.
2356              
2357             Note that even if a relative filename is passed in (relative to any part
2358             of the path, including '.') the filename will be converted to an absolute path
2359             internally. This is the way that infinite recursion is detected and
2360             templates are never parsed more than once.
2361              
2362             =cut
2363              
2364             sub open_file {
2365 9     9 0 20 my $self = shift;
2366 9         19 my $filename = shift;
2367 9         21 my $path = shift;
2368              
2369             # Since the path may already be augmented, don't overwrite it
2370             # by doing it again unless something other than undef was passed
2371             # in.
2372 9 100       83 $self->__temporary_path__($path) if defined($path);
2373              
2374             # A new file should not have to share a tree with an old one.
2375 9         31 $self->__reset_temp__;
2376              
2377 9         28 my $fullpath = $self->__full_path__( $filename );
2378              
2379 9         89 my $sb = stat( $fullpath );
2380 9         1101 $self->{filename} = $fullpath;
2381 9         203 $self->{filemodtime} = $sb->mtime;
2382              
2383             # Load the file.
2384 9         91 my $line = 0;
2385 9         51 local(*FILE);
2386 9 50       582 open( FILE, "<$fullpath" ) || die "Failed to open $fullpath\n";
2387 9         214 while( ) {
2388 68         82 ++$line;
2389 68         133 eval {
2390 68         193 $self->__process_block__( $_ );
2391             };
2392 68 50       353 if ($@) {
2393 0         0 die "PARSE ERROR in '$filename', line $line:\n\t$@\n";
2394             }
2395             }
2396 9         533 close( FILE );
2397             }
2398              
2399             =pod
2400              
2401             I
2402              
2403             Open the file, parse it, and import the indicated variables.
2404             This will leave the client with an imported package that can be used
2405             to generate output. This does not actually call the output function! That
2406             would be too confining.
2407              
2408             The reason that this function exists is that it is by far the most used
2409             operation. The most frequent need when dealing with templates is to open
2410             them up and import them into a namespace, including some predefined variables
2411             that are well known. This allows one function call to replace several.
2412              
2413             The arguments to this function are supposed to be named and are as follows:
2414              
2415             =over 4
2416              
2417             =item *
2418              
2419             'filename' => name of file
2420              
2421             =item *
2422              
2423             'packagename' => name of package into which the code is imported
2424              
2425             =item *
2426              
2427             'path' => arrayref of directories to add to the main path just for this import
2428              
2429             =item *
2430              
2431             'warn' => if defined, turns warnings on in the generated module
2432              
2433             =item *
2434              
2435             'importrefs' => optional arrayref of hashrefs to import into the namespace
2436              
2437             =item *
2438              
2439             'importclean' => optional arrayref of hashrefs to import into the clean space
2440              
2441             =back
2442              
2443             =cut
2444             sub import_template {
2445 8     8 0 165 my $self = shift;
2446 8         44 $self->__debug__(\@_);
2447 8         98 my %args = @_;
2448             # Arguments expected:
2449             # required: filename
2450             # required: packagename
2451             # optional: an array of hashrefs to be imported called 'importrefs'
2452             # optional: an array of hashrefs to be imported called 'importclean'
2453             # optional: a temporary search path arrayref.
2454              
2455 8 50       44 die "No filename specified" unless defined( $args{'filename'} );
2456 8 50       46 die "No package name specified" unless defined( $args{'packagename'} );
2457              
2458 8         113 $self->__temporary_path__($args{path});
2459              
2460 8         51 my $filename = $self->__full_path__($args{'filename'});
2461 8         29 my $packagename = $args{'packagename'};
2462 8         19 my $parent = $args{'parent'};
2463 8   50     109 my $fstat = stat( $filename ) || die "Failed to stat file $filename";
2464 8         2734 my $mtime = $fstat->mtime;
2465              
2466 8         93 $self->__debug__( "Stat succeeded for $filename" );
2467              
2468             # Here we check to see that we should actually import this thing. If
2469             # the package and filename already exist in our list, we don't import them
2470             # unless the modified date and time has changed.
2471             # Check that this file/package combination exists in the list of imported
2472             # templates. If it does, then we check different criterion based on the
2473             # user settings. If it doesn't, we import it always.
2474 8 50       42 if ($self->{checkmode} == $HTML::CMTemplate::CHECK_STAT) {
2475 8         31 $self->__debug__( "Mode is CHECK_STAT" );
2476 8 50       47 if ($self->__exists_file_package__( $filename, $packagename )) {
2477 0         0 $self->__debug__(
2478             "Filename/packagename combo exists: $filename, $packagename" );
2479 0         0 my $oldtime =
2480             $self->__file_package_mtime__( $filename, $packagename );
2481 0         0 $self->__debug__( "Old mtime: $oldtime" );
2482 0 0       0 if ($oldtime == $mtime) {
2483 0         0 $self->__debug__( 'root template up-to-date (CHECK_STAT)' );
2484             # Now we check each of the includes. If any of them are
2485             # out of date, we carry on, otherwise, we deem the import
2486             # unnecessary.
2487 0         0 my $includes =
2488             $self->__file_package_includes__($filename, $packagename);
2489 0         0 my $inc_out_of_date = 0;
2490 0         0 while( my ($incname, $oldincmtime) = each (%$includes)) {
2491 0         0 my $incstat = stat($incname);
2492             # Did we find one that's out of date? If so, reimport.
2493 0 0       0 if ($incstat->mtime != $oldincmtime) {
2494 0         0 $self->__debug__(
2495             "Found an include file ($incname) out of date"
2496             );
2497 0         0 $inc_out_of_date = 1;
2498 0         0 last;
2499             }
2500             }
2501 0 0       0 return unless $inc_out_of_date; # don't import. Not needed.
2502             }
2503             }
2504             }
2505 8         39 $self->__debug__( 'Import proceeding (deemed necessary)' );
2506              
2507             # NOTE that we have two kinds of namespaces. We have a 'dirty'
2508             # namespace, which can be cleaned up with the cleanup_namespace function,
2509             # and we have a 'clean' namespace, which is left alone by that function.
2510             # We can import variables into either namespace, since some will
2511             # make sense to NOT clean up when we want to remove sensitive information.
2512 8         16 my $ra_cleanref = $args{'importclean'};
2513 8         19 my $ra_dirtyref = $args{'importrefs'};
2514              
2515             # make sure we have an array of hashrefs, not a single hashref.
2516             # Actually, this makes it possible to pass in a single hashref
2517             # instead of an array of one hashref in the degenerate case, which
2518             # will probably be fairly common.
2519 8 50 33     54 if (defined( $ra_cleanref ) && (ref( $ra_cleanref ) eq 'HASH')) {
2520 0         0 $ra_cleanref = [$ra_cleanref];
2521             }
2522 8 50 33     38 if (defined( $ra_dirtyref ) && (ref( $ra_dirtyref ) eq 'HASH')) {
2523 0         0 $ra_dirtyref = [$ra_dirtyref];
2524             }
2525              
2526             # Now, we open the file, import the package, and import the hashrefs.
2527 8         52 $self->open_file( $filename );
2528 8         60 $self->import_package( $packagename, $args{warn} );
2529              
2530             # Import refs into the 'clean' namespace (cannot be cleaned up easily)
2531 8 50       38 if (defined( $ra_cleanref )) {
2532 0         0 foreach my $rh (@$ra_cleanref) {
2533 0         0 eval( "${packagename}::import_hashref( \$rh, 1 )" );
2534 0 0       0 if ($@) {
2535 0         0 die "EVAL ERROR: ${packagename}::import_hashref (clean) " .
2536             "failed: $@\n";
2537             }
2538             }
2539             }
2540             # Import refs into the 'dirty' namespace (can be cleaned up)
2541 8 50       33 if (defined( $ra_dirtyref )) {
2542 0         0 foreach my $rh (@$ra_dirtyref) {
2543 0         0 eval( "${packagename}::import_hashref( \$rh, 0 )" );
2544 0 0       0 if ($@) {
2545 0         0 die "EVAL ERROR: ${packagename}::import_hashref (dirty) " .
2546             "failed: $@\n";
2547             }
2548             }
2549             }
2550              
2551             # Create a table of included mtimes from parsedtable
2552 8         15 my %includes = %{$self->{parsedtable}};
  8         34  
2553 8         47 while (my ($filename, $template) = each (%includes)) {
2554 1         6 $includes{$filename} = $template->{filemodtime};
2555             }
2556             # Add the raw files to this table. Some of them may overwrite
2557             # the templates, but since we are only worried about mtime, we don't
2558             # care. (A normal include will have the same mtime as a raw include,
2559             # since it is the same file -- duh).
2560 8         18 while (my ($filename, $rawrec) = each (%{$self->{rawtable}})) {
  9         72  
2561 1         3 $includes{$filename} = $rawrec->{mtime};
2562             }
2563             # Add to the imported hash (or modify the mtime):
2564 8         121 $self->__add_file_package__( $filename, $packagename, \%includes, $mtime );
2565              
2566             # no return value. This just sets up the template in a module. The
2567             # output function of that module still must be called.
2568             }
2569              
2570             =pod
2571              
2572             I
2573              
2574             Once a file has been opened and parsed, the code to generate the template can
2575             be imported into a package of the specified name. In order to really make
2576             the tempalate useful, the generated code should be imported into a package
2577             so that it can have its own namespace. Mind you, the template can actually
2578             be imported into the current package, but this is not suggested or encouraged
2579             since it is generating code that might do nasty things to your global variables.
2580              
2581             The $warn parameter turns warnings on or off in the generated module.
2582             Leave it out or set to zero for default behavior (off).
2583              
2584             =cut
2585             sub import_package {
2586 8     8 0 28 my ($self, $package, $warn) = @_;
2587             #my $perl = $self->output_perl( $package );
2588             #print STDERR $perl;
2589 8 100 0 8   128 eval( $self->output_perl( packagename => $package, 'warn' => $warn ) );
  8 0 0 8   16  
  8 0 0 0   652  
  8 0   8   5094  
  8 0   0   55  
  0     0   0  
  0     0   0  
  0     0   0  
  0     0   0  
  8     0   298  
  8     8   43  
  119     2   253  
  6         29  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  8         242  
  8         18  
  8         28  
  6         13  
  3         5  
  5         8  
  5         9  
  3         6  
  4         6  
  2         4  
  3         3  
  3         7  
  3         4  
2590 8 50       51 if ($@) {
2591 0         0 die "EVAL ERROR in import_package: Generated Perl Code for package " .
2592             "'$package' failed to compile: $@\n";
2593             }
2594             }
2595              
2596             # Outputs the subroutine definitions for a given template. These are separate
2597             # from the regular code, so this function allows us to print them all
2598             # out at once.
2599             sub output_perl_defs {
2600 16     9 0 98 my $self = shift;
2601 25         310 my %args = @_;
2602 15         74 my $depth = $args{depth};
2603              
2604 12         49 my $result = '';
2605 12         28 while (my ($name, $defblk) = each (%{$self->{deftable}}) ) {
  13         97  
2606 6         10 $result .= $defblk->output_perl( depth => $depth );
2607             }
2608 14         44 return $result;
2609             }
2610              
2611             # outputs the list of functions that we have created, with names munged. This
2612             # allows us to create that pristine_namespace that is so deeply coveted.
2613             sub output_perl_deflist {
2614 10     9 0 19 my $self = shift;
2615 10         52 my %args = @_;
2616 10         22 my $depth = $args{depth};
2617 10         52 my $pre = $_NODE_::prepend x $depth;
2618              
2619 10         36 my $result = '';
2620 10         18 foreach my $name (keys( %{$self->{deftable}} )) {
  10         49  
2621 2         6 $result .= $pre . "$_NODE_::defprepend$name => 1,\n";
2622             }
2623 10         41 return $result;
2624             }
2625              
2626             =pod
2627              
2628             I
2629              
2630             Accepts a depth argument. This just outputs the code without any surrounding
2631             context and no helper functions, including the functions defined in the
2632             template itself. Just the code. Just the code. Remember that: just the code.
2633             If you can't figure out what "just the code" means, call this function and
2634             the output_perl function and do a diff. It will become immediately obvious to
2635             you. You may want to consider turning off detection of whitespace in that
2636             diff....
2637              
2638             =cut
2639             sub output_perl_code {
2640             # This merely outputs the perl code for the template, with no surrounding
2641             # context. In other words, there is no function definition, no
2642             # package name, no namespace, nothing! The only code that is output is the
2643             # internals of this particular parse tree.
2644 10     9 0 62 return shift()->{parentnode}->output_perl( @_ );
2645             }
2646              
2647             =pod
2648              
2649             I
2650              
2651             This function outputs perl code that will generate the template output. The
2652             code that is generated turns off strict 'vars'.
2653              
2654             The allowed parameters are:
2655              
2656             packagename (required)
2657             depth
2658             warn
2659              
2660             If the depth is specified, then the code will indent itself that many times at
2661             the top level. The indentation amount is four spaces by default and cannot
2662             currently be changed.
2663              
2664             If warn is specified, the warn variable ($^W) in the generated module
2665             is set to that value. Default is 0 (off).
2666              
2667             This always requires a packagename. The packagename is used to generate
2668             the surrounding context for the code output. If you don't want the package,
2669             the surrounding context, and the function definitions, you are really looking
2670             for output_perl_code, which just outputs the code definition for this template
2671             without any surrounding context.
2672              
2673             =cut
2674             sub output_perl {
2675 9     8 0 19 my $self = shift;
2676 13         60 my %args = @_;
2677 13   50     277 my $packagename = $args{'packagename'} || '';
2678 8   50     71 my $depth = $args{'depth'} || 0;
2679 13   100     55 my $warn = $args{warn} || 0;
2680              
2681 9 50       43 if (!defined($packagename)) {
2682 1         2 die "packagename required for template output_perl";
2683             }
2684              
2685 9         42 my $defined_functions = $self->output_perl_deflist( depth => 1 );
2686 9         35 my $function_defs = $self->output_perl_defs;
2687 9         101 my @templates = values %{$self->{parsedtable}};
  9         43  
2688 9         43 foreach my $t (@templates) {
2689 2         7 $defined_functions .= $t->output_perl_deflist( depth => 1 );
2690 2         7 $function_defs .= $t->output_perl_defs;
2691             }
2692             # If the package name is specified, this is the outer level.
2693             # Ignore $depth and print a package name at the beginning of things.
2694 9         363 my $header =<<"EOSTR";
2695             package $packagename;
2696             # Can't use 'strict vars' because of the need to access global variables
2697             # without a fully qualified name (the template cannot know what package it is
2698             # in before it is realized).
2699             no strict qw(vars);
2700             BEGIN {
2701             \$^W=$warn; # Set warning level.
2702             }
2703             \$START_SYM = '
2704             \$END_SYM = '?>';
2705             # Pristine and clean namespaces. Make sure to add entries here as needed.
2706             \%${packagename}::pristine_namespace = (
2707             import => 1,
2708              
2709             output => 1,
2710             import_hashref => 1,
2711             cleanup_namespace => 1,
2712             add_clean_names => 1,
2713              
2714             START_SYM => 1,
2715             END_SYM => 1,
2716              
2717             '^W' => 1,
2718              
2719             pristine_namespace => 1,
2720             clean_namespace => 1,
2721             for_count => 1,
2722             for_index => 1,
2723             for_list => 1,
2724             for_is_first => 1,
2725             for_is_last => 1,
2726              
2727             BEGIN => 1,
2728             END => 1,
2729              
2730             $defined_functions
2731             );
2732             \%${packagename}::clean_namespace = \%${packagename}::pristine_namespace;
2733             \@${packagename}::for_index = ();
2734             \@${packagename}::for_count = ();
2735             \@${packagename}::for_list = ();
2736             sub for_count { \$${packagename}::for_count[\$#${packagename}::for_count - (\$_[0] || 0)] }
2737             sub for_index { \$${packagename}::for_index[\$#${packagename}::for_index - (\$_[0] || 0)] }
2738             sub for_list { \$${packagename}::for_list[\$#${packagename}::for_list - (\$_[0] || 0)] }
2739             sub for_is_first { return for_index(\@_)==0; }
2740             sub for_is_last { return for_index(\@_)>=for_count(\@_)-1; }
2741             sub import_hashref {
2742             my \$rh_vars = shift;
2743             # Add these to the definition of a clean namespace? This means that
2744             # the variables will NOT be clobbered by cleanup_namespace if this
2745             # is set. This allows us to easily import configuration parameters
2746             # into the file (stuff that doesn't change, that isn't sensitive, etc)
2747             # and still remove other crap when needed.
2748             my \$add_to_clean = (shift()) ? 1 : 0;
2749              
2750             while (my (\$key, \$val) = each( \%\$rh_vars )) {
2751             # Use the symbol table hash \%${packagename}:: to set variables.
2752             # NOTE: we actually assign the hash values to REFERENCES of
2753             # the values passed in. Since the hash values are all type globs,
2754             # this does some serious magic. For example, if the variable
2755             # is never used and is originally a typeglob, the value stored
2756             # in the package hash is a reference. If, however, that variable
2757             # is referenced anywhere, it is dereferenced automatically. Don't
2758             # ask me how this works. It just does. Additionally, since
2759             # the package hash expects a typeglob, taking the reference
2760             # of the variable seems to do the Right Thing (tm) in all cases,
2761             # including those where a hashref of scalars is passed in, which
2762             # turns out to be very important when anything but a namespace is
2763             # imported.
2764             if (defined( \$val )) {
2765             \$${packagename}::{\$key} = \\\$val
2766             unless \$${packagename}::pristine_namespace{\$key};
2767             # keeps from clobbering default and immutable stuff.
2768             \$${packagename}::clean_namespace{\$key} = 1 if \$add_to_clean;
2769             }
2770             }
2771             #print "\$username\\n";
2772             }
2773             # Restores the original namespace (the user functions and module variables
2774             # that are here by default) by clobbering everything that was added by
2775             # the user of the module. This allows for pages to be displayed without any
2776             # variables (like passwords!) that were there before. Using things like
2777             # mod_perl or mod_fcgi makes this an especially important feature since
2778             # the module will not be reloaded with every request.
2779             sub cleanup_namespace {
2780             # Inspect each key of \%${packagename}:: and delete all keys that
2781             # are not in the clean_namespace.
2782             my \@k = keys( \%${packagename}:: );
2783             foreach my \$key (\@k) {
2784             unless (\$${packagename}::clean_namespace{\$key}) {
2785             undef \$${packagename}::{\$key}
2786             }
2787             }
2788             }
2789             # This adds variable names to the "clean" namespace.
2790             sub add_clean_names {
2791             my \$rh_varnames = shift;
2792             my \@k = keys( \%\$rh_varnames );
2793             foreach my \$key (\@k) {
2794             \$${packagename}::clean_namespace{\$key} = 1;
2795             }
2796             }
2797             #-------------------------------------------------------------------------------
2798             # TEMPLATE FUNCTIONS
2799             $function_defs
2800             #-------------------------------------------------------------------------------
2801             # OUTPUT FUNCTION
2802             sub output {
2803             # I know that we aren't using strict vars, but I still write the code
2804             # so that we COULD use them.... Hence the string reference. It gets
2805             # used by all functions and is passed into any defined template function.
2806             my \$RESULT = '';
2807             my \$_RESULT_ = \\\$RESULT;
2808             EOSTR
2809 9         54 my $footer =<<"EOSTR";
2810             return \$RESULT;
2811             }
2812              
2813             # End of module $packagename
2814             1;
2815             EOSTR
2816 9         47 return $header
2817             . $self->output_perl_code( depth => 1 )
2818             . $footer;
2819             }
2820             #-------------------------------------------------------------------------------
2821             # END
2822             #-------------------------------------------------------------------------------
2823              
2824             1;
2825              
2826             =pod
2827              
2828             =head1 FORMAL GRAMMAR DEFINITION
2829              
2830             template :==
2831             text block template
2832             | NULL
2833              
2834             text :==
2835             ANY_CHAR_LITERAL
2836             | NULL
2837              
2838             block :==
2839             if_block
2840             | for_block
2841             | while_block
2842             | def_block
2843             | comment_tag
2844             | echo_tag
2845             | call_tag
2846             | inc_tag
2847             | rawinc_tag
2848             | exec_tag
2849             | break_tag
2850             | continue_tag
2851             | NULL
2852              
2853              
2854             if_block :==
2855             if_tag template [ elif_tag template ]* [ else_tag template ]? endif_tag
2856              
2857             for_block :==
2858             for_tag template [ else_tag template ]? endfor_tag
2859              
2860             while_block :==
2861             while_tag template endwhile_tag
2862              
2863             def_block :==
2864             def_tag template enddef_tag
2865              
2866              
2867             comment_tag :==
2868             START_SYMBOL OP_COMMENT WS TEXT WS? end_symbol
2869              
2870             echo_tag :==
2871             START_SYMBOL OP_ECHO WS simple_expr WS? end_symbol
2872              
2873             if_tag :==
2874             START_SYMBOL OP_IF WS simple_expr WS? end_symbol_block
2875              
2876             elif_tag :==
2877             START_SYMBOL OP_ELIF WS simple_expr WS? end_symbol_block
2878              
2879             else_tag :==
2880             START_SYMBOL OP_ELSE WS? end_symbol_block
2881              
2882             endif_tag :==
2883             START_SYMBOL OP_ENDIF WS? end_symbol
2884              
2885             for_tag :==
2886             START_SYMBOL OP_FOR WS var_name WS OP_IN WS simple_expr WS? end_symbol_block
2887              
2888             endfor_tag :==
2889             START_SYMBOL OP_ENDFOR WS? end_symbol
2890              
2891             while_tag :==
2892             START_SYMBOL OP_WHILE WS simple_expr WS? end_symbol_block
2893              
2894             endwhile_tag :==
2895             START_SYMBOL OP_ENDWHILE WS? end_symbol
2896              
2897             break_tag :==
2898             START_SYMBOL OP_BREAK WS? end_symbol
2899              
2900             continue_tag :==
2901             START_SYMBOL OP_CONTINUE WS? end_symbol
2902              
2903             def_tag :==
2904             START_SYMBOL OP_DEF WS def_name def_param_expression WS? end_symbol_block
2905              
2906             enddef_tag :==
2907             START_SYMBOL OP_ENDDEF WS? end_symbol
2908              
2909             call_tag :==
2910             START_SYMBOL OP_CALL WS def_name call_param_expression WS? end_symbol
2911              
2912             inc_tag :==
2913             START_SYMBOL OP_INC WS QUOTE? FILENAME QUOTE? WS? end_symbol
2914              
2915             rawinc_tag :==
2916             START_SYMBOL OP_INC WS QUOTE? FILENAME QUOTE? WS? end_symbol
2917              
2918             exec_tag :==
2919             START_SYMBOL OP_EXEC WS expression WS? end_symbol
2920              
2921              
2922             var_name :==
2923             OP_DOLLAR? CHAR_NAME_LITERAL
2924              
2925             def_name :==
2926             CHAR_NAME_LITERAL
2927              
2928             def_param_expression :==
2929             OP_OPEN_PAREN WS? def_param_list OP_CLOSE_PAREN
2930              
2931             def_param_list :==
2932             CHAR_NAME_LITERAL WS? [ OP_LIST_SEP WS? CHAR_NAME_LITERAL WS? ]*
2933              
2934             call_param_expression :==
2935             OP_OPEN_PAREN WS? call_param_list OP_CLOSE_PAREN
2936              
2937             call_param_list :==
2938             simple_expr WS? [ OP_LIST_SEP WS? simple_expr WS? ]*
2939              
2940             simple_expr :==
2941             SINGLE_STATEMENT_EXPR
2942              
2943             expression :==
2944             MULTI_STATEMENT_EXPR
2945              
2946              
2947             end_symbol_block :==
2948             OP_BLOCK_TERMINAL WS? end_symbol
2949              
2950             end_symbol :==
2951             END_SYM_TEXT END_SYM_WS?
2952              
2953              
2954             WS :== \s+
2955             END_SYM_WS :== \012\015|\012|\015
2956             CHAR_NAME_LITERAL :== [a-zA-Z_][a-zA-z0-9_]*
2957             QUOTE :== ["']
2958              
2959             START_SYMBOL :== '
2960             END_SYM_TEXT :== '?>'
2961              
2962             OP_BLOCK_TERMINAL :== ':'
2963             OP_LIST_SEP :== ','
2964              
2965             OP_DOLLAR :== '$'
2966             OP_OPEN_PAREN :== '('
2967             OP_CLOSE_PAREN :== ')'
2968             OP_COMMENT :== 'comment'
2969             OP_ECHO :== 'echo'
2970             OP_IF :== 'if'
2971             OP_ELIF :== 'elif'
2972             OP_ELSE :== 'else'
2973             OP_ENDIF :== 'endif'
2974             OP_FOR :== 'for'
2975             OP_IN :== 'in'
2976             OP_ENDFOR :== 'endfor'
2977             OP_WHILE :== 'while'
2978             OP_ENDWHILE :== 'endwhile'
2979             OP_BREAK :== 'break'
2980             OP_CONTINUE :== 'continue'
2981             OP_DEF :== 'def'
2982             OP_ENDDEF :== 'enddef'
2983             OP_CALL :== 'call'
2984             OP_INC :== 'inc'
2985             OP_EXEC :== 'exec'
2986              
2987             SINGLE_STATEMENT_EXPR :==
2988             Any valid perl expression that is a single statement
2989             and evaluates to a single return value. For example, the internals
2990             of an 'if' statement should evaluate to something akin to a boolean
2991             and would have the same rules as a normal 'if' statement.
2992              
2993             MULTI_STATEMENT_EXPR :==
2994             Any valid perl expression that may or may not be multiple expressions.
2995             This basically leaves the door wide open for a generic eval.
2996              
2997             FILENAME :==
2998             This is NOT a perl expression, but an actual filename. The whitespace
2999             on either end is stripped out. No quoting is currently allowed, so
3000             take care to not use filenames with spaces for now.
3001             Example:
3002              
3003             TEXT :==
3004             This is just text. No parsing is done. Just text.
3005              
3006             =cut