File Coverage

blib/lib/PML.pm
Criterion Covered Total %
statement 977 1204 81.1
branch 314 518 60.6
condition 117 246 47.5
subroutine 127 135 94.0
pod 8 56 14.2
total 1543 2159 71.4


line stmt bran cond sub pod time code
1             ################################################################################
2             #
3             # PML.pm (PML Markup Language)
4             #
5             ################################################################################
6             #
7             # Copyright (C) 1999-2000 Peter J Jones (pjones@cpan.org)
8             # All Rights Reserved
9             #
10             # Redistribution and use in source and binary forms, with or without
11             # modification, are permitted provided that the following conditions
12             # are met:
13             #
14             # 1. Redistributions of source code must retain the above copyright
15             # notice, this list of conditions and the following disclaimer.
16             # 2. Redistributions in binary form must reproduce the above copyright
17             # notice, this list of conditions and the following disclaimer in the
18             # documentation and/or other materials provided with the distribution.
19             # 3. Neither the name of the Author nor the names of its contributors
20             # may be used to endorse or promote products derived from this software
21             # without specific prior written permission.
22             #
23             # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
24             # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25             # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26             # DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
27             # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28             # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29             # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30             # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31             # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32             # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
33             # DAMAGE.
34             #
35             ################################################################################
36             #
37             # POD
38             #
39             ################################################################################
40              
41             =pod
42              
43             =head1 NAME
44              
45             PML (PML Markup Lanuage)
46              
47             =head1 SYNOPSIS
48              
49             use PML;
50              
51             my $parser = new PML;
52              
53             $parser->parse('/path/to/somefile');
54              
55             my $output = $parser->execute;
56              
57             =head1 DESCRIPTION
58              
59             PML is a powerful text preprocessor. It supports such things as
60             variables, flow control and macros. After preprocessing a text file
61             it returns the result to your Perl script. The power comes from
62             the fact that you can even embed Perl code into the file that is
63             getting processed.
64              
65             PML was originaly designed to seperate a Perl CGI script and the
66             HTML that it generates. What sets PML apart from other similar
67             solutions is that it is not just a web solution using mod_perl.
68             You can parse PML files from the command line using the supplied
69             pml script or from within your Perl scripts using the PML Perl
70             module.
71              
72             If you do have mod_perl, you can use the supplied mod_pml Apache
73             module to parse PML files from within the Apache web server.
74              
75             =head1 EXAMPLE PML FILE
76              
77            
78            
79             ${title}
80            
81            
82             @if(${title}) {
83            

${title}

84             }
85            
86            
87              
88             =head1 DOCUMENTATION
89              
90             Documentation is supplied with this module, in the doc directory.
91              
92             language.html: describes the language.
93              
94             pml-modules.html: tells you how to write a PML module
95              
96             pml-custom-app.html: tells you how to extend PML from
97             within your application.
98              
99             =head1 USAGE
100              
101             The following is an overview of the PML API
102              
103             =cut
104             ################################################################################
105             #
106             # Package Definition
107             #
108             ################################################################################
109             package PML; {
110             package PML::Token;
111 18     18   153239 use base PML;
  18         43  
  18         2386  
112             }
113             ################################################################################
114             #
115             # Includes
116             #
117             ################################################################################
118 18     18   95 use strict;
  18         33  
  18         574  
119 18     18   87 use Carp;
  18         35  
  18         1144  
120 18     18   18561 use Text::Wrap;
  18         62399  
  18         1101  
121 18     18   123 use File::Basename;
  18         34  
  18         1994  
122 18     18   94 use Cwd qw(cwd chdir);
  18         32  
  18         1032  
123             ################################################################################
124             #
125             # Constants
126             #
127             ################################################################################
128 18     18   83 use constant ID => '$Id: PML.pm,v 1.29 2000/07/31 20:39:50 pjones Exp $';
  18         32  
  18         1462  
129              
130 18     18   85 use constant PML_V => 0; # pml variables
  18         31  
  18         738  
131 18     18   84 use constant PML_LINE => 1; # current line number
  18         29  
  18         725  
132 18     18   254 use constant PML_LINE_STR => 2; # line string
  18         32  
  18         719  
133 18     18   75 use constant PML_TOKENS => 3; # tokens array
  18         25  
  18         818  
134 18     18   91 use constant PML_TC => 4; # the token counter
  18         29  
  18         840  
135 18     18   115 use constant PML_LINES => 5; # list of lines
  18         35  
  18         737  
136 18     18   95 use constant PML_W => 6; # warnings flag
  18         59  
  18         748  
137 18     18   81 use constant PML_PEEK => 7; # peek flag
  18         30  
  18         793  
138 18     18   89 use constant PML_FILE => 8; # file name element
  18         25  
  18         936  
139 18     18   88 use constant PML_MAGIC => 9; # use magic flag
  18         33  
  18         790  
140 18     18   97 use constant PML_MAGIC_NEWLINE => 10; # magic newline flag
  18         35  
  18         728  
141 18     18   97 use constant PML_MAGIC_TAB => 11; # magic tab flag
  18         36  
  18         782  
142 18     18   85 use constant PML_COLLECTOR => 12; # collect the output from a execute
  18         29  
  18         699  
143 18     18   82 use constant PML_MACROS => 13; # hash of macro tokens
  18         33  
  18         735  
144 18     18   79 use constant PML_INCLUDES => 14; # hash of filenames for includes
  18         27  
  18         691  
145 18     18   88 use constant PML_USE_STDERR => 15; # flag; allow errors to STDERR
  18         43  
  18         732  
146 18     18   78 use constant PML_PARSE_AFTER => 16; # parse after flag
  18         31  
  18         802  
147 18     18   78 use constant PML_RECURSIVE_MAX => 17; # max times to allow recurse
  18         39  
  18         753  
148 18     18   79 use constant PML_RECURSIVE_COUNT => 18; # current number of recurse
  18         25  
  18         879  
149 18     18   78 use constant PML_NEED_LIST => 19; # list of needed modules
  18         39  
  18         716  
150 18     18   78 use constant PML_OBJ_DIR => 20; # dir to store object
  18         35  
  18         823  
151 18     18   77 use constant PML_LOOP_COUNTERS => 21; # are we in a loop flags
  18         31  
  18         779  
152 18     18   76 use constant PML_DIE_MESSAGE => 22; # message given durring a die
  18         35  
  18         692  
153 18     18   83 use constant PML_PCALLBACKS => 23; # object specific parser callbacks
  18         301  
  18         823  
154 18     18   83 use constant PML_TCALLBACKS => 24; # object specific token callbacks
  18         31  
  18         692  
155              
156 18     18   78 use constant PML_TOKEN_ID => 0; # store the token id
  18         27  
  18         728  
157 18     18   92 use constant PML_TOKEN_CONTEXT => 1; # the context that the token is called in
  18         29  
  18         700  
158 18     18   80 use constant PML_TOKEN_FILE_LOC => 2; # arg; block; file
  18         42  
  18         676  
159 18     18   75 use constant PML_TOKEN_LABEL => 3; # label name if we have one
  18         39  
  18         859  
160 18     18   93 use constant PML_TOKEN_DATA => 4; # the actual token data
  18         39  
  18         722  
161              
162 18     18   84 use constant CONTEXT_SCALAR => 1; # scalar context
  18         50  
  18         718  
163 18     18   89 use constant CONTEXT_LIST => 2; # list context
  18         28  
  18         645  
164              
165 18     18   76 use constant FILE_LOC_FILE => 0; # token within file scope
  18         28  
  18         685  
166 18     18   91 use constant FILE_LOC_ARG => 1; # token within arg list
  18         25  
  18         791  
167 18     18   85 use constant FILE_LOC_BLOCK => 2; # token within block
  18         28  
  18         666  
168              
169 18     18   78 use constant TOKEN_IF => 1; # if function token
  18         25  
  18         716  
170 18     18   77 use constant TOKEN_NOT => 2; # unless function
  18         20  
  18         712  
171 18     18   76 use constant TOKEN_EVAL => 3; # eval internal token
  18         34  
  18         732  
172 18     18   6231 use constant TOKEN_PERL => 4; # perl function token
  18         39  
  18         738  
173 18     18   78 use constant TOKEN_SET => 5; # set function token
  18         27  
  18         797  
174 18     18   81 use constant TOKEN_INCLUDE => 6; # include function token
  18         24  
  18         754  
175 18     18   91 use constant TOKEN_MACRO => 7; # macro function token
  18         41  
  18         764  
176 18     18   85 use constant TOKEN_VARIABLE => 8; # allows the expansion of a variable outside a string
  18         25  
  18         669  
177 18     18   81 use constant TOKEN_FOREACH => 9; # foreach function token
  18         35  
  18         948  
178 18     18   82 use constant TOKEN_WHILE => 10; # while and until loop token
  18         28  
  18         760  
179 18     18   82 use constant TOKEN_SKIP => 11; # skip function
  18         25  
  18         692  
180 18     18   80 use constant TOKEN_WRAP => 12; # wrap function
  18         25  
  18         682  
181 18     18   88 use constant TOKEN_RIB => 13; # replace if blank function
  18         41  
  18         882  
182 18     18   102 use constant TOKEN_MAGIC_MACRO => 14; # call a unknown macro
  18         46  
  18         889  
183 18     18   279 use constant TOKEN_LOOP_INT => 15; # next, redo, last functions
  18         31  
  18         814  
184              
185 18     18   78 use constant TOKEN_SET_SET => 1; # set sub tokens
  18         27  
  18         738  
186 18     18   77 use constant TOKEN_SET_IF => 2; # |
  18         26  
  18         724  
187 18     18   84 use constant TOKEN_SET_APPEND => 3; # |
  18         28  
  18         778  
188 18     18   108 use constant TOKEN_SET_PREPEND => 4; # |
  18         33  
  18         781  
189 18     18   78 use constant TOKEN_SET_CONCAT => 5; # |
  18         30  
  18         692  
190              
191 18     18   89 use constant TOKEN_START_AVAL => 1001;# what token id to start at for others
  18         28  
  18         754  
192 18     18   90 use constant ARG_BLOCK => 1; # function with arguments and a block
  18         24  
  18         1102  
193 18     18   80 use constant ARG_ONLY => 2; # function with only arguments, no block
  18         32  
  18         809  
194 18     18   81 use constant BLOCK_ONLY => 3; # function with only a block, no arguments
  18         27  
  18         696  
195              
196 18     18   78 use constant G_MARKER => '@';
  18         34  
  18         1407  
197 18     18   88 use constant G_RE_IF => qr/^\@(elsif|else)/o;
  18         32  
  18         812  
198             ################################################################################
199             #
200             # Global Variables and Default Settings
201             #
202             ################################################################################
203 18     18   321 use vars qw($VERSION $AUTOLOAD);
  18         27  
  18         28657  
204             $VERSION = '0.4.1';
205              
206             my %function_arg_block = (
207             'if' => \&parse_if,
208             'unless' => [\&parse_if, 1],
209             'macro' => \&parse_macro,
210             'foreach' => \&parse_foreach,
211             'while' => \&parse_while,
212             'until' => [\&parse_while, 1],
213             'wrap' => \&parse_wrap,
214             'rib' => \&parse_rib,
215             );
216              
217             my %function_arg_only = (
218             'set' => [\&parse_set, TOKEN_SET_SET],
219             'setif' => [\&parse_set, TOKEN_SET_IF],
220             'append' => [\&parse_set, TOKEN_SET_APPEND],
221             'prepend' => [\&parse_set, TOKEN_SET_PREPEND],
222             'concat' => [\&parse_set, TOKEN_SET_CONCAT],
223             'include' => \&parse_include,
224             'warning' => \&parse_warning,
225             'need' => \&parse_need,
226             'next' => [\&parse_loop_int, 'next'],
227             'redo' => [\&parse_loop_int, 'redo'],
228             'last' => [\&parse_loop_int, 'last'],
229             );
230              
231             my %function_block_only = (
232             );
233              
234             my %function_block_no_parse = (
235             'perl' => \&parse_perl,
236             'skip' => \&parse_skip,
237             );
238              
239             my %allow_remove_tabs = (
240             'set' => 1,
241             'setif' => 1,
242             'append' => 1,
243             'prepend' => 1,
244             'concat' => 1,
245             'include' => 1,
246             'need' => 1,
247             'if' => 1,
248             'unless' => 1,
249             'macro' => 1,
250             'foreach' => 1,
251             'while' => 1,
252             'until' => 1,
253             'rib' => 1,
254             );
255              
256             my %allow_remove_newline = (
257             'macro' => 1,
258             'set' => 1,
259             'setif' => 1,
260             'append' => 1,
261             'prepend' => 1,
262             'concat' => 1,
263             'include' => 1,
264             'need' => 1,
265             'if' => 1,
266             'unless' => 1,
267             'while' => 1,
268             'until' => 1,
269             'skip' => 1,
270             'perl' => 1,
271             'rib' => 1,
272             'wrap' => 1,
273             );
274              
275             my %loop_functions = (
276             'foreach' => 1,
277             'while' => 1,
278             'until' => 1,
279             );
280              
281             my %tokens = (
282             TOKEN_IF() => \&token_if,
283             TOKEN_NOT() => \&token_not,
284             TOKEN_EVAL() => \&token_eval,
285             TOKEN_PERL() => \&token_perl,
286             TOKEN_SET() => \&token_set,
287             TOKEN_INCLUDE() => \&token_include,
288             TOKEN_MACRO() => \&token_macro,
289             TOKEN_VARIABLE() => \&token_variable,
290             TOKEN_FOREACH() => \&token_foreach,
291             TOKEN_WHILE() => \&token_while,
292             TOKEN_SKIP() => \&token_skip,
293             TOKEN_WRAP() => \&token_wrap,
294             TOKEN_RIB() => \&token_rib,
295             TOKEN_MAGIC_MACRO() => \&token_magic_macro,
296             TOKEN_LOOP_INT() => \&token_loop_int,
297             );
298              
299             my @invalid_functions;
300             my $next_token = TOKEN_START_AVAL;
301              
302             my @inc = (
303             '.',
304             '..',
305             '../include',
306             '/usr/local/share/pml',
307             '/usr/local/pml/include',
308             );
309              
310             my $RE_NAME = qr/(?:(?:[A-Za-z_]|\$\{)(?:\w|\$|(?<=\$)\{|\}|::|\.|-|[\[\]])*)/o;
311             my $RE_VAR = qr/(?:[A-Za-z_\$](?:\w|::|\.|-|\[|\]|\{|\}|\$)*)|\./o;
312             my $RE_VAR_TEST = qr/([^\$]*)(?
313             my $RE_FUNCTION = '^([^' . G_MARKER() . ']*)(?
314             my $RE_LOOP_INT = qr/^(next|last|redo):(\w+)?/o;
315             my $RE_LABEL = qr/([A-Z0-9]+):\s*$/o;
316              
317 18     18   99 use vars qw($DEBUG);
  18         31  
  18         327412  
318             $DEBUG = 0;
319             ################################################################################
320             #------------------------------------------------------------------------------#
321              
322             =pod
323              
324             =head2 METHOD new
325              
326              
327             Arguments:
328             1) Class or PML Object to clone
329             2) Hash Reference (Optional)
330              
331             Returns:
332             1) A PML Object
333              
334             Description:
335             new creates a new PML Object and returns the object
336             to the caller. You can optionaly pass in a hash
337             refernece, where the keys are PML variables to set
338             and the values are the values to set those variables
339             to.
340              
341             =cut
342              
343             #------------------------------------------------------------------------------#
344             ################################################################################
345             sub new
346             {
347 333     333 1 7368 my $ref = shift;
348 333   66     1420 my $class = ref($ref) || $ref;
349 333         470 my $v = shift;
350 333         525 my $self = [];
351            
352             # check to see if the is a PML::Token object
353 333 100       872 if ($class eq 'PML::Token') {
354 311         424 my $self = [];
355 311         595 $self->[PML_TOKEN_ID] = undef;
356 311         498 $self->[PML_TOKEN_CONTEXT] = CONTEXT_SCALAR;
357 311         393 $self->[PML_TOKEN_FILE_LOC] = FILE_LOC_FILE;
358 311         498 $self->[PML_TOKEN_DATA] = undef;
359            
360 311 50       1092 _token_id($self, $v) if defined $v;
361 311         2039 return bless $self, $class;
362             }
363            
364 22 100       84 if (not ref $ref) {
365             # create new PML Object and set some variables
366 20         114 $self->[PML_V] = {PMLVERSION => $VERSION};
367 20         59 $self->[PML_W] = 0;
368 20         51 $self->[PML_LINE] = 0;
369 20         57 $self->[PML_LINE_STR] = 'on Line 1';
370 20         47 $self->[PML_TOKENS] = [];
371 20         57 $self->[PML_PEEK] = 0;
372 20         55 $self->[PML_FILE] = 'input stream';
373 20         58 $self->[PML_MAGIC] = 1;
374 20         47 $self->[PML_MAGIC_NEWLINE] = 1;
375 20         48 $self->[PML_MAGIC_TAB] = 0;
376 20         47 $self->[PML_COLLECTOR] = '';
377 20         50 $self->[PML_MACROS] = {};
378 20         49 $self->[PML_INCLUDES] = {};
379 20         42 $self->[PML_USE_STDERR] = 1;
380 20         47 $self->[PML_PARSE_AFTER] = 0;
381 20         73 $self->[PML_RECURSIVE_MAX] = 1000;
382 20         50 $self->[PML_RECURSIVE_COUNT] = 0;
383 20         49 $self->[PML_NEED_LIST] = [];
384 20         63 $self->[PML_OBJ_DIR] = '/tmp';
385 20         68 $self->[PML_LOOP_COUNTERS] = {};
386 20         56 $self->[PML_DIE_MESSAGE] = '';
387 20         57 $self->[PML_TCALLBACKS] = {};
388 20         154 $self->[PML_PCALLBACKS] = {
389             'function_arg_block' => {},
390             'function_arg_only' => {},
391             'function_block_only' => {},
392             'function_block_no_parse' => {},
393             };
394              
395             # Set up the loop counters
396 20         216 $self->[PML_LOOP_COUNTERS]{$_} = 0 foreach keys %loop_functions;
397             } else { # we need to clone an existsing object
398 2 50       122 eval {require Storable} or # make sure Storable is avaliable
  2         25  
399             croak "can't call new as a method unless you install the Storable module";
400              
401 2         171 $self->[PML_V] = Storable::dclone($ref->[PML_V]);
402 2         5 $self->[PML_W] = $ref->[PML_W];
403 2         4 $self->[PML_LINE] = $ref->[PML_LINE];
404 2         3 $self->[PML_LINE_STR] = $ref->[PML_LINE_STR];
405 2         119 $self->[PML_TOKENS] = Storable::dclone($ref->[PML_TOKENS]);
406 2         4 $self->[PML_PEEK] = $ref->[PML_PEEK];
407 2         8 $self->[PML_FILE] = $ref->[PML_FILE];
408 2         5 $self->[PML_MAGIC] = $ref->[PML_MAGIC];
409 2         2 $self->[PML_MAGIC_NEWLINE] = $ref->[PML_MAGIC_NEWLINE];
410 2         4 $self->[PML_MAGIC_TAB] = $ref->[PML_MAGIC_TAB];
411 2         6 $self->[PML_COLLECTOR] = $ref->[PML_COLLECTOR];
412 2         34 $self->[PML_MACROS] = Storable::dclone($ref->[PML_MACROS]);
413 2         21 $self->[PML_INCLUDES] = Storable::dclone($ref->[PML_INCLUDES]);
414 2         5 $self->[PML_USE_STDERR] = $ref->[PML_USE_STDERR];
415 2         3 $self->[PML_PARSE_AFTER] = $ref->[PML_PARSE_AFTER];
416 2         3 $self->[PML_RECURSIVE_MAX] = $ref->[PML_RECURSIVE_MAX];
417 2         3 $self->[PML_RECURSIVE_COUNT]= $ref->[PML_RECURSIVE_COUNT];
418 2         18 $self->[PML_NEED_LIST] = Storable::dclone($ref->[PML_NEED_LIST]);
419 2         6 $self->[PML_OBJ_DIR] = $ref->[PML_OBJ_DIR];
420 2         38 $self->[PML_LOOP_COUNTERS] = Storable::dclone($ref->[PML_LOOP_COUNTERS]);
421 2         7 $self->[PML_DIE_MESSAGE] = $ref->[PML_DIE_MESSAGE];
422 2         3 $self->[PML_TCALLBACKS] = {%{$ref->[PML_TCALLBACKS]}};
  2         5  
423 2         3 $self->[PML_PCALLBACKS] = {};
424            
425             # clone the callback holders
426 2         3 foreach my $key (keys %{$ref->[PML_PCALLBACKS]}) {
  2         15  
427 8         8 $self->[PML_PCALLBACKS]{$key} = {%{$ref->[PML_PCALLBACKS]{$key}}};
  8         23  
428             };
429             }
430              
431             # Set some other variables if passed into this sub
432 22 100       159 %{$self->[PML_V]} = (%{$self->[PML_V]}, %$v) if defined $v;
  1         5  
  1         5  
433            
434             # Bless and return this new object
435 22         100 bless $self, $class;
436             } # <-- End new -->
437             ################################################################################
438             #
439             # ==== ready ==== ##############################################################
440             #
441             # Arguments:
442             # 1) A PML Object
443             # 2) A String (filename) or A reference to an array
444             #
445             # Returns:
446             # None
447             #
448             # Description:
449             # Gets the PML Object ready to parse
450             #
451             ################################################################################
452             sub ready
453             {
454 19     19 0 43 my ($self, $x) = @_;
455            
456             #
457             # check the arguments
458             #
459 19 50 33     155 croak("Usage: ready(pml_object, lines_string|lines_arrayref)")
460             unless defined $self and defined $x;
461            
462             #
463             # setup the lines array ref
464             #
465 19 100       80 if ((ref $x) eq 'ARRAY')
466             {
467 18         108 $self->[PML_LINES] = $x;
468             }
469             else
470             {
471 1 50       41 open(SOURCE, $x) || die "cannot open file \"$x\": $!\n";
472 1         25 @{$self->[PML_LINES]} = ;
  1         5  
473 1         11 close SOURCE;
474 1         5 $self->[PML_FILE] = $x;
475             }
476             } # <-- End ready -->
477             ################################################################################
478             #------------------------------------------------------------------------------#
479              
480             =pod
481              
482             =head2 METHOD parse
483              
484              
485             Arguments:
486             1) PML Object
487             2) Filename or a reference to an array of lines
488              
489             Returns:
490             1) True if parse was successful
491              
492             Description:
493             parse will parse the file or array that you give
494             it. If there is an error, such as a syntax error,
495             parse will throw an exception via die. Therefore
496             if you want to catch the exception you should wrap
497             the call to parse in an eval block and check $@.
498             If $@ is true there was and error and the error
499             message can be found in $@.
500              
501             =cut
502              
503             #------------------------------------------------------------------------------#
504             ################################################################################
505             sub parse
506             {
507 19     19 1 566 my ($self, $x) = @_;
508 19         64 my ($cwd);
509            
510             # check the arguments
511 19 50 33     184 croak("Usage: parse(pml_object, lines_string|lines_arrayref)")
512             unless defined $self and defined $x;
513            
514             # call ready to prep the pml object
515 19         122 $self->ready($x);
516            
517            
518             # if we were given the filename to parse then chdir
519             # to where that file lives before we parse it
520 19         136086 $cwd = cwd;
521            
522 19 100       543 if (not ref $x) {
523 1         118 my $dir = dirname $x;
524            
525 1 50       241 unless (chdir $dir) {
526 0         0 print STDERR "A error occured while trying to change directroies to parse the file \"$x\": $!\n";
527 0         0 die "$!\n";
528             }
529             }
530            
531             # now parse all the lines
532 19         137 my ($line, @tokens);
533              
534 19         126 while (1) {
535 176 100 100     1563 $line = $self->next_line unless defined $line and length $line;
536 176 100       672 defined $line or last;
537            
538 158 50       455 if ($self->[PML_PARSE_AFTER]) {
539 0 0       0 if ($line =~ $self->[PML_PARSE_AFTER]) {
540 0         0 $self->[PML_PARSE_AFTER] = 0;
541             }
542            
543 0         0 $line = '';
544 0         0 next;
545             }
546            
547 158         755 @tokens = $self->parse_one_line(\$line);
548 157 100       538 push(@{$self->[PML_TOKENS]}, @tokens) if @tokens;
  149         399  
549             }
550            
551 18         117 foreach my $invalid_function (@invalid_functions) {
552 2 50 33     34 unless (
553             exists $self->[PML_MACROS]{$invalid_function->[0]}
554             and defined $self->[PML_MACROS]{$invalid_function->[0]}
555             ) {
556 0         0 $self->error_syntax("$invalid_function->[1], the macro or function \"$invalid_function->[0]\" is not defined.");
557             }
558             }
559            
560             # now that we are done parsing we can
561             # move back to the dir where we started
562 18         2930 chdir $cwd;
563              
564 18         179 return 1;
565             } # <-- End parse -->
566             ################################################################################
567             #------------------------------------------------------------------------------#
568              
569             =pod
570              
571             =head2 METHOD execute
572              
573              
574             Arguments:
575             1) PML Object
576             2) A Hash Reference (Optional)
577              
578             Returns:
579             1) The text in the file after processing it
580              
581             Description:
582             execute will process the file and return the
583             post-processed text. You can optionaly pass in a
584             reference to a hash, where the keys are PML variables
585             to set and the values are the value to set them
586             to. This is a good way so talk to your text file.
587              
588             You can call execute as many times as you wish.
589             Each call will start afresh at the top of the parsed
590             file.
591              
592             =cut
593              
594             #------------------------------------------------------------------------------#
595             ################################################################################
596             sub execute
597             {
598 18     18 1 17678 my ($self, $v) = @_;
599 18         43 my ($tmp);
600            
601             #
602             # check arguments
603             #
604 18 50       107 croak("Usage: execute(pml_object, hash_ref_optional)") unless defined $self;
605            
606             #
607             # make sure that there are tokens
608             #
609 18 50       128 unless ($self->[PML_TOKENS])
610             {
611 0         0 croak("There were no tokens to process, maybe you did not call parse or maybe the file was empty");
612             }
613            
614             #
615             # Clean out the collector if we need to
616             #
617 18         92 undef $self->[PML_COLLECTOR];
618            
619             #
620             # set any variables
621             #
622 18         166 $self->[PML_V]{$_} = $v->{$_} foreach keys %$v;
623            
624             #
625             # set some default values
626             #
627 18         62 $self->[PML_TC] = 0;
628            
629             #
630             # now walk the token list and execute tokens
631             #
632 18         71 while ($#{$self->[PML_TOKENS]} >= $self->[PML_TC])
  166         665  
633             {
634 148         453 $tmp = $self->tokens_execute (
635             $self->[PML_TOKENS][$self->[PML_TC]]
636             );
637              
638 148 50       4673 $self->[PML_COLLECTOR] .= $tmp if defined $tmp;
639            
640             # check to see if it died
641 148 50       669 if ($self->[PML_DIE_MESSAGE]) {
642             # see if it is ours
643 0 0       0 if ($self->[PML_DIE_MESSAGE] =~ /$RE_LOOP_INT/o) {
644             # do stuff
645 0 0       0 if ($1 eq 'next') {
    0          
    0          
646 0         0 $self->[PML_TC]++;
647 0         0 next;
648             } elsif ($1 eq 'redo') {
649 0         0 redo;
650             } elsif ($1 eq 'last') {
651 0         0 last;
652             }
653             } else { # it's not ours
654 0         0 die $self->[PML_DIE_MESSAGE];
655             }
656             }
657            
658 148         362 $self->[PML_TC]++;
659             }
660            
661 18         107 return $self->[PML_COLLECTOR];
662             } # <-- End execute -->
663             ################################################################################
664             #------------------------------------------------------------------------------#
665              
666             =pod
667              
668             =head2 METHOD v
669              
670              
671             Arguments:
672             1) PML Object
673              
674             -- or --
675            
676             2) Variable Name
677              
678             -- or --
679              
680             2) Variable Name
681             3) New Value
682              
683             -- or --
684              
685             2) Hash Reference
686              
687             Returns:
688             1) Depends on Arguments, see below.
689              
690             Description:
691             The v method allows you to get and set PML variables.
692             There are a few different ways to use v, and we
693             will cover them all.
694              
695             Arguments:
696             1) PML Object
697              
698             In this case, you call v with only the object, no
699             arguments. This will return an array of variable
700             names. This is so you can see what variables are
701             defined.
702              
703             Arguments:
704             1) PML Object
705             2) Variable Name
706              
707             This time you give a name of a variable. The v
708             method will return the current value of that
709             variable, or undef if it is not set.
710              
711             Arguments:
712             1) PML Object
713             2) Variable Name
714             3) Value
715              
716             Here, you give a variable name and the value to
717             set it to. The v method will then set the give
718             variable to the value you gave it. It should return
719             the same value.
720              
721             Arguments:
722             1) PML Object
723             2) Hash Reference
724              
725             To limit method calls, you can give a hash reference
726             where the keys are the variable to set and the
727             values are the value to set those variables to.
728             Returns 1.
729              
730             =cut
731              
732             #------------------------------------------------------------------------------#
733             ################################################################################
734             sub v
735             {
736 2     2 1 21 my ($self, $variable, $value) = @_;
737            
738 2 50       12 unless ($self) {
739 0         0 carp "Usage: v(PML, [Variable, [Value]])";
740 0         0 return undef;
741             }
742            
743 2 50       4 unless ($variable) {
744 0         0 return %{$self->[PML_V]};
  0         0  
745             }
746              
747 2 50       6 if (ref $variable eq 'HASH') {
748 0         0 foreach my $key (keys %$variable) {
749 0         0 $self->[PML_V]{$key} = $variable->{$key};
750             }
751 0         0 return 1;
752             }
753            
754 2 50       5 if (defined $value) {
755 0         0 $self->[PML_V]{$variable} = $value;
756             }
757            
758 2         10 return $self->[PML_V]{$variable};
759             } # <-- End v -->
760             ################################################################################
761             #------------------------------------------------------------------------------#
762              
763             =pod
764              
765             =head2 METHOD parse_after
766              
767              
768             Arguments:
769             1) PML Object
770             2) Regular Expression String or Object
771              
772             Returns:
773             1) Nothing
774              
775             Description:
776             Used before the call to parse, this method will
777             effect when parsing will start. When you call the
778             parse method, it will search for the given regex,
779             when that regex matches, parsing will begin on the
780             NEXT line.
781              
782             =cut
783              
784             #------------------------------------------------------------------------------#
785             ################################################################################
786             sub parse_after
787             {
788 0     0 1 0 my ($self, $regex) = @_;
789            
790 0 0       0 $regex = qr/$regex/ unless ref $regex eq 'Regexp';
791 0         0 $self->[PML_PARSE_AFTER] = $regex;
792             } # <-- End parse_after -->
793             ################################################################################
794             #------------------------------------------------------------------------------#
795              
796             =pod
797              
798             =head2 CLASS METHOD register
799              
800              
801             Arguments:
802             1) Class ie PML->register(...)
803             2) A Hash, keys are described below
804              
805             Returns:
806             1) An ID number to refer to your token
807              
808             Description:
809             The register function is used to extend the PML
810             syntax. You register a callback for a new PML
811             function. When parsing the text, PML will call your
812             parser-callback to assist parsing. When executing,
813             PML will call your token-callback to process the
814             token created by your parser-callback.
815              
816             Here is what you should pass to register:
817              
818             parse => A callback. Defaults to using the
819             builtin autoparser
820             token => A callback. You must give this.
821             name => The name of the new PML function to add.
822             type => See Types below
823            
824             Callbacks:
825              
826             A callback is a reference to a subroutine like this:
827             \&myfunc -- or -- sub{}
828              
829             It can also be a reference to an array,
830             where the first element is a reference to
831             a subroutine and the remaining elements
832             are passed to the subroutine as arguemnts
833             after the standard arguments.
834              
835             Types:
836              
837             The types are constants in PML.pm.
838              
839             PML->ARG_ONLY This means that your new
840             function will only take
841             arguments, just like the
842             builtin @set function.
843              
844             PML->BLOCK_ONLY This means that your new
845             function only takes a block
846             just like the builtin @perl
847             function.
848              
849             PML->ARG_BLOCK This means that your new
850             function takes arguments
851             and a block, just like the
852             builtin @if function.
853              
854             =cut
855              
856             #------------------------------------------------------------------------------#
857             ################################################################################
858             sub register
859             {
860 8     8 1 101 my $ref = shift;
861 8         14 my $table;
862 8         58 my %options = (
863             parse => undef,
864             token => undef,
865             name => undef,
866             type => ARG_ONLY,
867             id => undef,
868            
869             @_,
870             );
871            
872 8 50 33     51 unless (defined $options{token} and defined $options{name}) {
873 0         0 croak "You must, at a minimum, give token sub and name arguments to PML->register";
874             }
875            
876 8         19 foreach ('token', 'parse') {
877 16 100       49 next unless defined $options{$_};
878 8 50       27 unless (ref($options{$_}) eq 'CODE') {
879 0 0 0     0 unless (ref($options{$_}) eq 'ARRAY' and ref($options{$_}->[0]) eq 'CODE') {
880 0         0 croak "callback must be a ref to a sub or a ref to an array who's first elemnt is a ref to a sub";
881             }
882             }
883             }
884            
885 8 100       39 if ($options{type} == ARG_BLOCK) {
    100          
    50          
886 2 100       15 if (ref $ref) {
887 1         3 $table = $ref->[PML_PCALLBACKS]{'function_arg_block'};
888             } else {
889 1         2 $table = \%function_arg_block;
890             }
891             } elsif ($options{type} == ARG_ONLY) {
892 4 100       13 if (ref $ref) {
893 1         7 $table = $ref->[PML_PCALLBACKS]{'function_arg_only'};
894             } else {
895 3         7 $table = \%function_arg_only;
896             }
897             } elsif ($options{type} == BLOCK_ONLY) {
898 2 100       9 if (ref $ref) {
899 1         2 $table = $ref->[PML_PCALLBACKS]{'function_block_only'};
900             } else {
901 1         3 $table = \%function_block_only;
902             }
903             } else {
904 0         0 croak "Bad type argument to register, what is type \"$options{type}\"?";
905             }
906            
907 8   33     43 $options{id} ||= $next_token++;
908 8 100       17 if (ref $ref) { # this is a method call
909 3         13 $ref->[PML_TCALLBACKS]{$options{id}} = $options{token};
910             } else { # this is a class call
911 5         38 $tokens{$options{id}} = $options{token};
912             }
913 8   50     66 $table->{$options{name}} = $options{parse} || [\&auto_parse, \%options];
914            
915 8         27 return $options{id};
916             } # <-- End register -->
917             ################################################################################
918             #
919             # ==== execute_callback ==== ###################################################
920             #
921             # Arguments:
922             # 1) A callback Object
923             # 2) All the args to send to the callback
924             #
925             # Returns:
926             # What ever the callback returns
927             #
928             # Description:
929             # Calls the callback
930             #
931             ################################################################################
932             sub execute_callback
933             {
934 418     418 0 1063 my ($callback, @args) = @_;
935            
936 418 100 33     1287 if (ref($callback) eq 'CODE')
    50          
937             {
938 382         17179 return $callback->(@args);
939             }
940             elsif (ref($callback) eq 'ARRAY' and ref($callback->[0]) eq 'CODE')
941             {
942 36         87 return $callback->[0]->(@args, @$callback[1 .. $#{$callback}]);
  36         230  
943             }
944             else
945             {
946 0         0 print STDERR 'Internal error, bad callback object ';
947 0         0 print STDERR "\"ref(callback) = ";
948 0         0 print STDERR scalar ref($callback);
949 0         0 print STDERR "\", sorry but you found a bug. ";
950 0         0 print STDERR caller, "\n";
951 0         0 exit 1;
952             }
953             } # <-- End execute_callback -->
954             ################################################################################
955             #------------------------------------------------------------------------------#
956              
957             =pod
958              
959             =head2 METHOD warning
960              
961              
962             Arguments:
963             1) PML Object
964             2) Boolean Flag (Optional)
965              
966             Returns:
967             1) Current Warning Flag
968              
969             Description:
970             The warning method will set the warning flag to
971             the one given, if one was given. It always returns
972             the current value. If the flag is true, PML will
973             print warnings to STDERR.
974              
975             =cut
976              
977             #------------------------------------------------------------------------------#
978             ################################################################################
979             sub warning
980             {
981 2     2 1 5 my ($self, $flag) = @_;
982            
983 2 50       13 croak "Usage: warning(pml_object, [flag])" unless defined $self;
984            
985 2 50       7 $self->[PML_W] = $flag if $flag;
986 2         4 return $self->[PML_W];
987             } # <-- End warning -->
988             ################################################################################
989             #------------------------------------------------------------------------------#
990              
991             =pod
992              
993             =head2 METHOD use_stderr
994              
995             Arguments:
996             1) PML Object
997             2) True to allow use of stderr, false to disallow
998              
999             Returns:
1000             1) Nothing
1001              
1002             Description:
1003             Sets the use_stderr flag for this object
1004              
1005             =cut
1006              
1007             #------------------------------------------------------------------------------#
1008             ################################################################################
1009             sub use_stderr ($$)
1010             {
1011 1     1 1 102 my ($self, $flag) = @_;
1012 1         4 $self->[PML_USE_STDERR] = $flag;
1013             } #<-- End: use_stderr -->
1014             ################################################################################
1015             #
1016             # ==== tokens_execute ==== #####################################################
1017             #
1018             # Arguments:
1019             # 1) A PML Object
1020             # 2) A reference to an array of tokens
1021             #
1022             # Returns:
1023             # The results of the tokens
1024             #
1025             # Description:
1026             # runs through the tokens and returns the results
1027             #
1028             ################################################################################
1029             sub tokens_execute
1030             {
1031 329     329 0 654 my ($self, @tokens) = @_;
1032 329         371 my ($token, @rv, $callback);
1033            
1034             # check arguments
1035 329 50       625 croak("Usage: tokens_execute(pml_object, tokens)")
1036             unless defined $self;
1037            
1038             # reset the die message
1039 329         705 $self->[PML_DIE_MESSAGE] = '';
1040            
1041             # return an empty list if there are no tokens
1042 329 50       696 return () unless @tokens;
1043            
1044             # check to see if there is only one token and
1045             # if that token is realy a array ref to a token
1046 329 100 100     1679 if (@tokens == 1 and ref($tokens[0]) eq 'ARRAY') {
1047 65         80 @tokens = @{$tokens[0]};
  65         258  
1048             }
1049            
1050             # process the tokens
1051 329         563 foreach $token (@tokens) {
1052             # skip this token unless it is defined
1053 346 100       667 next unless defined $token;
1054            
1055             # check for an array of tokens
1056 345 50       678 if (ref $token eq 'ARRAY') {
1057 0         0 push @rv, scalar $self->tokens_execute(@$token);
1058 0         0 next;
1059             }
1060            
1061             # if this is not a token just add it to the result
1062 345 100       695 unless (ref $token eq 'PML::Token') {
1063 2         4 push @rv, $token;
1064 2         5 next;
1065             }
1066            
1067             # check to see if the token exists
1068 343 100       1792 if (exists $self->[PML_TCALLBACKS]{$token->id}) {
    50          
1069 3         14 $callback = $self->[PML_TCALLBACKS]{$token->id};
1070             } elsif (exists $tokens{$token->id}) {
1071 340         1209 $callback = $tokens{$token->id};
1072             } else {
1073 0         0 die("Hmmm... bad token id '$token->[0]', you found a bug in PML");
1074             }
1075            
1076             # we wrap the next line in an eval because
1077             # if we come across a @next, @redo or @last
1078             # they will call die
1079 343         727 eval {
1080             # call the token and record it's return value
1081 343         719 push @rv, execute_callback($callback, $self, $token);
1082             };
1083            
1084             # check to see if we died
1085 343 100       1064 if ($@) {$self->[PML_DIE_MESSAGE]=$@; last}
  1         2  
  1         3  
1086             }
1087            
1088             # why in the heck am i getting
1089             # `Use of uninitialized value at ...'
1090 329         986 local ($^W)=0; #FIXME
1091            
1092             # now check the calling context
1093 329 100       594 if (wantarray) {
1094 67         330 return @rv;
1095             } else {
1096 262         1290 return join '', @rv;
1097             }
1098             } # <-- End tokens_execute -->
1099             ################################################################################
1100             #
1101             # ==== parse_one_line ==== #####################################################
1102             #
1103             # Arguments:
1104             # 1) A PML Object
1105             # 2) A line of text
1106             # 3) A ref to an array of lines (Optional, default is $self->[PML_LINES])
1107             #
1108             # Returns:
1109             # A List of PML_TOKENS to add to the token array
1110             #
1111             # Description:
1112             # Parses the line, getting more lines from $self->[PML_LINES] if necessary
1113             # then returns entries to the tokens array
1114             #
1115             ################################################################################
1116             sub parse_one_line
1117             {
1118 203     203 0 347 my ($self, $line_ref, $lines) = @_;
1119 203         249 my (@tokens, $func, @arguments, @block);
1120 0         0 my ($token, $pre_text, $label, $callback);
1121            
1122             # check arguments
1123 203 50 33     1060 croak("Usage: parse_one_line(pml_object, lines)") unless defined $self and defined $line_ref;
1124 203 50 66     1177 croak("PML object is missing the lines array") if not $lines and not defined $self->[PML_LINES];
1125            
1126             # set lines to self PML_LINES if not already set
1127 203   66     737 $lines ||= $self->[PML_LINES];
1128            
1129             # now check to see if there is a call to a built-in function
1130             # or a call to a macro
1131 203 100       3064 if ($$line_ref =~ s/$RE_FUNCTION//o) {
1132             # store the removed text
1133 82         316 $pre_text = $1; $func = $2;
  82         328  
1134            
1135             # is the pretext a Label?
1136 82 100 100     343 if ($loop_functions{$func} and $pre_text =~ s/$RE_LABEL//o) {
1137 1         3 $label = $1;
1138             }
1139            
1140             # Remove pre_text if it only contains tabs and
1141             # we want magic and it is allowed for this func
1142 82 100 66     291 if ($pre_text and $self->[PML_MAGIC]) {
1143 4         14 $pre_text =~ s/^\s+$//o;
1144             }
1145            
1146             # Put the pretext into a token so that it is not lost
1147 82 100       191 if ($pre_text) {
1148 4         26 $token = new PML::Token TOKEN_EVAL;
1149 4         23 $token->data($pre_text);
1150 4         8 push @tokens, $token;
1151             }
1152            
1153 82 100 100     889 if (
    100 100        
    100 66        
    100 100        
1154             exists $function_arg_only{$func} or
1155             exists $self->[PML_PCALLBACKS]{'function_arg_only'}{$func} ){
1156             # these type have args with no blocks
1157 32 100       141 if (exists $self->[PML_PCALLBACKS]{'function_arg_only'}{$func}) {
1158 1         3 $callback = $self->[PML_PCALLBACKS]{'function_arg_only'}{$func};
1159             } else { #build in parser or register-class parser
1160 31         132 $callback = $function_arg_only{$func};
1161             }
1162 32         155 @arguments = $self->parse_arguments($line_ref, $lines);
1163 32         174 $token = execute_callback($callback, $self, [@arguments], undef, $line_ref, $lines);
1164 32 50 66     243 if ($token and $label) {$token->label($label)}
  0         0  
1165 32 100       100 if ($token) {push @tokens, $token};
  29         206  
1166             } elsif (
1167             exists $function_arg_block{$func} or
1168             exists $self->[PML_PCALLBACKS]{'function_arg_block'}{$func} ){
1169             # these functions have args and blocks
1170 32 100       112 if (exists $self->[PML_PCALLBACKS]{'function_arg_block'}{$func}) {
1171 1         4 $callback = $self->[PML_PCALLBACKS]{'function_arg_block'}{$func};
1172             } else {
1173 31         102 $callback = $function_arg_block{$func};
1174             }
1175 32         117 @arguments = $self->parse_arguments($line_ref, $lines);
1176 32         115 @block = $self->parse_block($line_ref, $lines);
1177             # call the built in and store the tokens that it returns
1178 32         169 $token = execute_callback($callback, $self, [@arguments], [@block], $line_ref, $lines);
1179 32 100 100     216 if ($token and $label) {$token->label($label)}
  1         13  
1180 32 100       99 if ($token) {push @tokens, $token};
  27         53  
1181             } elsif (
1182             exists $function_block_no_parse{$func} or
1183             exists $self->[PML_PCALLBACKS]{'function_block_no_parse'}{$func} ){
1184             # these are fuctions that need to parse their own blocks
1185             # we just grab whats between the { and } and give them the rest
1186 9 50       32 if (exists $self->[PML_PCALLBACKS]{'function_block_no_parse'}{$func}) {
1187 0         0 $callback = $self->[PML_PCALLBACKS]{'function_block_no_parse'}{$func};
1188             } else {
1189 9         28 $callback = $function_block_no_parse{$func};
1190             }
1191 9         30 $self->magic_newline($line_ref, $lines);
1192 9         39 $token = execute_callback (
1193             $callback,
1194             $self,
1195             $self->gut('{', '}', $line_ref, $lines, 1)
1196             );
1197 9 50 33     74 if ($token and $label) {$token->label($label)}
  0         0  
1198 9 50       32 if ($token) {push @tokens, $token};
  9         15  
1199             } elsif (
1200             exists $function_block_only{$func} or
1201             exists $self->[PML_PCALLBACKS]{'function_block_only'}{$func} ){
1202             # these are functins that only have a block
1203 2 100       7 if (exists $self->[PML_PCALLBACKS]{'function_block_only'}{$func}) {
1204 1         4 $callback = $self->[PML_PCALLBACKS]{'function_block_only'}{$func};
1205             } else {
1206 1         3 $callback = $function_block_only{$func};
1207             }
1208 2         10 @block = $self->parse_block($line_ref, $lines);
1209 2         9 $token = execute_callback($callback, $self, undef, [@block], $line_ref, $lines);
1210 2 50 33     23 if ($token and $label) {$token->label($label)}
  0         0  
1211 2 50       7 if ($token) {push @tokens, $token};
  2         4  
1212             } else {
1213             # these are macros or functions that are not defined
1214             # we need to see if the macro has a variable in it's name
1215 7 100       69 if ($func =~ /$RE_VAR_TEST/o) {
1216 1         5 $token = new PML::Token TOKEN_MAGIC_MACRO;
1217             } else { # this is just a normal macro call
1218 6         44 $token = new PML::Token TOKEN_MACRO;
1219             }
1220 7         38 $token->data([$func, $self->parse_arguments($line_ref, $lines)]);
1221 7 50 33     60 if ($token and $label) {$token->label($label)}
  0         0  
1222 7 50       26 if ($token) {push @tokens, $token}
  7         19  
1223            
1224 7 100       227 if ($self->peek(qr/^{/o, $line_ref, $lines)) {
1225 1         14 $self->error_syntax
1226             ("there is no such function called '$func'");
1227             }
1228 6 100 100     64 unless (
1229             $token->id == TOKEN_MAGIC_MACRO or
1230             exists $self->[PML_MACROS]{$func} ){
1231 3         20 push @invalid_functions,
1232             [$func, $self->[PML_LINE_STR]];
1233             }
1234             }
1235            
1236             # Check to see if we are allowed to remove the trailing
1237             # spaces and newline
1238 81 100       260 if ($allow_remove_newline{$func}) {
1239 62         283 $$line_ref =~ s/^\s*\n//o;
1240             }
1241            
1242             } else {
1243             # if there were no calls to a built-in then this
1244             # line will only contain variables and/or text
1245             # so we add the line with the EVAL token
1246 121         706 $token = new PML::Token TOKEN_EVAL;
1247 121         1088 $token->data($$line_ref);
1248 121         189 push @tokens, $token;
1249 121         216 $$line_ref = ''; # we took the whole line
1250             }
1251            
1252 202         954 return @tokens;
1253             } # <-- End parse_one_line -->
1254             ################################################################################
1255             #
1256             # ==== parse_arguments ==== ####################################################
1257             #
1258             # Arguments:
1259             # 1) A PML Object
1260             # 2) A reference to a line to cut up
1261             # 3) A ref to an array of lines (Optional, defaults to self->[PML_LINES]
1262             #
1263             # Returns:
1264             # A list of tokens that make up the arguments to the function call
1265             #
1266             # Description:
1267             # Looks in the line for the arguments to the function call
1268             #
1269             ################################################################################
1270             sub parse_arguments
1271             {
1272 75     75 0 165 my ($self, $line_ref, $lines) = @_;
1273 75         113 my (@tokens, $guts, @args, $x, $y, @queue);
1274 0         0 my ($token, $stoken);
1275 75         160 my $M = G_MARKER();
1276            
1277             # check arguments
1278 75 50 33     454 croak("Usage: parse_arguments(pml_object, line_reference)") unless defined $self and defined $line_ref;
1279            
1280             # set lines to self PML_LINES if not already set
1281 75   33     180 $lines ||= $self->[PML_LINES];
1282            
1283             # Remove any space and newlines that might apear before the arguments
1284 75         329 $self->magic_newline($line_ref, $lines);
1285            
1286             # check to see if the first char is an expected character
1287 75         162 $x = substr $$line_ref, 0, 1;
1288 75 50 33     463 if (not defined $x or $x ne '(') {
1289 0         0 $self->error_syntax("expected a '(' but found '$x' instead");
1290             }
1291              
1292             # get the guts between the '(' and the ')'
1293 75         260 $guts = $self->gut('(', ')', $line_ref, $lines);
1294            
1295             # return a empty list if there are no guts
1296 75 100       234 return () unless length $guts;
1297            
1298             # clean up the arg list
1299 71         171 $guts =~ s/\n+//ogs;
1300 71         235 $guts =~ s/^\s+//os;
1301 71         191 $guts =~ s/\s+$//os;
1302            
1303             # now break up the line
1304 71         301 while ($guts =~ /\S/o) {
1305 103         192 $x = substr($guts, 0, 1);
1306            
1307 103 100 100     1549 if ($x eq '"' or $x eq "'") {
    100          
    100          
1308 27         96 $y = $self->gut($x, $x, \$guts, []);
1309 27         674 while ($y =~ /$RE_FUNCTION/o) {
1310 0         0 push @queue,
1311             $self->parse_one_line(\$y, []);
1312             }
1313            
1314 27 50       89 if (length $y) {
1315 27         287 $token = new PML::Token TOKEN_EVAL;
1316 27         286 $token->data($y);
1317 27         62 push @queue, $token;
1318             }
1319             } elsif ($guts =~ s/^(\${$RE_VAR})\s*(?=,|=>|$)//o) {
1320 9         50 $token = new PML::Token TOKEN_VARIABLE;
1321 9         48 $token->data($y = $1);
1322 9         17 push @queue, $token;
1323             } elsif ($guts =~ s/^((?:\d+)(?:\.\d+)?)\s*(?=,|=>|$)//o) {
1324 35         170 $token = new PML::Token TOKEN_EVAL;
1325 35         241 $token->data($y = $1);
1326 35         62 push @queue, $token;
1327             } else {
1328 32 100       283 if ($guts =~ /^[^,]*?(?
1329 3         32 push @queue,
1330             $self->parse_one_line(\$guts, []);
1331             } else {
1332 29         94 $guts =~ s/^([^,]+)//o;
1333 29         111 ($y = $1) =~ s/\s+$//o;
1334 29 50       68 if (length $y) {
1335 29         179 $token = new PML::Token TOKEN_EVAL;
1336 29         283 $token->data($y);
1337 29         67 push @queue, $token;
1338             }
1339             }
1340             }
1341            
1342             # did we run out of arguments or should we move
1343             # on to the next one?
1344 103 50       542 if ($guts =~ s/^\s*(?:(?:,\s*)|(?:=>\s*)|$)//o) {
1345 103 50       231 if (@queue > 1) {
1346 0         0 push @tokens, [@queue];
1347 0         0 @queue = ();
1348             } else {
1349 103 50       531 push @tokens, shift @queue if @queue;
1350             }
1351             }
1352             }
1353            
1354             # now just make sure that the queue is empty
1355 71 50       194 if (@queue) {
1356 0 0       0 if (@queue > 1) {
1357 0         0 push @tokens, [@queue];
1358             } else {
1359 0         0 push @tokens, shift @queue;
1360             }
1361             }
1362            
1363             # set some token flags on all the tokens
1364 71         193 foreach $token (@tokens) {
1365 103 50       273 if (ref $token eq 'ARRAY') {
1366 0         0 foreach $stoken (@$token) {
1367 0         0 $stoken->file_loc(FILE_LOC_ARG);
1368 0         0 $stoken->context(CONTEXT_LIST);
1369 0         0 } next;
1370             }
1371            
1372 103         549 $token->file_loc(FILE_LOC_ARG);
1373 103         582 $token->context(CONTEXT_LIST);
1374             }
1375            
1376             # return the tokens that we collected
1377 71         314 return @tokens;
1378             } # <-- End parse_arguments -->
1379             ################################################################################
1380             #
1381             # ==== parse_block ==== ########################################################
1382             #
1383             # Arguments:
1384             # 1) A PML Object
1385             # 2) A Reference to a line
1386             # 3) A ref to an array of lines (Optional, defaults to self->[PML_LINES])
1387             #
1388             # Returns:
1389             # A List of tokens for the block
1390             #
1391             # Description:
1392             # tries to get the block following the function call
1393             #
1394             ################################################################################
1395             sub parse_block
1396             {
1397 44     44 0 176 my ($self, $line_ref, $lines) = @_;
1398 44         56 my ($x, @tokens, $guts, $token);
1399            
1400             # check arguments
1401 44 50 33     264 croak("Usage: parse_block(pml_object, line_reference")
1402             unless defined $self and defined $line_ref;
1403            
1404             # set lines to self PML_LINES if not already set
1405 44   33     123 $lines ||= $self->[PML_LINES];
1406            
1407             # Remove any spaces or newlines
1408 44         110 $self->magic_newline($line_ref, $lines);
1409            
1410             # check to see if the first char is an expected character
1411 44         87 $x = substr $$line_ref, 0, 1;
1412            
1413 44 50       202 unless ($x eq '{') {
1414 0         0 $self->error_syntax (
1415             "can't find opening brace, saw '$x' instead"
1416             );
1417             }
1418            
1419             # get the guts between the '{' and the '}'
1420 44         129 $guts = $self->gut('{', '}', $line_ref, $lines, 1);
1421 44         148 $self->magic_newline_gut(\$guts);
1422 44         168 $self->magic_tab(\$guts);
1423            
1424             # parse the text in the block
1425 44         108 while (length $guts) {
1426 42         320 push @tokens, $self->parse_one_line(\$guts, []);
1427             }
1428            
1429             # set some token flags
1430 44         109 foreach $token (@tokens) {
1431 45         195 $token->context(CONTEXT_SCALAR);
1432 45         193 $token->file_loc(FILE_LOC_BLOCK);
1433             }
1434            
1435 44         287 return @tokens;
1436             } # <-- End parse_block -->
1437             ################################################################################
1438             #
1439             # ==== magic_newline ==== ######################################################
1440             #
1441             # Arguments:
1442             # 1) A PML Object
1443             # 2) A reference to a string
1444             # 3) A reference to a array of strings (optional)
1445             #
1446             # Returns:
1447             # None
1448             #
1449             # Description:
1450             # Removes all spaces and newlines from the front of arg 2.
1451             # pulls another string off arg3 if necessary
1452             #
1453             ################################################################################
1454             sub magic_newline
1455             {
1456 138     138 0 216 my ($self, $line_ref, $lines) = @_;
1457 138         241 my $line_num = $self->[PML_LINE];
1458              
1459 138 50 33     795 return unless $self->[PML_MAGIC] and $self->[PML_MAGIC_NEWLINE];
1460            
1461 138         165 while (1)
1462             {
1463 173 50 66     454 last unless length($$line_ref) or @{$lines};
  35         119  
1464 173 100       407 $$line_ref = $self->next_line($lines) unless length($$line_ref);
1465 173         673 $$line_ref =~ s/^(\s|\n)+//og;
1466 173 100       508 last if length $$line_ref;
1467             }
1468            
1469 138 50       381 unless (length $$line_ref)
1470             {
1471 0         0 $self->warn_error("did not expect EOF, was looking for a char starting from line $line_num");
1472             }
1473             } # <-- End magic_newline -->
1474             ################################################################################
1475             #
1476             # ==== magic_newline_gut ==== ##################################################
1477             #
1478             # Arguments:
1479             # 1) A PML Object
1480             # 2) A reference to a string
1481             #
1482             # Returns:
1483             # None
1484             #
1485             # Description:
1486             # Removes prefixing and trail spaces and newline
1487             #
1488             ################################################################################
1489             sub magic_newline_gut
1490             {
1491 44     44 0 72 my ($self, $line_ref) = @_;
1492            
1493 44 50 33     421 return unless $self->[PML_MAGIC] and $self->[PML_MAGIC_NEWLINE];
1494            
1495 44         162 $$line_ref =~ s/^\s*\n//os;
1496 44         152 $$line_ref =~ s/\n\s*$//os;
1497             } # <-- End magic_newline_gut -->
1498             ################################################################################
1499             #
1500             # ==== magic_tab ==== ##########################################################
1501             #
1502             # Arguments:
1503             # 1) A PML Object
1504             # 2) A reference to a string
1505             #
1506             # Returns:
1507             # None
1508             #
1509             # Description:
1510             # Removes one tab from the begining of each line
1511             #
1512             ################################################################################
1513             sub magic_tab
1514             {
1515 44     44 0 77 my ($self, $line_ref) = @_;
1516            
1517 44 50 33     284 return unless $self->[PML_MAGIC] and $self->[PML_MAGIC_TAB];
1518 0         0 $$line_ref =~ s/^\t//mog;
1519             } # <-- End magic_tab -->
1520             ################################################################################
1521             #
1522             # ==== gut ==== ################################################################
1523             #
1524             # Arguments:
1525             # 1) A PML Object
1526             # 2) A starting delimiter
1527             # 3) An ending delimiter
1528             # 4) A ref to a string
1529             # 5) A ref to an array to get more lines (optional)
1530             # 6) A flag (true means don't sub gut for ('|")) (optioal)
1531             #
1532             # Returns:
1533             # An array of lines that are in between the delimiters
1534             #
1535             # Description:
1536             # This is a replacement for the orignial gut. It will do a charater by
1537             # charter look instead of using regexs
1538             #
1539             ################################################################################
1540             sub gut
1541             {
1542 256     256 0 586 my ($self, $od, $cd, $line_ref, $lines, $sflag) = @_;
1543 256         343 my (@repository, @gut, $result);
1544 0         0 my ($got_od, $last_char, $last_real_char, $char, $count, $ds);
1545 0         0 my (@sub_gut, @pre_sg, @post_sg);
1546 256         1126 my $sub_gut_regex = qr/:=:\((\d+)\):=:/;
1547            
1548 256         761 @pre_sg = (':', '=', ':', '(');
1549 256         507 @post_sg = (')', ':', '=', ':');
1550            
1551 256   33     614 $lines ||= $self->[PML_LINES];
1552 256         455 $last_char = $last_real_char = '';
1553 256         288 $ds = 0; # do we have a double back slash condition?
1554            
1555 256         274 while (1)
1556             {
1557 1941 100       4087 unless (@repository) # fill the repository
1558             {
1559 374 50 66     1599 last unless length($$line_ref) or @{$lines};
  87         298  
1560 374 100       902 $$line_ref = $self->next_line($lines)
1561             unless length $$line_ref;
1562 374 50       736 length $$line_ref or next;
1563 374         2352 push @repository, split(//, $$line_ref);
1564 374         1350 $$line_ref = '';
1565             }
1566            
1567 1941         2644 $char = shift @repository;
1568 1941 50       4352 defined $char or next;
1569            
1570 1941 100       3747 unless ($got_od)
1571             {
1572 256 50       507 unless ($char eq $od) {
1573 0         0 $self->error_syntax (
1574             "looking for open delimiter '$od' ".
1575             "but found '$char' instead, near '$char".
1576             join('', @repository) .
1577             "'"
1578             );
1579             } else {
1580 256         316 $got_od = 1;
1581 256         297 $count++;
1582 256         414 next;
1583             }
1584             }
1585            
1586 1685 100 66     10091 if ($last_real_char ne '\\' and $char =~ /^(['"])/o and $od ne $1 and not $sflag)
      100        
      100        
1587             {
1588 31         107 my $tmp = join '', $1, @repository; undef @repository;
  31         94  
1589 31         457 push @gut, $1, @pre_sg, scalar @sub_gut, @post_sg, $1;
1590 31         549 push @sub_gut, $self->gut($1, $1, \$tmp, $lines);
1591 31         63 $$line_ref = $tmp;
1592 31         71 next;
1593             }
1594            
1595 1654 50 33     3557 if ($char eq $od and ($last_real_char ne '\\' or $ds))
      66        
1596             {
1597 91 100       237 $count++ unless $od eq $cd;
1598             }
1599            
1600 1654 50 33     4092 if ($char eq $cd and ($last_real_char ne '\\' or $ds))
      66        
1601             {
1602 289         314 $count--;
1603 289 100       597 last unless $count;
1604             }
1605            
1606 1398         2173 push @gut, $char;
1607            
1608 1398 50 33     4683 if ($last_real_char eq '\\' and $char eq '\\') {
1609 0         0 $ds = 1;
1610             } else {
1611 1398         1717 $ds = 0;
1612             }
1613            
1614 1398         1495 $last_real_char = $char;
1615 1398 100       4458 $last_char = $char unless
1616             $char =~ /^(\s|\n|\\)/o;
1617             }
1618            
1619 256 50       528 if ($count) {
1620 0         0 $self->error_syntax (
1621             "I can't seem to find the closing '$cd'"
1622             );
1623             }
1624            
1625 256 100       772 $$line_ref = join '', @repository if @repository;
1626 256         541 $result = join '', @gut;
1627 256 100       899 $result =~ s/$sub_gut_regex/$sub_gut[$1]/gos if @sub_gut;
1628 256         1599 return $result;
1629             } # <-- End gut -->
1630             ################################################################################
1631             #
1632             # ==== next_line ==== ##########################################################
1633             #
1634             # Arguments:
1635             # 1) PML Object
1636             # 2) An Arrary Reference of Lines
1637             #
1638             # Returns:
1639             # 1) A line from the Array
1640             # -- or --
1641             # 2) undef if no more lines
1642             #
1643             # Description:
1644             # goes through the array of lines trying to find one that we can return.
1645             # lines that beging with a pound signare skipped. Lines that
1646             # end with a backslash are joined with the line that follows it.
1647             #
1648             ################################################################################
1649             sub next_line
1650             {
1651 280     280 0 498 my ($self, $lines) = @_;
1652 280         340 my ($line);
1653            
1654             # Check to make sure that we got the correct number of arguments
1655 280   50     1330 $lines ||= $self->[PML_LINES] || undef;
      66        
1656 280 50 33     1438 croak("Usage: next_line(pml_object, array_ref)") unless defined $self and defined $lines;
1657            
1658             # Now we loop pulling out lines
1659 280         365 while (@{$lines}) {
  336         1204  
1660             # Get a fresh line to work with
1661 318         694 $line = shift @$lines;
1662            
1663             # update the line counter
1664 318 50       933 if ($lines == $self->[PML_LINES]) {
1665 318         1007 $self->[PML_LINE_STR] = 'on line ' . ++$self->[PML_LINE];
1666 318         721 $self->[PML_LINE_STR] .= " from " . $self->[PML_FILE];
1667             }
1668            
1669             # reasons to check next line
1670 318 50       2094 defined $line or next; # this line needs to have something on it
1671 318 100       1188 $line =~ /^\s*#/o and next; # skip if line is a comment
1672             #length($line) or next;
1673            
1674 262         755 return $line;
1675             }
1676              
1677 18         237 return undef;
1678             } # <-- End next_line -->
1679             ################################################################################
1680             #
1681             # ==== peek ==== ###############################################################
1682             #
1683             # Arguments:
1684             # 1) PML Object
1685             # 2) A Regular Expression that you are looking for
1686             # 3) A ref to a string (current line)
1687             # 4) Array Reference (Optional if $self->[PML_LINES] exists)
1688             #
1689             # Returns:
1690             # True if that patter will be found; False otherwise
1691             #
1692             # Description:
1693             # Scans through the array of lines looking for the first charater
1694             # that is not space or newline and the tries to match the regular
1695             # expression on the remaining string.
1696             #
1697             ################################################################################
1698             sub peek
1699             {
1700 27     27 0 53 my ($self, $regex, $line_ref, $lines) = @_;
1701 27         143 my ($i);
1702            
1703 27 100       118 if ($$line_ref =~ /(\S+)/o) {
1704 9 100       99 return $1 =~ $regex ? 1 : undef;
1705             }
1706            
1707 18         37 for ($i=0; $i<=$#{$lines}; $i++) {
  29         118  
1708 28 100       121 next unless $lines->[$i] =~ /(\S+)/o;
1709 17 100       151 return $1 =~ $regex ? 1 : undef;
1710             }
1711             } # <-- End peek -->
1712             ################################################################################
1713             #
1714             # ==== replace_variable ==== ###################################################
1715             #
1716             # Arguments:
1717             # 1) A PML Object
1718             # 2) The name of the variable
1719             #
1720             # Returns:
1721             # A String
1722             #
1723             # Description:
1724             # Returns a string with the value of the varable
1725             #
1726             ################################################################################
1727             sub replace_variable
1728             {
1729 70     70 0 105 my ($self, $vref) = @_;
1730 70         74 my ($index, $v, $x);
1731            
1732             # get the inside of the variable
1733 70         191 $v = $self->gut('{', '}', $vref, []);
1734            
1735             # does this match a variable regex?
1736 70 50       733 unless ($v =~ /^$RE_VAR/o) {
1737 0         0 return "\${$v}";
1738             }
1739            
1740             # keep from deep recursion
1741 70         188 $self->_in;
1742              
1743             # look for another variable inside this one
1744 70         507 while ($v =~ s/^$RE_VAR_TEST//o) {
1745 7 100       25 $x .= $1 if $1;
1746 7         28 $x .= $self->replace_variable(\$v);
1747             }
1748            
1749             # set x back to v if v did not have a variable
1750 70 100       176 $x .= $v if length $v;
1751            
1752             # no longer going to call myself!
1753 70         151 $self->_out;
1754            
1755             # now, check once more for allowed charaters
1756 70 50       335 ($v = $x) =~ /$RE_VAR/o or return $v;
1757            
1758            
1759             # now look to see if this is an array index
1760 70 100       366 if ($v =~ /^(.*?)\[(\d+)\]$/o) {
    100          
    100          
    50          
1761 6         14 $index = $2;
1762 6         10 $v = $1;
1763            
1764 6 50       22 unless (ref($self->[PML_V]{$v}) eq 'ARRAY') {
1765 0 0       0 print STDERR "Variable $v is not an array but you used the index operator on it, the result is a blank string.\n" if $self->[PML_W];
1766 0 0       0 return '' unless wantarray; return ();
  0         0  
1767             }
1768            
1769 6 50       19 if (defined $self->[PML_V]{$v}[$index]) {
1770 6         34 return $self->[PML_V]{$v}[$index];
1771             } else {
1772 0 0       0 print STDERR "the index '$index' to the variable '$v' was used when it had no value\n" if $self->[PML_W];
1773 0         0 return '';
1774             }
1775             } elsif ($v =~ /^([^\.]+)\.([^\.]+)$/o) { # Hash index?
1776 4         12 $index = $2;
1777 4         8 $v = $1;
1778            
1779 4 50       23 unless (ref($self->[PML_V]{$v}) eq 'HASH') {
1780 0 0       0 print STDERR "variable '$v' is not a hash, but you used it as one. the result is a blank value\n" if $self->[PML_W];
1781 0         0 return '';
1782             }
1783            
1784 4 50       17 if (defined $self->[PML_V]{$v}{$index}) {
1785 4         25 return $self->[PML_V]{$v}{$index};
1786             } else {
1787 0 0       0 print STDERR "the hash key '$index' to the hash '$v' was not set, the result is a blank value\n" if $self->[PML_W];
1788 0         0 return '';
1789             }
1790             } elsif (ref ($self->[PML_V]{$v}) eq 'ARRAY') { # whole array?
1791 1 50       4 return @{$self->[PML_V]{$v}} if wantarray;
  1         9  
1792 0         0 return join ' ', @{$self->[PML_V]{$v}};
  0         0  
1793             } elsif (ref ($self->[PML_V]{$v}) eq 'HASH') { # whole hash?
1794 0 0       0 return values %{$self->[PML_V]{$v}} if wantarray;
  0         0  
1795 0         0 return join ' ', values %{$self->[PML_V]{$v}};
  0         0  
1796             } else { # normal variable
1797 59 50       125 if (defined $self->[PML_V]{$v}) {
1798 59         302 return $self->[PML_V]{$v};
1799             } else {
1800 0 0       0 print STDERR "the variable '$v' was used before it was set, the result is a blank value\n" if $self->[PML_W];
1801 0         0 return '';
1802             }
1803             }
1804             } # <-- End replace_variable -->
1805             ################################################################################
1806             #
1807             # ==== rel2abs ==== ############################################################
1808             #
1809             # Arguments:
1810             # 1) A relative path to a file
1811             # 2) Full path to a starting directory [Optional]
1812             #
1813             # Returns:
1814             # The full path to that file based on arg2 or cwd
1815             #
1816             # Description:
1817             # Removes the ./ and ../ from the path
1818             #
1819             ################################################################################
1820             sub rel2abs
1821             {
1822 0     0 0 0 my ($path, $base) = @_;
1823 0         0 my @path_parts = split(/\//, $path);
1824 0         0 my (@base_parts, $current_part);
1825            
1826 0   0     0 $base ||= cwd;
1827            
1828 0         0 @base_parts = split(/\//, $base);
1829            
1830 0         0 while ($current_part = shift @path_parts)
1831             {
1832 0 0       0 next if $current_part eq '.';
1833 0 0       0 pop @base_parts if $current_part eq '..';
1834 0 0       0 push @base_parts, $current_part unless $current_part eq '..';
1835             }
1836            
1837 0         0 return '/' . join '/', @base_parts;
1838             } # <-- End rel2abs -->
1839             ################################################################################
1840             #
1841             # ==== error ==== ##############################################################
1842             #
1843             # Arguments:
1844             # 1) A PML Object
1845             # 2) A String
1846             #
1847             # Returns:
1848             # None
1849             #
1850             # Description:
1851             # Prints an error message and exit 1
1852             #
1853             ################################################################################
1854             sub error
1855             {
1856 0     0 0 0 my ($self, $string) = @_;
1857            
1858 0         0 print STDERR "PML error on line $self->[PML_LINE] from $self->[PML_FILE]: $string\n";
1859 0         0 exit 1;
1860             } # <-- End error -->
1861             ################################################################################
1862             #
1863             # ==== warn_error ==== #########################################################
1864             #
1865             # Arguments:
1866             # 1) A PML Object
1867             # 2) A String
1868             #
1869             # Returns:
1870             # None
1871             #
1872             # Description:
1873             # Prints an error and returns
1874             #
1875             ################################################################################
1876             sub warn_error
1877             {
1878 0     0 0 0 my ($self, $string) = @_;
1879            
1880 0         0 print STDERR "PML error on line $self->[PML_LINE] from $self->[PML_FILE]: $string\n";
1881             } # <-- End warn_error -->
1882             ################################################################################
1883             #
1884             # ==== error_syntax ==== #######################################################
1885             #
1886             # Arguments:
1887             # 1) A PML Object
1888             # 2) An Description of the syntax error
1889             #
1890             # Returns:
1891             # None
1892             #
1893             # Description:
1894             # Reports an error then dies
1895             #
1896             ################################################################################
1897             sub error_syntax
1898             {
1899 1     1 0 3 my ($self, $message) = @_;
1900 1         5 my ($text);
1901            
1902 1         4 $text = "PML Syntax Error " . $self->[PML_LINE_STR] . "\n";
1903 1         4 $text .= "$message\n";
1904            
1905 1 50       7 if ($self->[PML_USE_STDERR]) {
1906 0         0 print STDERR $text;
1907             }
1908            
1909 1         26 die $text;
1910             } # <-- End error_syntax -->
1911             ################################################################################
1912             #
1913             # ==== _in ==== ################################################################
1914             #
1915             # Arguments:
1916             # 1) A PML Object
1917             #
1918             # Returns:
1919             # None
1920             #
1921             # Description:
1922             # Increments the current Recurse count and check to see if we
1923             # went over the max.
1924             #
1925             ################################################################################
1926             sub _in
1927             {
1928 77     77   91 my $self = shift;
1929            
1930 77         109 $self->[PML_RECURSIVE_COUNT]++;
1931            
1932 77 50       219 if ($self->[PML_RECURSIVE_COUNT] > $self->[PML_RECURSIVE_MAX]) {
1933 0         0 print STDERR "deep recursion detected.\n";
1934 0         0 print STDERR "max recursion set to "
1935             . $self->[PML_RECURSIVE_MAX] . "\n";
1936 0         0 croak("recurse error");
1937             }
1938             } # <-- End _in -->
1939             ################################################################################
1940             #
1941             # ==== _out ==== ###############################################################
1942             #
1943             # Arguments:
1944             # 1) PML Object
1945             #
1946             # Returns:
1947             # None
1948             #
1949             # Description:
1950             # Lowers the recurse count
1951             #
1952             ################################################################################
1953             sub _out
1954             {
1955 77     77   149 $_[0]->[PML_RECURSIVE_COUNT]--;
1956             } # <-- End _out -->
1957             ################################################################################
1958             #
1959             # ==== append ==== #############################################################
1960             #
1961             # Arguments:
1962             # 1) PML Object
1963             # 2) PML Object to append to object in arg 1
1964             #
1965             # Returns:
1966             # None
1967             #
1968             # Description:
1969             # Appends PML Object 2 to PML Object 1, PML Object 1 takes priority
1970             # does not append TOKENS though
1971             #
1972             ################################################################################
1973             sub append
1974             {
1975 1     1 0 5 my ($self, $append) = @_;
1976            
1977 1         5 %{$self->[PML_INCLUDES]} = (
  1         6  
1978 1         6 %{$self->[PML_INCLUDES]},
1979 1         2 %{$append->[PML_INCLUDES]}
1980             );
1981            
1982 1         3 %{$self->[PML_MACROS]} = (
  1         6  
1983 1         5 %{$self->[PML_MACROS]},
1984 1         5 %{$append->[PML_MACROS]}
1985             );
1986            
1987 1         11 %{$self->[PML_V]} = (
  1         8  
1988 1         5 %{$self->[PML_V]},
1989 1         3 %{$append->[PML_V]}
1990             );
1991              
1992 1         3 return $self;
1993             } # <-- End append -->
1994             ################################################################################
1995             #
1996             # ==== _token_id ==== ##########################################################
1997             #
1998             # Arguments:
1999             # 1) PML::Token Object
2000             # 2) New Token ID (Optional)
2001             #
2002             # Returns:
2003             # The Current Token ID
2004             #
2005             # Description:
2006             # Sets the Token ID to the one given, if any, then returns the ID.
2007             #
2008             ################################################################################
2009             sub _token_id
2010             {
2011 1344     1344   1734 my ($token, $id) = @_;
2012            
2013 1344 100       2469 if (defined $id) {
2014 312         600 $token->[PML_TOKEN_ID] = $id;
2015             }
2016            
2017 1344         5231 return $token->[PML_TOKEN_ID];
2018             } # <-- End _token_id -->
2019             ################################################################################
2020             #
2021             # ==== _token_context ==== #####################################################
2022             #
2023             # Arguments:
2024             # 1) PML::Token Object
2025             # 2) New Context ID (Optional)
2026             #
2027             # Returns:
2028             # Current Context ID
2029             #
2030             # Description:
2031             # Sets the Context ID if given, then returns the context ID
2032             #
2033             ################################################################################
2034             sub _token_context
2035             {
2036 191     191   253 my ($token, $context) = @_;
2037            
2038 191 100       429 if (defined $context) {
2039 148 50 66     713 unless (
2040             $context == CONTEXT_SCALAR ||
2041             $context == CONTEXT_LIST
2042             ) {
2043 0         0 carp "context not scalar or array";
2044 0         0 return $token->[PML_TOKEN_CONTEXT];
2045             }
2046            
2047 148         222 $token->[PML_TOKEN_CONTEXT] = $context;
2048             }
2049            
2050 191   50     885 return $token->[PML_TOKEN_CONTEXT] || CONTEXT_SCALAR;
2051             } # <-- End _token_context -->
2052             ################################################################################
2053             #
2054             # ==== _token_file_loc ==== ####################################################
2055             #
2056             # Arguments:
2057             # 1) PML::Token Object
2058             # 2) New File Location ID (Optional)
2059             #
2060             # Returns:
2061             # File Location ID
2062             #
2063             # Description:
2064             # Sets the File Location ID if given, then returns the FLI
2065             #
2066             ################################################################################
2067             sub _token_file_loc
2068             {
2069 371     371   474 my ($token, $fli) = @_;
2070            
2071 371 100       878 if (defined $fli) {
2072 148 50 66     901 unless (
      66        
2073             $fli == FILE_LOC_FILE or
2074             $fli == FILE_LOC_ARG or
2075             $fli == FILE_LOC_BLOCK
2076             ) { # then
2077 0         0 carp "file location id is not file, arg or block";
2078 0         0 return $token->[PML_TOKEN_FILE_LOC];
2079             }
2080            
2081 148         240 $token->[PML_TOKEN_FILE_LOC] = $fli;
2082             }
2083            
2084 371         1176 return $token->[PML_TOKEN_FILE_LOC];
2085             } # <-- End _token_file_loc -->
2086             ################################################################################
2087             #
2088             # ==== _token_data ==== ########################################################
2089             #
2090             # Arguments:
2091             # 1) PML::Token Object
2092             # 2) Data (optional)
2093             #
2094             # Returns:
2095             # Data
2096             #
2097             # Description:
2098             # Sets the data section to whatever you give, or returns it
2099             #
2100             ################################################################################
2101             sub _token_data
2102             {
2103 656     656   1022 my ($token, $data) = (shift, shift);
2104            
2105 656 100       1356 if (defined $data) {
2106 312         686 $token->[PML_TOKEN_DATA] = $data;
2107             }
2108            
2109 656         6948 return $token->[PML_TOKEN_DATA];
2110             } # <-- End _token_data -->
2111             ################################################################################
2112             #
2113             # ==== _token_label ==== #######################################################
2114             #
2115             # Arguments:
2116             # 1) PML::Token Object
2117             # 2) Label (optional)
2118             #
2119             # Returns:
2120             # The current label
2121             #
2122             # Description:
2123             # Sets the label if one is given, return the label
2124             #
2125             ################################################################################
2126             sub _token_label
2127             {
2128 3     3   8 my ($token, $label) = @_;
2129            
2130 3 100       9 if (defined $label) {
2131 1         3 $token->[PML_TOKEN_LABEL] = $label;
2132             }
2133            
2134 3         15 return $token->[PML_TOKEN_LABEL];
2135             } # <-- End _token_label -->
2136             ################################################################################
2137             #
2138             # ==== object_directory ==== ###################################################
2139             #
2140             # Arguments:
2141             # 1) A PML Variable
2142             # 2) A directory to place objects (optional)
2143             #
2144             # Returns:
2145             # Current directory
2146             #
2147             # Description:
2148             # Sets the object directory if given then returns the object directory
2149             #
2150             ################################################################################
2151             sub object_directory
2152             {
2153 0     0 0 0 my ($self, $dir) = @_;
2154            
2155 0 0       0 if (defined $dir) {
2156 0 0       0 unless (-d $dir) {
    0          
2157 0         0 carp "directory '$dir' does not exists\n";
2158             } elsif (-w $dir) {
2159 0         0 carp "you don't have permission to write into '$dir'\n";
2160             } else {
2161 0         0 $self->[PML_OBJ_DIR] = $dir;
2162             }
2163             }
2164            
2165 0         0 return $self->[PML_OBJ_DIR];
2166             } # <-- End object_directory -->
2167             ################################################################################
2168             #
2169             # B U I L T -- I N -- F U N C T I O N S
2170             # ------------------------------------
2171             #
2172             #
2173             # All built in functions take the following arguments
2174             #
2175             # 1) A PML Object
2176             # 2) A Reference to an array of argument tokens
2177             # 3) A Reference to an array of block tokens
2178             # 4) A Reference to a line (if you need to get more stuff from file)
2179             # 5) A Reference to an array of lines, in case you need more data
2180             # from the file. This argument is optional and should default
2181             # to $self->[PML_LINES];
2182             #
2183             ################################################################################
2184             #
2185             # ==== auto_parse ==== #########################################################
2186             #
2187             # Arguments:
2188             # See Above, but in addition to that :
2189             # 1) The name of the function
2190             # 2) The Token ID of the function
2191             #
2192             # Returns:
2193             # A Token
2194             #
2195             # Description:
2196             # Auto Parse is a parser for function that do not provide a parser for
2197             # themselves. It just makes a generic token, no syntax checking is done.
2198             #
2199             ################################################################################
2200             sub auto_parse
2201             {
2202 8     8 0 12 my ($self, $a, $b, $line_ref, $lines) = @_;
2203 8         13 my ($options, $name, $id, $token);
2204            
2205 8         15 $options = pop @_;
2206 8         19 $id = $options->{id};
2207 8         26 $name = $options->{name};
2208            
2209 8         26 $token = new PML::Token $id;
2210 8         47 $token->data([$name, $a, $b]);
2211            
2212 8         29 return $token;
2213             } # <-- End auto_parse -->
2214             ################################################################################
2215             #
2216             # ==== parse_if ==== ###########################################################
2217             #
2218             # Arguments:
2219             # See Above
2220             #
2221             # Returns:
2222             # A List of tokens
2223             #
2224             # Description:
2225             # Builds tokens needed for an IF statement (function)
2226             # removes elsif and else statments as needed from the file
2227             #
2228             ################################################################################
2229             sub parse_if
2230             {
2231 16     16 0 33 my ($self, $a, $b, $line_ref, $lines, $unless) = @_;
2232 16         22 my (@tokens, $regex, $token);
2233            
2234             # prepare the regex for speed
2235 16         25 $regex = G_RE_IF;
2236            
2237             # make sure we only have one condition
2238 16 50       6135 if ($#{$a} > 1) {
  16         45  
2239 0         0 $self->error_syntax
2240             ("you can only have one condition to a if function");
2241             } else {
2242 16         27 $a = $a->[0];
2243             }
2244            
2245             # check to see if this is a @if or @unless
2246 16 100       36 if ($unless) {
2247             # push a unless token
2248 3         10 $token = new PML::Token TOKEN_NOT;
2249 3         14 $token->data($a);
2250 3         6 push @tokens, $token, $b;
2251             } else {
2252             # add the if token
2253 13         26 push @tokens, $a, $b;
2254             }
2255            
2256             # look for else or elsif functions
2257 16         59 while ($self->peek($regex, $line_ref, $lines)) {
2258             # remove all dead space before the @ marker
2259 10         24 $self->magic_newline($line_ref, $lines);
2260            
2261             # remove the @ marker and either the 'else' or 'elsif'
2262             # leaving $1 set to 'else' or 'elsif'
2263 10         47 $$line_ref =~ s/$regex//o;
2264            
2265             # handle the elsif and else
2266 10 100       40 if ($1 eq 'elsif') {
    50          
2267 4         10 my $elsif_a =
2268             [$self->parse_arguments($line_ref, $lines)];
2269 4 50       6 if (@{$elsif_a} > 1) {
  4         10  
2270 0         0 $self->error_syntax
2271             ("you are only allowed to give one condition to elsif");
2272             }
2273            
2274 4         14 push @tokens,
2275             $elsif_a->[0],
2276             [$self->parse_block($line_ref, $lines)];
2277             } elsif ($1 eq 'else') {
2278 6         52 $token = new PML::Token TOKEN_EVAL;
2279 6         26 $token->data(1);
2280 6         16 push @tokens,
2281             $token,
2282             [$self->parse_block($line_ref, $lines)];
2283 6         10 last; # nothing allowed after the else
2284             }
2285             }
2286            
2287 16         101 $token = new PML::Token TOKEN_IF;
2288 16         74 $token->data(\@tokens);
2289 16         61 return $token;
2290             } # <-- End parse_if -->
2291             ################################################################################
2292             #
2293             # ==== parse_perl ==== #########################################################
2294             #
2295             # Arguments:
2296             # 1) A PML Object
2297             # 2) The charters between the { and the } after a @perl
2298             #
2299             # Returns:
2300             # 1 Token
2301             #
2302             # Description:
2303             # Just grabs the perl code and puts it into a token.
2304             # This parse function is special because the arguments and block
2305             # are not parsed for it. Thus $a and $b are undef
2306             #
2307             ################################################################################
2308             sub parse_perl
2309             {
2310 8     8 0 17 my ($self, $code) = @_;
2311 8         36 my $token = new PML::Token TOKEN_PERL;
2312            
2313 8         47 $token->data($code);
2314 8         23 return $token;
2315             } # <-- End parse_perl -->
2316             ################################################################################
2317             #
2318             # ==== parse_set ==== ##########################################################
2319             #
2320             # Arguments:
2321             # See Above
2322             # A TOKEN_SET_* token id
2323             #
2324             # Returns:
2325             # A Token
2326             #
2327             # Description:
2328             # Sets the variable to the give value(s)
2329             #
2330             ################################################################################
2331             sub parse_set
2332             {
2333 23     23 0 51 my ($self, $a, $b, $line_ref, $lines, $set) = @_;
2334 23         35 my $token;
2335            
2336             # make sure that we were given a variable name to set
2337 23 50       69 unless (defined $a->[0]) {
2338 0         0 $self->error_syntax(
2339             "you must give a variable name to set"
2340             );
2341             }
2342            
2343 23         71 $token = new PML::Token TOKEN_SET;
2344 23         136 $token->data([$set, @$a]);
2345 23         83 return $token;
2346             } # <-- End parse_set -->
2347             ################################################################################
2348             #
2349             # ==== parse_include ==== ######################################################
2350             #
2351             # Arguments:
2352             # See Above
2353             #
2354             # Returns:
2355             # Tokens
2356             #
2357             # Description:
2358             # Returns a include token after parsing a file and keeping it's tokens
2359             #
2360             ################################################################################
2361             sub parse_include
2362             {
2363 1     1 0 2 my ($self, $a, $b, $line_ref, $lines) = @_;
2364 1         5 my @args = $self->tokens_execute($a);
2365 1         2 my ($found, @tokens, $token);
2366            
2367 1 50       4 unless (@args)
2368             {
2369 0         0 $self->error("syntax error, the include function needs a list of files to include.\n");
2370             }
2371            
2372 1         3 foreach my $file (@args)
2373             {
2374 1         2 $found = 0;
2375            
2376 1 50       8 unless ($file =~ m{^(?:\.(?:\./|/)|/)}o)
2377             {
2378 1         5 foreach my $path (@inc)
2379             {
2380 1 50       28 if (-e "$path/$file")
2381             {
2382 1         3 $found = 1;
2383 1         3 $file = "$path/$file";
2384 1         3 last;
2385             }
2386             }
2387             }
2388             else
2389             {
2390 0 0       0 if (-e $file)
2391             {
2392 0         0 $found = 1;
2393 0 0       0 $file = rel2abs($file) unless $file =~ m(^/)o;
2394             }
2395             }
2396            
2397 1 50       10 unless ($found)
2398             {
2399 0         0 $self->error("can't find included file \"$file\". inc contains ". join(' ', @inc). "\n");
2400             }
2401            
2402 1         7 my $inc_parser = new PML;
2403 1         10 $inc_parser->parse($file);
2404            
2405 1 50       7 if ($DEBUG)
2406             {
2407 0         0 print STDERR "Including file $file\n";
2408 0         0 print STDERR "Before including $file the macro list is:\n";
2409 0         0 print STDERR "\t$_\n" foreach sort keys %{$self->[PML_MACROS]};
  0         0  
2410 0         0 print STDERR "Before including $file the includes list is:\n";
2411 0         0 print STDERR "\t$_\n" foreach sort keys %{$self->[PML_INCLUDES]};
  0         0  
2412             }
2413              
2414 1         13 $self->[PML_INCLUDES]{$file} = $inc_parser->[PML_TOKENS];
2415 1         13 $self->append($inc_parser);
2416            
2417 1 50       8 if ($DEBUG)
2418             {
2419 0         0 print STDERR "After including $file the macro list is:\n";
2420 0         0 print STDERR "\t$_\n" foreach sort keys %{$self->[PML_MACROS]};
  0         0  
2421 0         0 print STDERR "After including $file the includes list is:\n";
2422 0         0 print STDERR "\t$_\n" foreach sort keys %{$self->[PML_INCLUDES]};
  0         0  
2423             }
2424            
2425 1         37 push(@tokens, $file);
2426             }
2427            
2428 1         6 $token = new PML::Token TOKEN_INCLUDE;
2429 1         12 $token->data(\@tokens);
2430 1         55 return $token;
2431             } # <-- End parse_include -->
2432             ################################################################################
2433             #
2434             # ==== parse_macro ==== ########################################################
2435             #
2436             # Arguments:
2437             # See Above
2438             #
2439             # Returns:
2440             # A Token
2441             #
2442             # Description:
2443             # Sets a MACRO_TOKEN
2444             #
2445             ################################################################################
2446             sub parse_macro
2447             {
2448 5     5 0 11 my ($self, $a, $b, $line_ref, $lines) = @_;
2449            
2450 5 50       23 unless (defined $a->[0])
2451             {
2452 0         0 $self->error("syntax Error, you must give the name of the macro\n");
2453             }
2454            
2455 5         23 my $name = $self->tokens_execute(shift @$a);
2456            
2457 5 50 33     43 if (exists $self->[PML_MACROS]{$name} and $self->[PML_W])
2458             {
2459 0         0 print STDERR "Macro \"$name\" was redfined ", $self->[PML_LINE_STR], "\n";
2460             }
2461            
2462 5         32 $self->[PML_MACROS]{$name} = [$a, $b];
2463 5         15 return undef;
2464             } # <-- End parse_macro -->
2465             ################################################################################
2466             #
2467             # ==== parse_warning ==== ######################################################
2468             #
2469             # Arguments:
2470             # See Above
2471             #
2472             # Returns:
2473             # None
2474             #
2475             # Description:
2476             # Changes the warning flag
2477             #
2478             ################################################################################
2479             sub parse_warning
2480             {
2481 2     2 0 5 my ($self, $a, $b, $line_ref, $lines) = @_;
2482            
2483 2 50       8 unless (@$a == 1)
2484             {
2485 0         0 $self->error("syntax error, you must give one boolean flag to the warning function.\n");
2486             }
2487            
2488 2   50     10 $self->warning($self->tokens_execute($a->[0]) || 0);
2489 2         5 return undef;
2490             } # <-- End parse_warning -->
2491             ################################################################################
2492             #
2493             # ==== parse_foreach ==== ######################################################
2494             #
2495             # Arguments:
2496             # See Above
2497             #
2498             # Returns:
2499             # A FOREACH_TOKEN
2500             #
2501             # Description:
2502             # Parses the foreach pml function
2503             #
2504             ################################################################################
2505             sub parse_foreach
2506             {
2507 2     2 0 8 my ($self, $a, $b, $line_ref, $lines) = @_;
2508 2         3 my $token;
2509            
2510 2 50       9 unless (@$a)
2511             {
2512 0         0 $self->error("syntax error, you need to give some arguments to the foreach function.\n");
2513             }
2514            
2515 2         16 $token = new PML::Token TOKEN_FOREACH;
2516 2         13 $token->data([$a, $b]);
2517 2         6 return $token;
2518             } # <-- End parse_foreach -->
2519             ################################################################################
2520             #
2521             # ==== parse_need ==== #########################################################
2522             #
2523             # Arguments:
2524             # See Above
2525             #
2526             # Returns:
2527             # None
2528             #
2529             # Description:
2530             # Loads the modules that need to be loaded, if the are not alread loaded
2531             #
2532             ################################################################################
2533             sub parse_need
2534             {
2535 1     1 0 3 my ($self, $a, $b, $line_ref, $lines) = @_;
2536 1         3 my @modules = $self->tokens_execute($a);
2537            
2538 1         7 foreach (@modules)
2539             {
2540 1         2 push @{$self->[PML_NEED_LIST]}, $_;
  1         3  
2541 1         123 eval "require PML::" . $_;
2542            
2543 1 50       4 if ($@)
2544             {
2545 0         0 $self->error("error loading module \"$_\", make sure you entered it correctly");
2546             }
2547            
2548 1         63 eval "PML::" . $_ . "->init(\$self)";
2549            
2550 1 0 33     7 if ($DEBUG and $@)
2551             {
2552 0         0 print STDERR "error from PML::$_->init: $@\n";
2553             }
2554             }
2555            
2556 1         4 return undef;
2557             } # <-- End parse_need -->
2558             ################################################################################
2559             #
2560             # ==== parse_while ==== ########################################################
2561             #
2562             # Arguments:
2563             # See Above
2564             #
2565             # Returns:
2566             # Tokens
2567             #
2568             # Description:
2569             # The while and until functions
2570             #
2571             ################################################################################
2572             sub parse_while
2573             {
2574 3     3 0 6 my ($self, $a, $b, $line_ref, $lines, $until) = @_;
2575 3         3 my (@tokens, $token);
2576            
2577             # check to make sure there no more then one condition
2578 3 50       5 if (@{$a} > 1) {
  3         7  
2579 0         0 error_syntax("you can only supply one condition to the while/until function");
2580             } else {
2581 3         11 $a = $a->[0];
2582             }
2583            
2584             # create the token, negate the condition if this is until
2585 3 100       8 if ($until) {
2586 1         3 $token = new PML::Token TOKEN_NOT;
2587 1         5 $token->data($a);
2588 1         2 push @tokens, $token, $b;
2589             } else {
2590 2         14 push @tokens, $a, $b;
2591             }
2592            
2593 3         23 $token = new PML::Token TOKEN_WHILE;
2594 3         12 $token->data(\@tokens);
2595 3         11 return $token;
2596             } # <-- End parse_while -->
2597             ################################################################################
2598             #
2599             # ==== parse_skip ==== #########################################################
2600             #
2601             # 1) A PML Object
2602             # 2) The charters between the { and the } after a @perl
2603             #
2604             # Returns:
2605             # 1 Token
2606             #
2607             # Description:
2608             # Keeps PML from parsing any text in the skip block
2609             #
2610             ################################################################################
2611             sub parse_skip
2612             {
2613 1     1 0 2 my ($self, $skip) = @_;
2614 1         5 my $token = new PML::Token TOKEN_SKIP;
2615            
2616 1         7 $token->data($skip);
2617 1         3 return $token;
2618             } # <-- End parse_skip -->
2619             ################################################################################
2620             #
2621             # ==== parse_wrap ==== #########################################################
2622             #
2623             # Arguments:
2624             # See Above
2625             #
2626             # Returns:
2627             # A wrap token
2628             #
2629             # Description:
2630             # Wraps text to a certain number of chars per line
2631             #
2632             ################################################################################
2633             sub parse_wrap
2634             {
2635 0     0 0 0 my ($self, $a, $b, $line_ref, $lines) = @_;
2636 0         0 my $token = new PML::Token TOKEN_WRAP;
2637            
2638 0 0       0 unless (@$a <= 3) {
2639 0         0 $self->error_syntax (
2640             "wrap function only takes 3 arguments"
2641             );
2642             }
2643            
2644 0   0     0 $token->data([$a->[0]||80, $a->[1]||'', $a->[2]||'', $b]);
      0        
      0        
2645 0         0 return $token;
2646             } # <-- End parse_wrap -->
2647             ################################################################################
2648             #
2649             # ==== parse_rib ==== ##########################################################
2650             #
2651             # Arguments:
2652             # See Above
2653             #
2654             # Returns:
2655             # A rib token
2656             #
2657             # Description:
2658             # Parses the rib function
2659             #
2660             ################################################################################
2661             sub parse_rib
2662             {
2663 4     4 0 9 my ($self, $a, $b, $line_ref, $lines) = @_;
2664 4         14 my $token = new PML::Token TOKEN_RIB;
2665            
2666 4 50       13 unless (@$a == 1) {
2667 0         0 $self->error_syntax (
2668             "the rib function needs one argument"
2669             );
2670             }
2671            
2672 4         22 $token->data([$a->[0], $b]);
2673 4         12 return $token;
2674             } # <-- End parse_rib -->
2675             ################################################################################
2676             #
2677             # ==== parse_loop_int ==== #####################################################
2678             #
2679             # Arguments:
2680             # See Above
2681             #
2682             # Returns:
2683             # A Token
2684             #
2685             # Description:
2686             # Creates a token for @next, @last and @redo
2687             #
2688             ################################################################################
2689             sub parse_loop_int
2690             {
2691 1     1 0 6 my ($self, $a, $b, $line_ref, $lines, $name) = @_;
2692 1         6 my $token = new PML::Token TOKEN_LOOP_INT;
2693            
2694             # make sure that we are only getting one label
2695 1 50       4 if (@$a > 1) {
2696 0         0 $self->error_syntax("you can only give one label to $name");
2697             }
2698            
2699             # set the data to be the name (next,redo or last) and the label ($a)
2700 1   50     13 $token->data([$name, $a->[0] || '']);
2701            
2702 1         3 return $token;
2703             } # <-- End parse_loop_int -->
2704             ################################################################################
2705             #
2706             # B U I L T -- I N -- T O K E N S
2707             # ------------------------------------
2708             #
2709             #
2710             # All built in tokens take the following arguments
2711             #
2712             # 1) A PML Object
2713             # 2) A PML::Token Object
2714             #
2715             ################################################################################
2716             #
2717             # ==== token_eval ==== #########################################################
2718             #
2719             # Arguments:
2720             # See Above
2721             #
2722             # Returns:
2723             # A String
2724             #
2725             # Description:
2726             # Replaces all variables in the string and returns it
2727             #
2728             ################################################################################
2729             sub token_eval
2730             {
2731 223     223 0 316 my ($self, $token) = @_;
2732 223         974 my $string = $token->data;
2733 223         409 my $result = '';
2734            
2735             # check to make sure that we have a string
2736 223 50 33     1154 return undef unless defined $string and length($string);
2737            
2738             # replace variable names with the value
2739 223         1567 while ($string =~ s/^$RE_VAR_TEST//o) {
2740 40 100       139 $result .= $1 if $1;
2741 40         136 $result .= $self->replace_variable(\$string);
2742             }
2743            
2744             # if we found none then set the result to the string
2745 223 100       569 $result .= $string if length $string;
2746            
2747             # replace backslashed charaters with their actual ASCII codes
2748 223         276 $result =~ s/(?
  0         0  
2749            
2750             # Remove some tabs if asked
2751 223         255 $result =~ s/[\t]+\\T//og;
2752            
2753             # remove any remaining backslashes unless we are processing
2754             # the arguments of a function call. If that is the case
2755             # we will surly get another change to remove the backslash
2756             # when charater is used in the block or body.
2757 223 100       1141 $result =~ s/(?file_loc == FILE_LOC_ARG;
2758            
2759             # and return the result
2760 223         882 return $result;
2761             } # <-- End token_eval -->
2762             ################################################################################
2763             #
2764             # ==== token_if ==== ###########################################################
2765             #
2766             # Arguments:
2767             # See Above
2768             #
2769             # Returns:
2770             # Whatever is in the if block or elsif block or else block
2771             #
2772             # Description:
2773             # Check to see if the args are true then executes the correct tokens
2774             #
2775             ################################################################################
2776             sub token_if
2777             {
2778 16     16 0 23 my ($self, $token) = @_;
2779 16         18 my (@tokens) = @{$token->data};
  16         60  
2780 16         26 my ($a, $b, $rv, $tmp);
2781            
2782             #
2783             # now loop trying to execute a block of PML
2784             #
2785 16         22 while(1)
2786             {
2787             #
2788             # check to make sure there are at least two tokens
2789             #
2790 21 50       47 last unless @tokens >= 2;
2791            
2792             #
2793             # get the argument and block tokens from the tokens array
2794             #
2795 21         47 ($a, $b, @tokens) = @tokens;
2796            
2797             #
2798             # check to see if this token return a true value
2799             #
2800 21 100       81 if ($self->tokens_execute($a))
2801             {
2802             # if we get here then we get to execute
2803             # the block and return what it returns
2804 16   50     40 return $self->tokens_execute($b) || undef;
2805            
2806             #foreach my $token (@$b)
2807             #{
2808             # $tmp = $self->token_execute($token);
2809             # $rv .= $tmp if defined $tmp;
2810             #}
2811            
2812             #return $rv;
2813             }
2814             }
2815            
2816             #
2817             # if we get this far there were no succesfull tokens
2818             #
2819 0         0 return undef;
2820             } # <-- End token_if -->
2821             ################################################################################
2822             #
2823             # ==== token_not ==== ##########################################################
2824             #
2825             # Arguments:
2826             # See Above
2827             #
2828             # Returns:
2829             # The inverse of the inner token
2830             #
2831             # Description:
2832             # This token comes with one other token to execute
2833             # The unless token returns the inverse of executing that token
2834             #
2835             ################################################################################
2836             sub token_not
2837             {
2838 11     11 0 20 my ($self, $token) = @_;
2839 11         52 return not scalar $self->tokens_execute($token->data);
2840             } # <-- End token_not -->
2841             ################################################################################
2842             #
2843             # ==== token_perl ==== #########################################################
2844             #
2845             # Arguments:
2846             # See Above
2847             #
2848             # Returns:
2849             # What ever is the last value in the perl code
2850             #
2851             # Description:
2852             # Evals the perl code and returns it
2853             #
2854             ################################################################################
2855             sub token_perl
2856             {
2857 20     20 0 31 my ($self, $token) = @_;
2858 20         25 my %v = %{$self->[PML_V]};
  20         127  
2859 20         88 my $code = $token->data;
2860 20         34 my @rv;
2861            
2862 20         1680 @rv = eval "$code";
2863            
2864 20 50 33     128 if ($@ and $self->warning) {
2865 0         0 print STDERR "An error occured in your perl code: $@\n";
2866             }
2867            
2868 20         46 %{$self->[PML_V]} = %v;
  20         87  
2869            
2870 20         276 local $^W=0; # bug in perl? next line causes "Use of uninitialized value at PML.pm"
2871 20 100       97 if ($token->context == CONTEXT_LIST) {
2872 3         16 return @rv;
2873             } else {
2874 17         101 return join '', @rv;
2875             }
2876             } # <-- End token_perl -->
2877             ################################################################################
2878             #
2879             # ==== token_set ==== ##########################################################
2880             #
2881             # Arguments:
2882             # See Above
2883             #
2884             # Returns:
2885             # None
2886             #
2887             # Description:
2888             # Sets the variable to the value(s) in the token(s)
2889             #
2890             ################################################################################
2891             sub token_set
2892             {
2893 25     25 0 43 my ($self, $token) = @_;
2894 25         31 my ($sub_token, $v, @values) = @{$token->data};
  25         105  
2895 25         42 my ($array, $hash, $index, $ref, $i);
2896            
2897 25         115 $v = $self->tokens_execute($v);
2898            
2899             # reject the variable name if it does not match
2900             # the standard variable naming procedures
2901 25 50 33     752 if ($v !~ /^$RE_VAR/o or $v =~ /[\$\{\}]/o or $v =~ /^(\.|ARGV)$/o) {
      33        
2902 0         0 print STDERR "The variable name '$v' contains illeagal charaters\n";
2903 0         0 croak("bad variable name");
2904             }
2905            
2906             # execute the tokens and get the real data
2907 25         232 @values = $self->tokens_execute(@values);
2908            
2909 25 50       92 if ($v =~ /^(.*?)\[(\d+)\]$/o) {
    50          
2910 0         0 $array = $1; $index = $2;
  0         0  
2911            
2912 0 0 0     0 if (
2913             defined $self->[PML_V]{$array} and
2914             ref($self->[PML_V]{$array}) ne 'ARRAY'
2915             ) {
2916 0         0 print STDERR "pml does not support complexe data structures, but you tried to set one\n";
2917 0         0 return undef;
2918             }
2919            
2920 0         0 $ref = \$self->[PML_V]{$array}[$index];
2921             } elsif ($v =~ /^([^\.]+)\.([^\.]+)$/o) {
2922 0         0 $hash = $1; $index = $2;
  0         0  
2923              
2924 0 0 0     0 if (
2925             defined $self->[PML_V]{$hash} and
2926             ref($self->[PML_V]{$hash}) ne 'HASH'
2927             ) {
2928 0         0 print STDERR "pml does not support complexe data structures, but you tried to set one\n";
2929 0         0 return undef;
2930             }
2931            
2932 0         0 $ref = \$self->[PML_V]{$hash}{$index};
2933             } else {
2934 25 100       152 $self->[PML_V]{$v} = '' unless exists $self->[PML_V]{$v};
2935 25         64 $ref = \$self->[PML_V]{$v};
2936             }
2937            
2938 25 100       75 if ($sub_token == TOKEN_SET_SET) {
    100          
    100          
    50          
    0          
2939 20 100       66 if (@values > 1) {
2940 3 50 33     36 if ($array or $hash) {
2941 0         0 print STDERR "you can only assign one value to a array index or hash key\n";
2942 0         0 $$ref = $values[-1];
2943             } else {
2944 3         12 $self->[PML_V]{$v} = [@values];
2945             }
2946             } else {
2947 17         33 $$ref = $values[0];
2948             }
2949             } elsif ($sub_token == TOKEN_SET_IF) {
2950 3 100 66     25 return undef if defined $ref and $$ref;
2951 1         4 $token = new PML::Token TOKEN_SET;
2952 1         12 $token->data([TOKEN_SET_SET, $v, @values]);
2953 1         13 $self->token_set($token);
2954             } elsif ($sub_token == TOKEN_SET_APPEND) {
2955 1 50 33     25 if (not $array and not $hash and ref $self->[PML_V]{$v} eq 'ARRAY') {
      33        
2956 0         0 push(@{$self->[PML_V]{$v}}, @values);
  0         0  
2957             } else {
2958 1         4 foreach $i (@values) {
2959 1         5 $i =~ s/^\s+//o;
2960 1 50       4 defined $$ref and $$ref =~ s/\s+$//o;
2961 1         4 $$ref .= " $i";
2962             }
2963             }
2964             } elsif ($sub_token == TOKEN_SET_PREPEND) {
2965 1 50 33     12 if (not $array and not $hash and ref $self->[PML_V]{$v} eq 'ARRAY') {
      33        
2966 0         0 unshift(@{$self->[PML_V]{$v}}, @values);
  0         0  
2967             } else {
2968 1         2 foreach $i (@values) {
2969 1         3 $i =~ s/\s+$//o;
2970 1 50       6 defined $$ref and $$ref =~ s/^\s+//o;
2971 1         6 $$ref = "$i $$ref";
2972             }
2973             }
2974             } elsif ($sub_token == TOKEN_SET_CONCAT) {
2975 0 0 0     0 if (not $array and not $hash and ref($self->[PML_V]{$v}) eq 'ARRAY') {
      0        
2976 0         0 push(@{$self->[PML_V]{$v}}, @values);
  0         0  
2977             } else {
2978 0         0 foreach $i (@values) {
2979 0         0 $i =~ s/^\s+//o;
2980 0 0       0 defined $$ref and $$ref =~ s/\s+$//o;
2981 0         0 $$ref .= "$i";
2982             }
2983             }
2984             } else {
2985 0         0 print STDERR "WOAH! Unknown Set Sub Token \"$sub_token\", you found a bug in PML.\n";
2986 0         0 croak "PML Internal Error";
2987             }
2988            
2989 23         89 return undef;
2990             } # <-- End token_set -->
2991             ################################################################################
2992             #
2993             # ==== token_include ==== ######################################################
2994             #
2995             # Arguments:
2996             # See Above
2997             #
2998             # Returns:
2999             # None
3000             #
3001             # Description:
3002             # runs the tokens for the included file
3003             #
3004             ################################################################################
3005             sub token_include
3006             {
3007 1     1 0 2 my ($self, $token) = @_;
3008 1         3 my @files = @{$token->data};
  1         4  
3009 1         2 my $file;
3010 1         5 my $rv = '';
3011            
3012 1         3 local $^W=0; #FIXME temp fix for Use of uninitialized value
3013            
3014 1         5 foreach $file (@files)
3015             {
3016 1 50       3 next unless defined $file;
3017 1         2 $rv .= $self->tokens_execute($_) foreach @{$self->[PML_INCLUDES]{$file}};
  1         12  
3018 1 50       6 print STDERR "Executed included file $file\n" if $DEBUG;
3019             }
3020            
3021 1 50       16 print STDERR "The included text to be returned is:\n$rv\n" if $DEBUG;
3022 1   50     6 return $rv || undef;
3023             } # <-- End token_include -->
3024             ################################################################################
3025             #
3026             # ==== token_macro ==== ########################################################
3027             #
3028             # Arguments:
3029             # See Above
3030             #
3031             # Returns:
3032             # What ever the macro returns
3033             #
3034             # Description:
3035             # Runs the tokens for the macro
3036             #
3037             ################################################################################
3038             sub token_macro
3039             {
3040 5     5 0 13 my ($self, $token) = @_;
3041 5         9 my ($name, @args) = @{$token->data};
  5         26  
3042 5         47 my ($argument, $save_argv, $result, %save);
3043            
3044             # keep from going to deep in recursion
3045 5         27 $self->_in;
3046            
3047             # first make sure that the macro exists
3048 5 50       22 unless (exists $self->[PML_MACROS]{$name}) {
3049 0         0 print STDERR "Macro \"$name\" was not defined, possible bug in PML\n";
3050 0         0 croak("PML Internal Error");
3051             }
3052            
3053             # process the list of argument names from the macro definition
3054 5         69 my @arg_names = $self->tokens_execute (
3055             $self->[PML_MACROS]{$name}->[0]
3056             );
3057            
3058             # look for one name called _ALL_ and remove it
3059             # this is for backwards compatability before ARGV existed
3060 5 50 66     30 if (defined $arg_names[0] and $arg_names[0] eq '_ALL_') {
3061 0         0 shift @arg_names;
3062             }
3063            
3064             # save the values of the arguments so
3065             # we can restore them at the end of the
3066             # macro call
3067 5         22 foreach $argument (@arg_names) {
3068 2         9 $save{$argument} = $self->[PML_V]{$argument};
3069             }
3070            
3071             # make sure that the macro was called with at least
3072             # the number of arguments as there are names
3073 5 50 33     19 if (not (@args >= @arg_names) and $self->[PML_W]) {
3074 0         0 print STDERR "Macro '$name' called with wrong number of arguments\n";
3075             }
3076              
3077             # now, place the arguments into the correct variables
3078 5         12 foreach $argument (@arg_names) {
3079 2         33 $self->[PML_V]{$argument} = $self->tokens_execute(shift @args);
3080             }
3081            
3082             # save the current value of ARGV incase this is a macro call
3083             # inside another macro call.
3084 5         25 $save_argv = $self->[PML_V]{'ARGV'};
3085            
3086             # all remaing arguments are put into ARGV and _ALL_
3087             # the _ALL_ part is for backward compatiblity and will be
3088             # removed someday
3089 5 100       15 if (@args) {
3090 1         4 $self->[PML_V]{'ARGV'} = [$self->tokens_execute(@args)];
3091 1         4 $self->[PML_V]{'_ALL_'} = $self->[PML_V]{'ARGV'};
3092             }
3093            
3094             # don't complain when we give join undef
3095 5         26 local $^W=0;
3096            
3097             # execute the block of the macro
3098 5         26 $result = join '', $self->tokens_execute($self->[PML_MACROS]{$name}[1]);
3099              
3100             # restore the ARGV variable
3101 5         18 $self->[PML_V]{'ARGV'} = $save_argv;
3102            
3103             # restore the variables in the arguments
3104 5         15 foreach $argument (keys %save) {
3105 2         6 $self->[PML_V]{$argument} = $save{$argument};
3106             }
3107            
3108             # restore the rescurse count
3109 5         17 $self->_out;
3110            
3111             # put the result into the output stream
3112 5         27 return $result;
3113             } # <-- End token_macro -->
3114             ################################################################################
3115             #
3116             # ==== token_variable ==== #####################################################
3117             #
3118             # Arguments:
3119             # See Above
3120             #
3121             # Returns:
3122             # 1 or more values or undef
3123             #
3124             # Description:
3125             # tries to expand variable
3126             #
3127             ################################################################################
3128             sub token_variable
3129             {
3130 23     23 0 31 my ($self, $token) = @_;
3131 23         81 my $v = $token->data;
3132 23         38 my @result;
3133            
3134 23         274 while ($v =~ s/^$RE_VAR_TEST//o) {
3135 23 50       73 push @result, $1 if $1;
3136 23         80 push @result, $self->replace_variable(\$v);
3137             }
3138            
3139             # set result to v if there is something in v
3140 23 50       47 push @result, $v if length $v;
3141            
3142 23 50       83 if ($token->context == CONTEXT_LIST) {
3143 23         76 return @result;
3144             } else {
3145 0         0 return join '', @result;
3146             }
3147             } # <-- End token_variable -->
3148             ################################################################################
3149             #
3150             # ==== token_foreach ==== ######################################################
3151             #
3152             # Arguments:
3153             # See Above
3154             #
3155             # Returns:
3156             # The code from the block
3157             #
3158             # Description:
3159             # Executes the block tokens one time for each of the arguments,
3160             # setting the variable "." to the name of the argument
3161             #
3162             ################################################################################
3163             sub token_foreach
3164             {
3165 2     2 0 4 my ($self, $token) = @_;
3166 2         4 my ($a, $b) = @{$token->data};
  2         9  
3167 2         10 my @args = $self->tokens_execute($a);
3168 2         12 my ($savedot, $savelabel, $havelabel, $rv);
3169            
3170             # protect from deep recursion
3171 2         7 $self->_in;
3172            
3173             # save off the old value of '.'
3174 2         6 $savedot = $self->[PML_V]{'.'};
3175            
3176             # if we have a label, use it along with '.'
3177 2 100       20 if ($havelabel = $token->label) {
3178 1         2 $savelabel = $self->[PML_V]{$havelabel};
3179             }
3180            
3181             # add to the count of loops
3182 2         7 $self->[PML_LOOP_COUNTERS]{'foreach'}++;
3183            
3184 2         12 foreach my $arg (@args) {
3185 6         22 $self->[PML_V]{'.'} = $arg;
3186 6 100       18 $self->[PML_V]{$havelabel} = $arg if $havelabel;
3187 6         16 $rv .= join('', $self->tokens_execute($b));
3188             # see if that last call died
3189 6 50       23 if ($self->[PML_DIE_MESSAGE]) {
3190 0 0       0 if ($self->[PML_DIE_MESSAGE] =~ /$RE_LOOP_INT/) {
  0         0  
3191             # the die was a next, last or redo
3192 0 0 0     0 if (not $2 or $2 eq $token->label) {
3193 0         0 $self->[PML_DIE_MESSAGE]='';
3194 0 0       0 if ($1 eq 'next') {next}
  0 0       0  
  0 0       0  
3195 0         0 elsif ($1 eq 'redo') {redo}
3196             elsif ($1 eq 'last') {last}
3197             } else {
3198 0         0 die $self->[PML_DIE_MESSAGE];
3199             }
3200             } else {die $self->[PML_DIE_MESSAGE]}
3201             }
3202             }
3203            
3204             # we are out of the loop
3205 2         7 $self->[PML_LOOP_COUNTERS]{'foreach'}--;
3206            
3207             # restore the variable stored in havelabel
3208 2 100       11 $self->[PML_V]{$havelabel} = $savelabel if $havelabel;
3209            
3210             # restore the value of the '.'
3211 2         14 $self->[PML_V]{'.'} = $savedot;
3212            
3213             # stop recursion protection
3214 2         22 $self->_out;
3215            
3216 2   50     14 return $rv || undef;
3217             } # <-- End token_foreach -->
3218             ################################################################################
3219             #
3220             # ==== token_while ==== ########################################################
3221             #
3222             # Arguments:
3223             # See Above
3224             #
3225             # Returns:
3226             # A String
3227             #
3228             # Description:
3229             # Repeates the block while the condition is true
3230             #
3231             ################################################################################
3232             sub token_while
3233             {
3234 3     3 0 9 my ($self, $token) = @_;
3235 3         6 my ($condition, $block) = @{$token->data};
  3         11  
3236 3         40 my $rv = '';
3237            
3238             # say that we are in a loop
3239 3         8 $self->[PML_LOOP_COUNTERS]{'while'}++;
3240            
3241 3         11 local $^W=0;
3242 3         10 while (scalar $self->tokens_execute($condition)) {
3243 15         32 $rv .= join '', $self->tokens_execute($block);
3244 15 100       55 if ($self->[PML_DIE_MESSAGE]) {
3245 1 50       16 if ($self->[PML_DIE_MESSAGE] =~ /$RE_LOOP_INT/) {
  0         0  
3246             # the die was a next, last or redo
3247 1 50 33     24 if (not $2 or $2 eq $token->label) {
3248 1         14 $self->[PML_DIE_MESSAGE]='';
3249 1 50       11 if ($1 eq 'next') {next}
  0 50       0  
  0 50       0  
3250 1         9 elsif ($1 eq 'redo') {redo}
3251             elsif ($1 eq 'last') {last}
3252             } else {
3253 0         0 die $self->[PML_DIE_MESSAGE];
3254             }
3255             } else {die $self->[PML_DIE_MESSAGE]}
3256             }
3257              
3258             }
3259            
3260             # done with the loop
3261 3         9 $self->[PML_LOOP_COUNTERS]{'while'}--;
3262            
3263 3   50     23 return $rv || undef;
3264             } # <-- End token_while -->
3265             ################################################################################
3266             #
3267             # ==== token_skip ==== #########################################################
3268             #
3269             # Arguments:
3270             # See Above
3271             #
3272             # Returns:
3273             # The skip text
3274             #
3275             # Description:
3276             # just returns the text in the skip block
3277             #
3278             ################################################################################
3279             sub token_skip
3280             {
3281 1   50 1 0 7 return $_[1]->data || undef;
3282             } # <-- End token_skip -->
3283             ################################################################################
3284             #
3285             # ==== token_wrap ==== #########################################################
3286             #
3287             # Arguments:
3288             # See Above
3289             #
3290             # Returns:
3291             # Text wrapped
3292             #
3293             # Description:
3294             # Wraps the text
3295             #
3296             ################################################################################
3297             sub token_wrap
3298             {
3299 0     0 0 0 my ($self, $token) = @_;
3300 0         0 my ($c, $f, $s, $b) = @{$token->data};
  0         0  
3301 0         0 my ($text, $result);
3302            
3303 0         0 $c = $self->tokens_execute($c);
3304 0         0 $f = $self->tokens_execute($f);
3305 0         0 $s = $self->tokens_execute($s);
3306            
3307 0         0 $Text::Wrap::columns = $c;
3308            
3309 0         0 $text = join '', $self->tokens_execute($b);
3310 0         0 $text =~ s/(?
3311            
3312 0         0 while ($text =~ /([^\n]+)?(\n+)?/go) {
3313 0 0       0 if ($1) {
3314 0         0 $result .= wrap($f, $s, $1);
3315             }
3316            
3317 0 0       0 if ($2) {
3318 0         0 $result .= $2;
3319             }
3320             }
3321            
3322 0         0 return $result;
3323             } # <-- End token_wrap -->
3324             ################################################################################
3325             #
3326             # ==== token_rib ==== ##########################################################
3327             #
3328             # Arguments:
3329             # See Above
3330             #
3331             # Returns:
3332             # The text in the block or the first argument
3333             #
3334             # Description:
3335             # replace if blank token executer
3336             #
3337             ################################################################################
3338             sub token_rib
3339             {
3340 4     4 0 10 local ($^W)=0;
3341 4         6 my ($self, $token) = @_;
3342 4         5 my ($a, $b) = @{$token->data};
  4         17  
3343 4         17 my $block = join '', $self->tokens_execute($b);
3344            
3345 4   50     26 return $block || $self->tokens_execute($a) || undef;
3346             } # <-- End token_rib -->
3347             ################################################################################
3348             #
3349             # ==== token_magic_macro ==== ##################################################
3350             #
3351             # Arguments:
3352             # 1) A PML Object
3353             # 2) A PML::Token Object
3354             #
3355             # Returns:
3356             # Whatever the macro call returns
3357             #
3358             # Description:
3359             # Replaces all variables in the macro name untill there are none
3360             # left, the calls that macro if it exists
3361             #
3362             ################################################################################
3363             sub token_magic_macro
3364             {
3365 1     1 0 3 my ($self, $token) = @_;
3366 1         2 my ($eval_token, $name);
3367 1         3 my ($func, $a) = @{$token->data};
  1         4  
3368            
3369             # first build a token to eval the macro name
3370 1         8 $eval_token = new PML::Token TOKEN_EVAL;
3371 1         6 $eval_token->data($func);
3372            
3373             # now get the name of the macro
3374 1         4 $name = $self->tokens_execute($eval_token);
3375            
3376             # make sure there is a macro called $name
3377 1 50       6 unless (exists $self->[PML_MACROS]{$name}) {
3378 0 0       0 if ($self->warning) {
3379 0         0 print STDERR "you called a macro with a variable in it's name, the name resolved to '$name' but there is no macro by that name\n";
3380             }
3381 0         0 return '';
3382             }
3383            
3384             # if we get here we can let token_macro do the work for us
3385 1         6 $token->id(TOKEN_MACRO);
3386 1         7 $token->data([$name, $a]);
3387            
3388 1         3 return scalar $self->tokens_execute($token);
3389             } # <-- End token_magic_macro -->
3390             ################################################################################
3391             #
3392             # ==== token_loop_int ==== #####################################################
3393             #
3394             # Arguments:
3395             # 1) PML Object
3396             # 2) PML::Token
3397             #
3398             # Returns:
3399             # Nothing
3400             #
3401             # Description:
3402             # Dies if we are in a loop
3403             #
3404             ################################################################################
3405             sub token_loop_int
3406             {
3407 1     1 0 3 my ($self, $token) = @_;
3408 1         3 my ($name, $label) = @{$token->data};
  1         9  
3409            
3410             # if we have a label then resolve it
3411 1 50       5 $label = $self->tokens_execute($label) if $label;
3412 1   50     14 $label ||= '';
3413            
3414             # check to see if we are in a loop
3415 1 50       2 if (grep {$_>=1} values %{$self->[PML_LOOP_COUNTERS]}) {
  3         12  
  1         7  
3416 1         17 die "$name:$label";
3417             } else { # we are not in a loop so we go all the way back up to execute
3418 0 0       0 if ($self->warning) {
3419 0         0 print STDERR "using \@$name() outside of a loop can be messy\n";
3420             };
3421 0         0 die "$name:tc";
3422             }
3423            
3424 0         0 return undef;
3425             } # <-- End token_loop_int -->
3426             ################################################################################
3427             #
3428             # ==== AUTOLOAD ==== ###########################################################
3429             #
3430             # Arguments:
3431             # 1) Args going to orig method call
3432             #
3433             # Returns:
3434             # What ever the orig method call would return
3435             #
3436             # Description:
3437             # Helps map method calls to subs
3438             #
3439             ################################################################################
3440             AUTOLOAD
3441             {
3442 2254     2254   10628 my ($class, $method) = ($AUTOLOAD =~ /^(.*)::(.*)$/);
3443            
3444 2254 50       4833 if ($class eq 'PML::Token') {
3445 2254 100 66     7490 if ($method eq 'id') {
    100          
    100          
    100          
    50          
3446 1033         1811 return _token_id(@_);
3447             } elsif ($method eq 'context') {
3448 191         471 return _token_context(@_);
3449             } elsif ($method eq 'file_loc' or $method eq 'fli') {
3450 371         846 return _token_file_loc(@_);
3451             } elsif ($method eq 'data') {
3452 656         1427 return _token_data(@_);
3453             } elsif ($method eq 'label') {
3454 3         11 return _token_label(@_);
3455             } else {
3456 0           carp "unknown PML::Token method '$method'";
3457 0           return undef;
3458             }
3459             } else {
3460 0           carp "unknown PML method '$method'";
3461 0           return undef;
3462             }
3463             } # <-- End AUTOLOAD -->
3464             ################################################################################
3465             #
3466             # ==== DESTROY ==== ############################################################
3467             #
3468             # Arguments:
3469             # 1) Object to destroy
3470             #
3471             # Returns:
3472             # None
3473             #
3474             # Description:
3475             # Cleans up after object
3476             #
3477             ################################################################################
3478             DESTROY
3479 0     0     {
3480              
3481             } # <-- End DESTROY -->
3482             ################################################################################
3483             # END-OF-MODULE #
3484             ################################################################################
3485             1;