Subversion Repositories gelsvn

Rev

Rev 107 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 107 Rev 198
1
package TemplateParser;
1
package TemplateParser;
2
 
2
 
3
# ************************************************************
3
# ************************************************************
4
# Description   : Parses the template and fills in missing values
4
# Description   : Parses the template and fills in missing values
5
# Author        : Chad Elliott
5
# Author        : Chad Elliott
6
# Create Date   : 5/17/2002
6
# Create Date   : 5/17/2002
7
# ************************************************************
7
# ************************************************************
8
 
8
 
9
# ************************************************************
9
# ************************************************************
10
# Pragmas
10
# Pragmas
11
# ************************************************************
11
# ************************************************************
12
 
12
 
13
use strict;
13
use strict;
14
 
14
 
15
use Parser;
15
use Parser;
16
use WinVersionTranslator;
16
use WinVersionTranslator;
17
 
17
 
18
use vars qw(@ISA);
18
use vars qw(@ISA);
19
@ISA = qw(Parser);
19
@ISA = qw(Parser);
20
 
20
 
21
# ************************************************************
21
# ************************************************************
22
# Data Section
22
# Data Section
23
# ************************************************************
23
# ************************************************************
24
 
24
 
25
# Valid keywords for use in template files.  Each has a handle_
25
# Valid keywords for use in template files.  Each has a handle_
26
# method available, but some have other methods too.
26
# method available, but some have other methods too.
27
# Bit  Meaning
27
# Bit  Meaning
28
# 0 means there is a get_ method available (used by if)
28
# 0 means there is a get_ method available (used by if)
29
# 1 means there is a perform_ method available (used by foreach)
29
# 1 means there is a perform_ method available (used by foreach)
30
# 2 means there is a doif_ method available (used by if)
30
# 2 means there is a doif_ method available (used by if)
31
my(%keywords) = ('if'              => 0,
31
my(%keywords) = ('if'              => 0,
32
                 'else'            => 0,
32
                 'else'            => 0,
33
                 'endif'           => 0,
33
                 'endif'           => 0,
34
                 'noextension'     => 2,
34
                 'noextension'     => 2,
35
                 'dirname'         => 5,
35
                 'dirname'         => 5,
36
                 'basename'        => 0,
36
                 'basename'        => 0,
37
                 'basenoextension' => 0,
37
                 'basenoextension' => 0,
38
                 'foreach'         => 0,
38
                 'foreach'         => 0,
39
                 'forfirst'        => 0,
39
                 'forfirst'        => 0,
40
                 'fornotfirst'     => 0,
40
                 'fornotfirst'     => 0,
41
                 'fornotlast'      => 0,
41
                 'fornotlast'      => 0,
42
                 'forlast'         => 0,
42
                 'forlast'         => 0,
43
                 'endfor'          => 0,
43
                 'endfor'          => 0,
44
                 'eval'            => 0,
44
                 'eval'            => 0,
45
                 'comment'         => 0,
45
                 'comment'         => 0,
46
                 'marker'          => 0,
46
                 'marker'          => 0,
47
                 'uc'              => 0,
47
                 'uc'              => 0,
48
                 'lc'              => 0,
48
                 'lc'              => 0,
49
                 'ucw'             => 0,
49
                 'ucw'             => 0,
50
                 'normalize'       => 2,
50
                 'normalize'       => 2,
51
                 'flag_overrides'  => 1,
51
                 'flag_overrides'  => 1,
52
                 'reverse'         => 2,
52
                 'reverse'         => 2,
53
                 'sort'            => 2,
53
                 'sort'            => 2,
54
                 'uniq'            => 3,
54
                 'uniq'            => 3,
55
                 'multiple'        => 5,
55
                 'multiple'        => 5,
56
                 'starts_with'     => 5,
56
                 'starts_with'     => 5,
57
                 'ends_with'       => 5,
57
                 'ends_with'       => 5,
58
                 'contains'        => 5,
58
                 'contains'        => 5,
59
                 'compares'        => 5,
59
                 'compares'        => 5,
60
                 'duplicate_index' => 5,
60
                 'duplicate_index' => 5,
61
                );
61
                );
62
 
62
 
63
my(%target_type_vars) = ('type_is_static'   => 1,
63
my(%target_type_vars) = ('type_is_static'   => 1,
64
                         'need_staticflags' => 1,
64
                         'need_staticflags' => 1,
65
                         'type_is_dynamic'  => 1,
65
                         'type_is_dynamic'  => 1,
66
                         'type_is_binary'   => 1,
66
                         'type_is_binary'   => 1,
67
                        );
67
                        );
68
 
68
 
69
# ************************************************************
69
# ************************************************************
70
# Subroutine Section
70
# Subroutine Section
71
# ************************************************************
71
# ************************************************************
72
 
72
 
73
sub new {
73
sub new {
74
  my($class) = shift;
74
  my($class) = shift;
75
  my($prjc)  = shift;
75
  my($prjc)  = shift;
76
  my($self)  = $class->SUPER::new();
76
  my($self)  = $class->SUPER::new();
77
 
77
 
78
  $self->{'prjc'}                 = $prjc;
78
  $self->{'prjc'}                 = $prjc;
79
  $self->{'ti'}                   = $prjc->get_template_input();
79
  $self->{'ti'}                   = $prjc->get_template_input();
80
  $self->{'cslashes'}             = $prjc->convert_slashes();
80
  $self->{'cslashes'}             = $prjc->convert_slashes();
81
  $self->{'crlf'}                 = $prjc->crlf();
81
  $self->{'crlf'}                 = $prjc->crlf();
82
  $self->{'cmds'}                 = $prjc->get_command_subs();
82
  $self->{'cmds'}                 = $prjc->get_command_subs();
83
  $self->{'vnames'}               = $prjc->get_valid_names();
83
  $self->{'vnames'}               = $prjc->get_valid_names();
84
  $self->{'values'}               = {};
84
  $self->{'values'}               = {};
85
  $self->{'defaults'}             = {};
85
  $self->{'defaults'}             = {};
86
  $self->{'lines'}                = [];
86
  $self->{'lines'}                = [];
87
  $self->{'built'}                = '';
87
  $self->{'built'}                = '';
88
  $self->{'sstack'}               = [];
88
  $self->{'sstack'}               = [];
89
  $self->{'lstack'}               = [];
89
  $self->{'lstack'}               = [];
90
  $self->{'if_skip'}              = 0;
90
  $self->{'if_skip'}              = 0;
91
  $self->{'eval'}                 = 0;
91
  $self->{'eval'}                 = 0;
92
  $self->{'eval_str'}             = '';
92
  $self->{'eval_str'}             = '';
93
  $self->{'dupfiles'}             = {};
93
  $self->{'dupfiles'}             = {};
94
  $self->{'override_target_type'} = undef;
94
  $self->{'override_target_type'} = undef;
95
 
95
 
96
  $self->{'foreach'}  = {};
96
  $self->{'foreach'}  = {};
97
  $self->{'foreach'}->{'count'}      = -1;
97
  $self->{'foreach'}->{'count'}      = -1;
98
  $self->{'foreach'}->{'nested'}     = 0;
98
  $self->{'foreach'}->{'nested'}     = 0;
99
  $self->{'foreach'}->{'name'}       = [];
99
  $self->{'foreach'}->{'name'}       = [];
100
  $self->{'foreach'}->{'vars'}       = [];
100
  $self->{'foreach'}->{'vars'}       = [];
101
  $self->{'foreach'}->{'text'}       = [];
101
  $self->{'foreach'}->{'text'}       = [];
102
  $self->{'foreach'}->{'scope'}      = [];
102
  $self->{'foreach'}->{'scope'}      = [];
103
  $self->{'foreach'}->{'scope_name'} = [];
103
  $self->{'foreach'}->{'scope_name'} = [];
104
  $self->{'foreach'}->{'temp_scope'} = [];
104
  $self->{'foreach'}->{'temp_scope'} = [];
105
  $self->{'foreach'}->{'processing'} = 0;
105
  $self->{'foreach'}->{'processing'} = 0;
106
 
106
 
107
  return $self;
107
  return $self;
108
}
108
}
109
 
109
 
110
 
110
 
111
sub basename {
111
sub basename {
112
  my($self) = shift;
112
  my($self) = shift;
113
  my($file) = shift;
113
  my($file) = shift;
114
 
114
 
115
  if ($self->{'cslashes'}) {
115
  if ($self->{'cslashes'}) {
116
    $file =~ s/.*[\/\\]//;
116
    $file =~ s/.*[\/\\]//;
117
  }
117
  }
118
  else {
118
  else {
119
    $file =~ s/.*\///;
119
    $file =~ s/.*\///;
120
  }
120
  }
121
  return $file;
121
  return $file;
122
}
122
}
123
 
123
 
124
 
124
 
125
sub tp_dirname {
125
sub tp_dirname {
126
  my($self)  = shift;
126
  my($self)  = shift;
127
  my($file)  = shift;
127
  my($file)  = shift;
128
  my($index) = rindex($file, ($self->{'cslashes'} ? '\\' : '/'));
128
  my($index) = rindex($file, ($self->{'cslashes'} ? '\\' : '/'));
129
 
129
 
130
  if ($index >= 0) {
130
  if ($index >= 0) {
131
    return $self->{'prjc'}->validated_directory(substr($file, 0, $index));
131
    return $self->{'prjc'}->validated_directory(substr($file, 0, $index));
132
  }
132
  }
133
  else {
133
  else {
134
    return '.';
134
    return '.';
135
  }
135
  }
136
}
136
}
137
 
137
 
138
 
138
 
139
sub strip_line {
139
sub strip_line {
140
  #my($self) = shift;
140
  #my($self) = shift;
141
  #my($line) = shift;
141
  #my($line) = shift;
142
 
142
 
143
  ## Override strip_line() from Parser.
143
  ## Override strip_line() from Parser.
144
  ## We need to preserve leading space and
144
  ## We need to preserve leading space and
145
  ## there is no comment string in templates.
145
  ## there is no comment string in templates.
146
  ++$_[0]->{'line_number'};
146
  ++$_[0]->{'line_number'};
147
  $_[1] =~ s/\s+$//;
147
  $_[1] =~ s/\s+$//;
148
 
148
 
149
  return $_[1];
149
  return $_[1];
150
}
150
}
151
 
151
 
152
 
152
 
153
## Append the current value to the line that is being
153
## Append the current value to the line that is being
154
## built.  This line may be a foreach line or a general
154
## built.  This line may be a foreach line or a general
155
## line without a foreach.
155
## line without a foreach.
156
sub append_current {
156
sub append_current {
157
#  my($self)  = shift;
157
#  my($self)  = shift;
158
#  my($value) = shift;
158
#  my($value) = shift;
159
 
159
 
160
  if ($_[0]->{'foreach'}->{'count'} >= 0) {
160
  if ($_[0]->{'foreach'}->{'count'} >= 0) {
161
    $_[0]->{'foreach'}->{'text'}->[$_[0]->{'foreach'}->{'count'}] .= $_[1];
161
    $_[0]->{'foreach'}->{'text'}->[$_[0]->{'foreach'}->{'count'}] .= $_[1];
162
  }
162
  }
163
  elsif ($_[0]->{'eval'}) {
163
  elsif ($_[0]->{'eval'}) {
164
    $_[0]->{'eval_str'} .= $_[1];
164
    $_[0]->{'eval_str'} .= $_[1];
165
  }
165
  }
166
  else {
166
  else {
167
    $_[0]->{'built'} .= $_[1];
167
    $_[0]->{'built'} .= $_[1];
168
  }
168
  }
169
}
169
}
170
 
170
 
171
 
171
 
172
sub split_parameters {
172
sub split_parameters {
173
  my($self)   = shift;
173
  my($self)   = shift;
174
  my($str)    = shift;
174
  my($str)    = shift;
175
  my(@params) = ();
175
  my(@params) = ();
176
 
176
 
177
  while($str =~ /(\w+\([^\)]+\))\s*,\s*(.*)/) {
177
  while($str =~ /(\w+\([^\)]+\))\s*,\s*(.*)/) {
178
    push(@params, $1);
178
    push(@params, $1);
179
    $str = $2;
179
    $str = $2;
180
  }
180
  }
181
  while($str =~ /([^,]+)\s*,\s*(.*)/) {
181
  while($str =~ /([^,]+)\s*,\s*(.*)/) {
182
    push(@params, $1);
182
    push(@params, $1);
183
    $str = $2;
183
    $str = $2;
184
  }
184
  }
185
 
185
 
186
  ## Return the parameters (which includes whatever is left in the
186
  ## Return the parameters (which includes whatever is left in the
187
  ## string).  Just return it instead of pushing it onto @params.
187
  ## string).  Just return it instead of pushing it onto @params.
188
  return @params, $str;
188
  return @params, $str;
189
}
189
}
190
 
190
 
191
 
191
 
192
sub set_current_values {
192
sub set_current_values {
193
  my($self) = shift;
193
  my($self) = shift;
194
  my($name) = shift;
194
  my($name) = shift;
195
  my($set)  = 0;
195
  my($set)  = 0;
196
 
196
 
197
  ## If any value within a foreach matches the name
197
  ## If any value within a foreach matches the name
198
  ## of a hash table within the template input we will
198
  ## of a hash table within the template input we will
199
  ## set the values of that hash table in the current scope
199
  ## set the values of that hash table in the current scope
200
  if (defined $self->{'ti'}) {
200
  if (defined $self->{'ti'}) {
201
    my($counter) = $self->{'foreach'}->{'count'};
201
    my($counter) = $self->{'foreach'}->{'count'};
202
    if ($counter >= 0) {
202
    if ($counter >= 0) {
203
      ## Variable names are case-insensitive in MPC, however this can
203
      ## Variable names are case-insensitive in MPC, however this can
204
      ## cause problems when dealing with template variable values that
204
      ## cause problems when dealing with template variable values that
205
      ## happen to match HASH names only by case-insensitivity.  So, we
205
      ## happen to match HASH names only by case-insensitivity.  So, we
206
      ## now make HASH names match with case-sensitivity.
206
      ## now make HASH names match with case-sensitivity.
207
      my($value) = $self->{'ti'}->get_value($name);
207
      my($value) = $self->{'ti'}->get_value($name);
208
      if (defined $value && UNIVERSAL::isa($value, 'HASH') &&
208
      if (defined $value && UNIVERSAL::isa($value, 'HASH') &&
209
          $self->{'ti'}->get_realname($name) eq $name) {
209
          $self->{'ti'}->get_realname($name) eq $name) {
210
        $self->{'foreach'}->{'scope_name'}->[$counter] = $name;
210
        $self->{'foreach'}->{'scope_name'}->[$counter] = $name;
211
        my(%copy) = ();
211
        my(%copy) = ();
212
        foreach my $key (keys %$value) {
212
        foreach my $key (keys %$value) {
213
          $copy{$key} = $self->{'prjc'}->adjust_value(
213
          $copy{$key} = $self->{'prjc'}->adjust_value(
214
                    [$name . '::' . $key, $name], $$value{$key});
214
                    [$name . '::' . $key, $name], $$value{$key});
215
        }
215
        }
216
        $self->{'foreach'}->{'temp_scope'}->[$counter] = \%copy;
216
        $self->{'foreach'}->{'temp_scope'}->[$counter] = \%copy;
217
        $set = 1;
217
        $set = 1;
218
      }
218
      }
219
    }
219
    }
220
  }
220
  }
221
  return $set;
221
  return $set;
222
}
222
}
223
 
223
 
224
 
224
 
225
sub get_value {
225
sub get_value {
226
  my($self)    = shift;
226
  my($self)    = shift;
227
  my($name)    = shift;
227
  my($name)    = shift;
228
  my($value)   = undef;
228
  my($value)   = undef;
229
  my($counter) = $self->{'foreach'}->{'count'};
229
  my($counter) = $self->{'foreach'}->{'count'};
230
  my($fromprj) = 0;
230
  my($fromprj) = 0;
231
  my($scope)   = undef;
231
  my($scope)   = undef;
232
  my($sname)   = undef;
232
  my($sname)   = undef;
233
  my($adjust)  = 1;
233
  my($adjust)  = 1;
234
 
234
 
-
 
235
  ## $name should always be all lower-case
-
 
236
  $name = lc($name);
-
 
237
 
235
  ## First, check the temporary scope (set inside a foreach)
238
  ## First, check the temporary scope (set inside a foreach)
236
  if ($counter >= 0) {
239
  if ($counter >= 0) {
237
    ## Find the outer most scope for our variable name
240
    ## Find the outer most scope for our variable name
238
    for(my $index = $counter; $index >= 0; --$index) {
241
    for(my $index = $counter; $index >= 0; --$index) {
239
      if (defined $self->{'foreach'}->{'scope_name'}->[$index]) {
242
      if (defined $self->{'foreach'}->{'scope_name'}->[$index]) {
240
        $scope = $self->{'foreach'}->{'scope_name'}->[$index];
243
        $scope = $self->{'foreach'}->{'scope_name'}->[$index];
241
        $sname = $scope . '::' . $name;
244
        $sname = $scope . '::' . $name;
242
        last;
245
        last;
243
      }
246
      }
244
    }
247
    }
245
    while(!defined $value && $counter >= 0) {
248
    while(!defined $value && $counter >= 0) {
246
      $value = $self->{'foreach'}->{'temp_scope'}->[$counter]->{$name};
249
      $value = $self->{'foreach'}->{'temp_scope'}->[$counter]->{$name};
247
      --$counter;
250
      --$counter;
248
    }
251
    }
249
    $counter = $self->{'foreach'}->{'count'};
252
    $counter = $self->{'foreach'}->{'count'};
250
 
253
 
251
    if ($self->{'override_target_type'} &&
254
    if ($self->{'override_target_type'} &&
252
        defined $value && defined $target_type_vars{$name}) {
255
        defined $value && defined $target_type_vars{$name}) {
253
      $value = $self->{'values'}->{$name};
256
      $value = $self->{'values'}->{$name};
254
    }
257
    }
255
  }
258
  }
256
 
259
 
257
  if (!defined $value) {
260
  if (!defined $value) {
258
    if ($name =~ /^flag_overrides\((.*)\)$/) {
261
    if ($name =~ /^flag_overrides\((.*)\)$/) {
259
      $value = $self->get_flag_overrides($1);
262
      $value = $self->get_flag_overrides($1);
260
    }
263
    }
261
 
264
 
262
    if (!defined $value) {
265
    if (!defined $value) {
263
      ## Next, check for a template value
266
      ## Next, check for a template value
264
      if (defined $self->{'ti'}) {
267
      if (defined $self->{'ti'}) {
265
        $value = $self->{'ti'}->get_value($name);
268
        $value = $self->{'ti'}->get_value($name);
266
      }
269
      }
267
 
270
 
268
      if (!defined $value) {
271
      if (!defined $value) {
269
        ## Calling adjust_value here allows us to pick up template
272
        ## Calling adjust_value here allows us to pick up template
270
        ## overrides before getting values elsewhere.
273
        ## overrides before getting values elsewhere.
271
        my($uvalue) = $self->{'prjc'}->adjust_value([$sname, $name], []);
274
        my($uvalue) = $self->{'prjc'}->adjust_value([$sname, $name], []);
272
        if (defined $$uvalue[0]) {
275
        if (defined $$uvalue[0]) {
273
          $value = $uvalue;
276
          $value = $uvalue;
274
          $adjust = 0;
277
          $adjust = 0;
275
        }
278
        }
276
 
279
 
277
        if (!defined $value) {
280
        if (!defined $value) {
278
          ## Next, check the inner to outer foreach
281
          ## Next, check the inner to outer foreach
279
          ## scopes for overriding values
282
          ## scopes for overriding values
280
          while(!defined $value && $counter >= 0) {
283
          while(!defined $value && $counter >= 0) {
281
            $value = $self->{'foreach'}->{'scope'}->[$counter]->{$name};
284
            $value = $self->{'foreach'}->{'scope'}->[$counter]->{$name};
282
            --$counter;
285
            --$counter;
283
          }
286
          }
284
 
287
 
285
          ## Then get the value from the project creator
288
          ## Then get the value from the project creator
286
          if (!defined $value) {
289
          if (!defined $value) {
287
            $fromprj = 1;
290
            $fromprj = 1;
288
            $value = $self->{'prjc'}->get_assignment($name);
291
            $value = $self->{'prjc'}->get_assignment($name);
289
 
292
 
290
            ## Then get it from our known values
293
            ## Then get it from our known values
291
            if (!defined $value) {
294
            if (!defined $value) {
292
              $value = $self->{'values'}->{$name};
295
              $value = $self->{'values'}->{$name};
293
              if (!defined $value) {
296
              if (!defined $value) {
294
                ## Call back onto the project creator to allow
297
                ## Call back onto the project creator to allow
295
                ## it to fill in the value before defaulting to undef.
298
                ## it to fill in the value before defaulting to undef.
296
                $value = $self->{'prjc'}->fill_value($name);
299
                $value = $self->{'prjc'}->fill_value($name);
297
                if (!defined $value && $name =~ /^(.*)\->(\w+)/) {
300
                if (!defined $value && $name =~ /^(.*)\->(\w+)/) {
298
                  my($pre)  = $1;
301
                  my($pre)  = $1;
299
                  my($post) = $2;
302
                  my($post) = $2;
300
                  my($base) = $self->get_value($pre);
303
                  my($base) = $self->get_value($pre);
301
 
304
 
302
                  if (defined $base) {
305
                  if (defined $base) {
303
                    $value = $self->{'prjc'}->get_special_value(
306
                    $value = $self->{'prjc'}->get_special_value(
304
                               $pre, $post, $base,
307
                               $pre, $post, $base,
305
                               ($self->{'prjc'}->requires_parameters($post) ?
308
                               ($self->{'prjc'}->requires_parameters($post) ?
306
                                   $self->prepare_parameters($pre) : undef));
309
                                   $self->prepare_parameters($pre) : undef));
307
                  }
310
                  }
308
                }
311
                }
309
              }
312
              }
310
            }
313
            }
311
          }
314
          }
312
        }
315
        }
313
      }
316
      }
314
    }
317
    }
315
  }
318
  }
316
 
319
 
317
  ## Adjust the value even if we haven't obtained one from an outside
320
  ## Adjust the value even if we haven't obtained one from an outside
318
  ## source.
321
  ## source.
319
  if ($adjust && defined $value) {
322
  if ($adjust && defined $value) {
320
    $value = $self->{'prjc'}->adjust_value([$sname, $name], $value);
323
    $value = $self->{'prjc'}->adjust_value([$sname, $name], $value);
321
  }
324
  }
322
 
325
 
323
  ## If the value did not come from the project creator, we
326
  ## If the value did not come from the project creator, we
324
  ## check the variable name.  If it is a project keyword we then
327
  ## check the variable name.  If it is a project keyword we then
325
  ## check to see if we need to add the project value to the template
328
  ## check to see if we need to add the project value to the template
326
  ## variable value.  If so, we make a copy of the value array and
329
  ## variable value.  If so, we make a copy of the value array and
327
  ## push the project value onto that (to avoid modifying the original).
330
  ## push the project value onto that (to avoid modifying the original).
328
  if (!$fromprj && defined $self->{'vnames'}->{$name} &&
331
  if (!$fromprj && defined $self->{'vnames'}->{$name} &&
329
      $self->{'prjc'}->add_to_template_input_value($name)) {
332
      $self->{'prjc'}->add_to_template_input_value($name)) {
330
    my($pjval) = $self->{'prjc'}->get_assignment($name);
333
    my($pjval) = $self->{'prjc'}->get_assignment($name);
331
    if (defined $pjval) {
334
    if (defined $pjval) {
332
      my(@copy) = @$value;
335
      my(@copy) = @$value;
333
      if (!UNIVERSAL::isa($pjval, 'ARRAY')) {
336
      if (!UNIVERSAL::isa($pjval, 'ARRAY')) {
334
        $pjval = $self->create_array($pjval);
337
        $pjval = $self->create_array($pjval);
335
      }
338
      }
336
      push(@copy, @$pjval);
339
      push(@copy, @$pjval);
337
      $value = \@copy;
340
      $value = \@copy;
338
    }
341
    }
339
  }
342
  }
340
 
343
 
341
  return $self->{'prjc'}->relative($value, undef, $scope);
344
  return $self->{'prjc'}->relative($value, undef, $scope);
342
}
345
}
343
 
346
 
344
 
347
 
345
sub get_value_with_default {
348
sub get_value_with_default {
346
  my($self)  = shift;
349
  my($self)  = shift;
347
  my($name)  = shift;
350
  my($name)  = shift;
348
  my($value) = $self->get_value($name);
351
  my($value) = $self->get_value($name);
349
 
352
 
350
  if (!defined $value) {
353
  if (!defined $value) {
351
    $value = $self->{'defaults'}->{$name};
354
    $value = $self->{'defaults'}->{$name};
352
    if (defined $value) {
355
    if (defined $value) {
353
      my($counter) = $self->{'foreach'}->{'count'};
356
      my($counter) = $self->{'foreach'}->{'count'};
354
      my($sname)   = undef;
357
      my($sname)   = undef;
355
 
358
 
356
      if ($counter >= 0) {
359
      if ($counter >= 0) {
357
        ## Find the outer most scope for our variable name
360
        ## Find the outer most scope for our variable name
358
        for(my $index = $counter; $index >= 0; --$index) {
361
        for(my $index = $counter; $index >= 0; --$index) {
359
          if (defined $self->{'foreach'}->{'scope_name'}->[$index]) {
362
          if (defined $self->{'foreach'}->{'scope_name'}->[$index]) {
360
            $sname = $self->{'foreach'}->{'scope_name'}->[$index] .
363
            $sname = $self->{'foreach'}->{'scope_name'}->[$index] .
361
                     '::' . $name;
364
                     '::' . $name;
362
            last;
365
            last;
363
          }
366
          }
364
        }
367
        }
365
      }
368
      }
366
      $value = $self->{'prjc'}->relative(
369
      $value = $self->{'prjc'}->relative(
367
                    $self->{'prjc'}->adjust_value([$sname, $name], $value));
370
                    $self->{'prjc'}->adjust_value([$sname, $name], $value));
368
 
371
 
369
      ## If the user set the variable to empty, we will go ahead and use
372
      ## If the user set the variable to empty, we will go ahead and use
370
      ## the default value (since we know we have one at this point).
373
      ## the default value (since we know we have one at this point).
371
      if (!defined $value) {
374
      if (!defined $value) {
372
        $value = $self->{'defaults'}->{$name};
375
        $value = $self->{'defaults'}->{$name};
373
      }
376
      }
374
    }
377
    }
375
    else {
378
    else {
376
      #$self->warning("$name defaulting to empty string.");
379
      #$self->warning("$name defaulting to empty string.");
377
      $value = '';
380
      $value = '';
378
    }
381
    }
379
  }
382
  }
380
 
383
 
381
  if (UNIVERSAL::isa($value, 'ARRAY')) {
384
  if (UNIVERSAL::isa($value, 'ARRAY')) {
382
    $value = "@$value";
385
    $value = "@$value";
383
  }
386
  }
384
 
387
 
385
  return $value;
388
  return $value;
386
}
389
}
387
 
390
 
388
 
391
 
389
sub process_foreach {
392
sub process_foreach {
390
  my($self)   = shift;
393
  my($self)   = shift;
391
  my($index)  = $self->{'foreach'}->{'count'};
394
  my($index)  = $self->{'foreach'}->{'count'};
392
  my($text)   = $self->{'foreach'}->{'text'}->[$index];
395
  my($text)   = $self->{'foreach'}->{'text'}->[$index];
393
  my($status) = 1;
396
  my($status) = 1;
394
  my($error)  = undef;
397
  my($error)  = undef;
395
  my(@values) = ();
398
  my(@values) = ();
396
  my($name)   = $self->{'foreach'}->{'name'}->[$index];
399
  my($name)   = $self->{'foreach'}->{'name'}->[$index];
397
  my(@cmds)   = ();
400
  my(@cmds)   = ();
398
  my($val)    = $self->{'foreach'}->{'vars'}->[$index];
401
  my($val)    = $self->{'foreach'}->{'vars'}->[$index];
399
 
402
 
400
  if ($val =~ /^((\w+),\s*)?flag_overrides\((.*)\)$/) {
403
  if ($val =~ /^((\w+),\s*)?flag_overrides\((.*)\)$/) {
401
    my($over) = $self->get_flag_overrides($3);
404
    my($over) = $self->get_flag_overrides($3);
402
    $name = $2;
405
    $name = $2;
403
    if (defined $over) {
406
    if (defined $over) {
404
      $val = $self->create_array($over);
407
      $val = $self->create_array($over);
405
      @values = @$val;
408
      @values = @$val;
406
    }
409
    }
407
    if (!defined $name) {
410
    if (!defined $name) {
408
      $name = '__unnamed__';
411
      $name = '__unnamed__';
409
    }
412
    }
410
  }
413
  }
411
  else {
414
  else {
412
    ## Pull out modifying commands first
415
    ## Pull out modifying commands first
413
    while ($val =~ /(\w+)\((.+)\)/) {
416
    while ($val =~ /(\w+)\((.+)\)/) {
414
      my($cmd) = $1;
417
      my($cmd) = $1;
415
      $val     = $2;
418
      $val     = $2;
416
      if (($keywords{$cmd} & 0x02) != 0) {
419
      if (($keywords{$cmd} & 0x02) != 0) {
417
        push(@cmds, 'perform_' . $cmd);
420
        push(@cmds, 'perform_' . $cmd);
418
      }
421
      }
419
      else {
422
      else {
420
        $self->warning("Unable to use $cmd in foreach (no perform_ method).");
423
        $self->warning("Unable to use $cmd in foreach (no perform_ method).");
421
      }
424
      }
422
    }
425
    }
423
 
426
 
424
    ## Get the values for all of the variable names
427
    ## Get the values for all of the variable names
425
    ## contained within the foreach
428
    ## contained within the foreach
426
    my($names) = $self->create_array($val);
429
    my($names) = $self->create_array($val);
427
    foreach my $n (@$names) {
430
    foreach my $n (@$names) {
428
      my($vals) = $self->get_value($n);
431
      my($vals) = $self->get_value($n);
429
      if (defined $vals && $vals ne '') {
432
      if (defined $vals && $vals ne '') {
430
        if (!UNIVERSAL::isa($vals, 'ARRAY')) {
433
        if (!UNIVERSAL::isa($vals, 'ARRAY')) {
431
          $vals = $self->create_array($vals);
434
          $vals = $self->create_array($vals);
432
        }
435
        }
433
        push(@values, @$vals);
436
        push(@values, @$vals);
434
      }
437
      }
435
      if (!defined $name) {
438
      if (!defined $name) {
436
        $name = $n;
439
        $name = $n;
437
        $name =~ s/s$//;
440
        $name =~ s/s$//;
438
      }
441
      }
439
    }
442
    }
440
  }
443
  }
441
 
444
 
442
  ## Perform the commands on the built up @values
445
  ## Perform the commands on the built up @values
443
  foreach my $cmd (reverse @cmds) {
446
  foreach my $cmd (reverse @cmds) {
444
    @values = $self->$cmd(\@values);
447
    @values = $self->$cmd(\@values);
445
  }
448
  }
446
 
449
 
447
  ## Reset the text (it will be regenerated by calling parse_line
450
  ## Reset the text (it will be regenerated by calling parse_line
448
  $self->{'foreach'}->{'text'}->[$index] = '';
451
  $self->{'foreach'}->{'text'}->[$index] = '';
449
 
452
 
450
  if (defined $values[0]) {
453
  if (defined $values[0]) {
451
    my($scope) = $self->{'foreach'}->{'scope'}->[$index];
454
    my($scope) = $self->{'foreach'}->{'scope'}->[$index];
452
 
455
 
453
    $$scope{'forlast'}     = '';
456
    $$scope{'forlast'}     = '';
454
    $$scope{'fornotlast'}  = 1;
457
    $$scope{'fornotlast'}  = 1;
455
    $$scope{'forfirst'}    = 1;
458
    $$scope{'forfirst'}    = 1;
456
    $$scope{'fornotfirst'} = '';
459
    $$scope{'fornotfirst'} = '';
457
 
460
 
458
    ## If the foreach values are mixed (HASH and SCALAR), then
461
    ## If the foreach values are mixed (HASH and SCALAR), then
459
    ## remove the SCALAR values.
462
    ## remove the SCALAR values.
460
    my(%mixed) = ();
463
    my(%mixed) = ();
461
    my($mixed) = 0;
464
    my($mixed) = 0;
462
    for(my $i = 0; $i <= $#values; ++$i) {
465
    for(my $i = 0; $i <= $#values; ++$i) {
463
      $mixed{$values[$i]} = $self->set_current_values($values[$i]);
466
      $mixed{$values[$i]} = $self->set_current_values($values[$i]);
464
      $mixed |= $mixed{$values[$i]};
467
      $mixed |= $mixed{$values[$i]};
465
    }
468
    }
466
    if ($mixed) {
469
    if ($mixed) {
467
      my(@nvalues) = ();
470
      my(@nvalues) = ();
468
      foreach my $key (sort keys %mixed) {
471
      foreach my $key (sort keys %mixed) {
469
        if ($mixed{$key}) {
472
        if ($mixed{$key}) {
470
          push(@nvalues, $key);
473
          push(@nvalues, $key);
471
        }
474
        }
472
      }
475
      }
473
 
476
 
474
      ## Set the new values only if they are different
477
      ## Set the new values only if they are different
475
      ## from the original (except for order).
478
      ## from the original (except for order).
476
      my(@sorted) = sort(@values);
479
      my(@sorted) = sort(@values);
477
      if (@sorted != @nvalues) {
480
      if (@sorted != @nvalues) {
478
        @values = @nvalues;
481
        @values = @nvalues;
479
      }
482
      }
480
    }
483
    }
481
 
484
 
482
    for(my $i = 0; $i <= $#values; ++$i) {
485
    for(my $i = 0; $i <= $#values; ++$i) {
483
      my($value) = $values[$i];
486
      my($value) = $values[$i];
484
 
487
 
485
      ## Set the corresponding values in the temporary scope
488
      ## Set the corresponding values in the temporary scope
486
      $self->set_current_values($value);
489
      $self->set_current_values($value);
487
 
490
 
488
      ## Set the special values that only exist
491
      ## Set the special values that only exist
489
      ## within a foreach
492
      ## within a foreach
490
      if ($i != 0) {
493
      if ($i != 0) {
491
        $$scope{'forfirst'}    = '';
494
        $$scope{'forfirst'}    = '';
492
        $$scope{'fornotfirst'} = 1;
495
        $$scope{'fornotfirst'} = 1;
493
      }
496
      }
494
      if ($i == $#values) {
497
      if ($i == $#values) {
495
        $$scope{'forlast'}    = 1;
498
        $$scope{'forlast'}    = 1;
496
        $$scope{'fornotlast'} = '';
499
        $$scope{'fornotlast'} = '';
497
      }
500
      }
498
      $$scope{'forcount'} = $i + 1;
501
      $$scope{'forcount'} = $i + 1;
499
 
502
 
500
      ## We don't use adjust_value here because these names
503
      ## We don't use adjust_value here because these names
501
      ## are generated from a foreach and should not be adjusted.
504
      ## are generated from a foreach and should not be adjusted.
502
      $$scope{$name} = $value;
505
      $$scope{$name} = $value;
503
 
506
 
504
      ## A tiny hack for VC7
507
      ## A tiny hack for VC7
505
      if ($name eq 'configuration') {
508
      if ($name eq 'configuration') {
506
        $self->{'prjc'}->update_project_info($self, 1,
509
        $self->{'prjc'}->update_project_info($self, 1,
507
                                             ['configuration', 'platform'],
510
                                             ['configuration', 'platform'],
508
                                             '|');
511
                                             '|');
509
      }
512
      }
510
 
513
 
511
      ## Now parse the line of text, each time
514
      ## Now parse the line of text, each time
512
      ## with different values
515
      ## with different values
513
      ++$self->{'foreach'}->{'processing'};
516
      ++$self->{'foreach'}->{'processing'};
514
      ($status, $error) = $self->parse_line(undef, $text);
517
      ($status, $error) = $self->parse_line(undef, $text);
515
      --$self->{'foreach'}->{'processing'};
518
      --$self->{'foreach'}->{'processing'};
516
      if (!$status) {
519
      if (!$status) {
517
        last;
520
        last;
518
      }
521
      }
519
    }
522
    }
520
  }
523
  }
521
 
524
 
522
  return $status, $error;
525
  return $status, $error;
523
}
526
}
524
 
527
 
525
 
528
 
526
sub handle_endif {
529
sub handle_endif {
527
  my($self) = shift;
530
  my($self) = shift;
528
  my($name) = shift;
531
  my($name) = shift;
529
  my($end)  = pop(@{$self->{'sstack'}});
532
  my($end)  = pop(@{$self->{'sstack'}});
530
  pop(@{$self->{'lstack'}});
533
  pop(@{$self->{'lstack'}});
531
 
534
 
532
  if (!defined $end) {
535
  if (!defined $end) {
533
    return 0, "Unmatched $name";
536
    return 0, "Unmatched $name";
534
  }
537
  }
535
  else {
538
  else {
536
    my($in) = index($end, $name);
539
    my($in) = index($end, $name);
537
    if ($in == 0) {
540
    if ($in == 0) {
538
      $self->{'if_skip'} = 0;
541
      $self->{'if_skip'} = 0;
539
    }
542
    }
540
    elsif ($in == -1) {
543
    elsif ($in == -1) {
541
      return 0, "Unmatched $name";
544
      return 0, "Unmatched $name";
542
    }
545
    }
543
  }
546
  }
544
 
547
 
545
  return 1, undef;
548
  return 1, undef;
546
}
549
}
547
 
550
 
548
 
551
 
549
sub handle_endfor {
552
sub handle_endfor {
550
  my($self) = shift;
553
  my($self) = shift;
551
  my($name) = shift;
554
  my($name) = shift;
552
  my($end)  = pop(@{$self->{'sstack'}});
555
  my($end)  = pop(@{$self->{'sstack'}});
553
  pop(@{$self->{'lstack'}});
556
  pop(@{$self->{'lstack'}});
554
 
557
 
555
  if (!defined $end) {
558
  if (!defined $end) {
556
    return 0, "Unmatched $name";
559
    return 0, "Unmatched $name";
557
  }
560
  }
558
  else {
561
  else {
559
    my($in) = index($end, $name);
562
    my($in) = index($end, $name);
560
    if ($in == 0) {
563
    if ($in == 0) {
561
      my($index) = $self->{'foreach'}->{'count'};
564
      my($index) = $self->{'foreach'}->{'count'};
562
      my($status, $error) = $self->process_foreach();
565
      my($status, $error) = $self->process_foreach();
563
      if ($status) {
566
      if ($status) {
564
        --$self->{'foreach'}->{'count'};
567
        --$self->{'foreach'}->{'count'};
565
        $self->append_current($self->{'foreach'}->{'text'}->[$index]);
568
        $self->append_current($self->{'foreach'}->{'text'}->[$index]);
566
      }
569
      }
567
      return $status, $error;
570
      return $status, $error;
568
    }
571
    }
569
    elsif ($in == -1) {
572
    elsif ($in == -1) {
570
      return 0, "Unmatched $name";
573
      return 0, "Unmatched $name";
571
    }
574
    }
572
  }
575
  }
573
 
576
 
574
  return 1, undef;
577
  return 1, undef;
575
}
578
}
576
 
579
 
577
 
580
 
578
sub get_flag_overrides {
581
sub get_flag_overrides {
579
  my($self)  = shift;
582
  my($self)  = shift;
580
  my($name)  = shift;
583
  my($name)  = shift;
581
  my($type)  = '';
584
  my($type)  = '';
582
 
585
 
583
  ## Split the name and type parameters
586
  ## Split the name and type parameters
584
  ($name, $type) = split(/,\s*/, $name);
587
  ($name, $type) = split(/,\s*/, $name);
585
 
588
 
586
  my($file) = $self->get_value($name);
589
  my($file) = $self->get_value($name);
587
  if (defined $file) {
590
  if (defined $file) {
588
    my($value) = undef;
591
    my($value) = undef;
589
    my($prjc)  = $self->{'prjc'};
592
    my($prjc)  = $self->{'prjc'};
590
    my($fo)    = $prjc->{'flag_overrides'};
593
    my($fo)    = $prjc->{'flag_overrides'};
591
 
594
 
592
    ## Save the name prefix (if there is one) for
595
    ## Save the name prefix (if there is one) for
593
    ## command parameter conversion at the end
596
    ## command parameter conversion at the end
594
    my($pre) = undef;
597
    my($pre) = undef;
595
    if ($name =~ /(\w+)->/) {
598
    if ($name =~ /(\w+)->/) {
596
      $pre = $1;
599
      $pre = $1;
597
    }
600
    }
598
 
601
 
599
    ## Replace the custom_type key with the actual custom type
602
    ## Replace the custom_type key with the actual custom type
600
    if ($name =~ /^custom_type\->/) {
603
    if ($name =~ /^custom_type\->/) {
601
      my($ct) = $self->get_value('custom_type');
604
      my($ct) = $self->get_value('custom_type');
602
      if (defined $ct) {
605
      if (defined $ct) {
603
        $name = $ct;
606
        $name = $ct;
604
      }
607
      }
605
    }
608
    }
606
 
609
 
607
    my($key) = (defined $$fo{$name} ? $name :
610
    my($key) = (defined $$fo{$name} ? $name :
608
                   (defined $$fo{$name . 's'} ? $name . 's' : undef));
611
                   (defined $$fo{$name . 's'} ? $name . 's' : undef));
609
    if (defined $key) {
612
    if (defined $key) {
610
      if (defined $prjc->{'matching_assignments'}->{$key}) {
613
      if (defined $prjc->{'matching_assignments'}->{$key}) {
611
        ## Convert the file name into a unix style file name
614
        ## Convert the file name into a unix style file name
612
        my($ustyle) = $file;
615
        my($ustyle) = $file;
613
        $ustyle =~ s/\\/\//g;
616
        $ustyle =~ s/\\/\//g;
614
 
617
 
615
        ## Save the directory portion for checking in the foreach
618
        ## Save the directory portion for checking in the foreach
616
        my($dir) = $self->mpc_dirname($ustyle);
619
        my($dir) = $self->mpc_dirname($ustyle);
617
 
620
 
618
        my($of) = (defined $$fo{$key}->{$ustyle} ? $ustyle :
621
        my($of) = (defined $$fo{$key}->{$ustyle} ? $ustyle :
619
                      (defined $$fo{$key}->{$dir} ? $dir : undef));
622
                      (defined $$fo{$key}->{$dir} ? $dir : undef));
620
        if (defined $of) {
623
        if (defined $of) {
621
          foreach my $aname (@{$prjc->{'matching_assignments'}->{$key}}) {
624
          foreach my $aname (@{$prjc->{'matching_assignments'}->{$key}}) {
622
            if ($aname eq $type && defined $$fo{$key}->{$of}->{$aname}) {
625
            if ($aname eq $type && defined $$fo{$key}->{$of}->{$aname}) {
623
              $value = $$fo{$key}->{$of}->{$aname};
626
              $value = $$fo{$key}->{$of}->{$aname};
624
              last;
627
              last;
625
            }
628
            }
626
          }
629
          }
627
        }
630
        }
628
      }
631
      }
629
    }
632
    }
630
 
633
 
631
    ## If the name that we're overriding has a value and
634
    ## If the name that we're overriding has a value and
632
    ## requires parameters, then we will convert all of the
635
    ## requires parameters, then we will convert all of the
633
    ## pseudo variables and provide parameters.
636
    ## pseudo variables and provide parameters.
634
    if (defined $pre &&
637
    if (defined $pre &&
635
        defined $value && $prjc->requires_parameters($type)) {
638
        defined $value && $prjc->requires_parameters($type)) {
636
      $value = $prjc->convert_command_parameters(
639
      $value = $prjc->convert_command_parameters(
637
                              $value,
640
                              $value,
638
                              $self->prepare_parameters($pre));
641
                              $self->prepare_parameters($pre));
639
    }
642
    }
640
 
643
 
641
    return $prjc->relative($value);
644
    return $prjc->relative($value);
642
  }
645
  }
643
 
646
 
644
  return undef;
647
  return undef;
645
}
648
}
646
 
649
 
647
 
650
 
648
sub get_multiple {
651
sub get_multiple {
649
  my($self)  = shift;
652
  my($self)  = shift;
650
  my($name)  = shift;
653
  my($name)  = shift;
651
  my($value) = $self->get_value_with_default($name);
654
  my($value) = $self->get_value_with_default($name);
652
  return (defined $value ?
655
  return (defined $value ?
653
              $self->doif_multiple($self->create_array($value)) :
656
              $self->doif_multiple($self->create_array($value)) :
654
              undef);
657
              undef);
655
}
658
}
656
 
659
 
657
 
660
 
658
sub doif_multiple {
661
sub doif_multiple {
659
  my($self)  = shift;
662
  my($self)  = shift;
660
  my($value) = shift;
663
  my($value) = shift;
661
 
664
 
662
  if (defined $value) {
665
  if (defined $value) {
663
    return (scalar(@$value) > 1);
666
    return (scalar(@$value) > 1);
664
  }
667
  }
665
  return undef;
668
  return undef;
666
}
669
}
667
 
670
 
668
 
671
 
669
sub handle_multiple {
672
sub handle_multiple {
670
  my($self) = shift;
673
  my($self) = shift;
671
  my($name) = shift;
674
  my($name) = shift;
672
  my($val)  = $self->get_value_with_default($name);
675
  my($val)  = $self->get_value_with_default($name);
673
 
676
 
674
  if (defined $val) {
677
  if (defined $val) {
675
    my($array) = $self->create_array($val);
678
    my($array) = $self->create_array($val);
676
    $self->append_current(scalar(@$array));
679
    $self->append_current(scalar(@$array));
677
  }
680
  }
678
  else {
681
  else {
679
    $self->append_current(0);
682
    $self->append_current(0);
680
  }
683
  }
681
}
684
}
682
 
685
 
683
 
686
 
684
sub get_starts_with {
687
sub get_starts_with {
685
  my($self) = shift;
688
  my($self) = shift;
686
  my($str)  = shift;
689
  my($str)  = shift;
687
  return $self->doif_starts_with([$str]);
690
  return $self->doif_starts_with([$str]);
688
}
691
}
689
 
692
 
690
 
693
 
691
sub doif_starts_with {
694
sub doif_starts_with {
692
  my($self) = shift;
695
  my($self) = shift;
693
  my($val)  = shift;
696
  my($val)  = shift;
694
 
697
 
695
  if (defined $val) {
698
  if (defined $val) {
696
    my($name, $pattern) = $self->split_parameters("@$val");
699
    my($name, $pattern) = $self->split_parameters("@$val");
697
    if (defined $name && defined $pattern) {
700
    if (defined $name && defined $pattern) {
698
      return ($self->get_value_with_default($name) =~ /^$pattern/);
701
      return ($self->get_value_with_default($name) =~ /^$pattern/);
699
    }
702
    }
700
  }
703
  }
701
  return undef;
704
  return undef;
702
}
705
}
703
 
706
 
704
 
707
 
705
sub handle_starts_with {
708
sub handle_starts_with {
706
  my($self) = shift;
709
  my($self) = shift;
707
  my($str)  = shift;
710
  my($str)  = shift;
708
 
711
 
709
  if (defined $str) {
712
  if (defined $str) {
710
    my($val) = $self->doif_starts_with([$str]);
713
    my($val) = $self->doif_starts_with([$str]);
711
 
714
 
712
    if (defined $val) {
715
    if (defined $val) {
713
      $self->append_current($val);
716
      $self->append_current($val);
714
    }
717
    }
715
    else {
718
    else {
716
      $self->append_current(0);
719
      $self->append_current(0);
717
    }
720
    }
718
  }
721
  }
719
}
722
}
720
 
723
 
721
 
724
 
722
sub get_ends_with {
725
sub get_ends_with {
723
  my($self) = shift;
726
  my($self) = shift;
724
  my($str)  = shift;
727
  my($str)  = shift;
725
  return $self->doif_ends_with([$str]);
728
  return $self->doif_ends_with([$str]);
726
}
729
}
727
 
730
 
728
 
731
 
729
sub doif_ends_with {
732
sub doif_ends_with {
730
  my($self) = shift;
733
  my($self) = shift;
731
  my($val)  = shift;
734
  my($val)  = shift;
732
 
735
 
733
  if (defined $val) {
736
  if (defined $val) {
734
    my($name, $pattern) = $self->split_parameters("@$val");
737
    my($name, $pattern) = $self->split_parameters("@$val");
735
    if (defined $name && defined $pattern) {
738
    if (defined $name && defined $pattern) {
736
      return ($self->get_value_with_default($name) =~ /$pattern$/);
739
      return ($self->get_value_with_default($name) =~ /$pattern$/);
737
    }
740
    }
738
  }
741
  }
739
  return undef;
742
  return undef;
740
}
743
}
741
 
744
 
742
 
745
 
743
sub handle_ends_with {
746
sub handle_ends_with {
744
  my($self) = shift;
747
  my($self) = shift;
745
  my($str)  = shift;
748
  my($str)  = shift;
746
 
749
 
747
  if (defined $str) {
750
  if (defined $str) {
748
    my($val) = $self->doif_ends_with([$str]);
751
    my($val) = $self->doif_ends_with([$str]);
749
 
752
 
750
    if (defined $val) {
753
    if (defined $val) {
751
      $self->append_current($val);
754
      $self->append_current($val);
752
    }
755
    }
753
    else {
756
    else {
754
      $self->append_current(0);
757
      $self->append_current(0);
755
    }
758
    }
756
  }
759
  }
757
}
760
}
758
 
761
 
759
 
762
 
760
sub get_contains {
763
sub get_contains {
761
  my($self) = shift;
764
  my($self) = shift;
762
  my($str)  = shift;
765
  my($str)  = shift;
763
  return $self->doif_contains([$str]);
766
  return $self->doif_contains([$str]);
764
}
767
}
765
 
768
 
766
 
769
 
767
sub doif_contains {
770
sub doif_contains {
768
  my($self) = shift;
771
  my($self) = shift;
769
  my($val)  = shift;
772
  my($val)  = shift;
770
 
773
 
771
  if (defined $val) {
774
  if (defined $val) {
772
    my($name, $pattern) = $self->split_parameters("@$val");
775
    my($name, $pattern) = $self->split_parameters("@$val");
773
    if (defined $name && defined $pattern) {
776
    if (defined $name && defined $pattern) {
774
      return ($self->get_value_with_default($name) =~ /$pattern/);
777
      return ($self->get_value_with_default($name) =~ /$pattern/);
775
    }
778
    }
776
  }
779
  }
777
  return undef;
780
  return undef;
778
}
781
}
779
 
782
 
780
 
783
 
781
sub handle_contains {
784
sub handle_contains {
782
  my($self) = shift;
785
  my($self) = shift;
783
  my($str)  = shift;
786
  my($str)  = shift;
784
 
787
 
785
  if (defined $str) {
788
  if (defined $str) {
786
    my($val) = $self->doif_contains([$str]);
789
    my($val) = $self->doif_contains([$str]);
787
 
790
 
788
    if (defined $val) {
791
    if (defined $val) {
789
      $self->append_current($val);
792
      $self->append_current($val);
790
    }
793
    }
791
    else {
794
    else {
792
      $self->append_current(0);
795
      $self->append_current(0);
793
    }
796
    }
794
  }
797
  }
795
}
798
}
796
 
799
 
797
 
800
 
798
sub get_compares {
801
sub get_compares {
799
  my($self) = shift;
802
  my($self) = shift;
800
  my($str)  = shift;
803
  my($str)  = shift;
801
  return $self->doif_compares([$str]);
804
  return $self->doif_compares([$str]);
802
}
805
}
803
 
806
 
804
 
807
 
805
sub doif_compares {
808
sub doif_compares {
806
  my($self) = shift;
809
  my($self) = shift;
807
  my($val)  = shift;
810
  my($val)  = shift;
808
 
811
 
809
  if (defined $val) {
812
  if (defined $val) {
810
    my($name, $pattern) = $self->split_parameters("@$val");
813
    my($name, $pattern) = $self->split_parameters("@$val");
811
    if (defined $name && defined $pattern) {
814
    if (defined $name && defined $pattern) {
812
      return ($self->get_value_with_default($name) eq $pattern);
815
      return ($self->get_value_with_default($name) eq $pattern);
813
    }
816
    }
814
  }
817
  }
815
  return undef;
818
  return undef;
816
}
819
}
817
 
820
 
818
 
821
 
819
sub handle_compares {
822
sub handle_compares {
820
  my($self) = shift;
823
  my($self) = shift;
821
  my($str)  = shift;
824
  my($str)  = shift;
822
 
825
 
823
  if (defined $str) {
826
  if (defined $str) {
824
    my($val) = $self->doif_compares([$str]);
827
    my($val) = $self->doif_compares([$str]);
825
 
828
 
826
    if (defined $val) {
829
    if (defined $val) {
827
      $self->append_current($val);
830
      $self->append_current($val);
828
    }
831
    }
829
    else {
832
    else {
830
      $self->append_current(0);
833
      $self->append_current(0);
831
    }
834
    }
832
  }
835
  }
833
}
836
}
834
 
837
 
835
 
838
 
836
sub perform_reverse {
839
sub perform_reverse {
837
  my($self)  = shift;
840
  my($self)  = shift;
838
  my($value) = shift;
841
  my($value) = shift;
839
  return reverse(@$value);
842
  return reverse(@$value);
840
}
843
}
841
 
844
 
842
 
845
 
843
sub handle_reverse {
846
sub handle_reverse {
844
  my($self) = shift;
847
  my($self) = shift;
845
  my($name) = shift;
848
  my($name) = shift;
846
  my($val)  = $self->get_value_with_default($name);
849
  my($val)  = $self->get_value_with_default($name);
847
 
850
 
848
  if (defined $val) {
851
  if (defined $val) {
849
    my(@array) = $self->perform_reverse($self->create_array($val));
852
    my(@array) = $self->perform_reverse($self->create_array($val));
850
    $self->append_current("@array");
853
    $self->append_current("@array");
851
  }
854
  }
852
}
855
}
853
 
856
 
854
 
857
 
855
sub perform_sort {
858
sub perform_sort {
856
  my($self)  = shift;
859
  my($self)  = shift;
857
  my($value) = shift;
860
  my($value) = shift;
858
  return sort(@$value);
861
  return sort(@$value);
859
}
862
}
860
 
863
 
861
 
864
 
862
sub handle_sort {
865
sub handle_sort {
863
  my($self) = shift;
866
  my($self) = shift;
864
  my($name) = shift;
867
  my($name) = shift;
865
  my($val)  = $self->get_value_with_default($name);
868
  my($val)  = $self->get_value_with_default($name);
866
 
869
 
867
  if (defined $val) {
870
  if (defined $val) {
868
    my(@array) = $self->perform_sort($self->create_array($val));
871
    my(@array) = $self->perform_sort($self->create_array($val));
869
    $self->append_current("@array");
872
    $self->append_current("@array");
870
  }
873
  }
871
}
874
}
872
 
875
 
873
 
876
 
874
sub get_uniq {
877
sub get_uniq {
875
  my($self)  = shift;
878
  my($self)  = shift;
876
  my($name)  = shift;
879
  my($name)  = shift;
877
  my($value) = $self->get_value_with_default($name);
880
  my($value) = $self->get_value_with_default($name);
878
 
881
 
879
  if (defined $value) {
882
  if (defined $value) {
880
    my(@array) = $self->perform_uniq($self->create_array($value));
883
    my(@array) = $self->perform_uniq($self->create_array($value));
881
    return \@array;
884
    return \@array;
882
  }
885
  }
883
 
886
 
884
  return undef;
887
  return undef;
885
}
888
}
886
 
889
 
887
 
890
 
888
sub perform_uniq {
891
sub perform_uniq {
889
  my($self)  = shift;
892
  my($self)  = shift;
890
  my($value) = shift;
893
  my($value) = shift;
891
  my(%value) = ();
894
  my(%value) = ();
892
  @value{@$value} = ();
895
  @value{@$value} = ();
893
  return sort(keys %value);
896
  return sort(keys %value);
894
}
897
}
895
 
898
 
896
 
899
 
897
sub handle_uniq {
900
sub handle_uniq {
898
  my($self) = shift;
901
  my($self) = shift;
899
  my($name) = shift;
902
  my($name) = shift;
900
  my($val)  = $self->get_value_with_default($name);
903
  my($val)  = $self->get_value_with_default($name);
901
 
904
 
902
  if (defined $val) {
905
  if (defined $val) {
903
    my(@array) = $self->perform_uniq($self->create_array($val));
906
    my(@array) = $self->perform_uniq($self->create_array($val));
904
    $self->append_current("@array");
907
    $self->append_current("@array");
905
  }
908
  }
906
}
909
}
907
 
910
 
908
 
911
 
909
sub process_compound_if {
912
sub process_compound_if {
910
  my($self)   = shift;
913
  my($self)   = shift;
911
  my($str)    = shift;
914
  my($str)    = shift;
912
  my($status) = 0;
915
  my($status) = 0;
913
 
916
 
914
  if ($str =~ /\|\|/) {
917
  if ($str =~ /\|\|/) {
915
    my($ret) = 0;
918
    my($ret) = 0;
916
    foreach my $v (split(/\s*\|\|\s*/, $str)) {
919
    foreach my $v (split(/\s*\|\|\s*/, $str)) {
917
      $ret |= $self->process_compound_if($v);
920
      $ret |= $self->process_compound_if($v);
918
      if ($ret != 0) {
921
      if ($ret != 0) {
919
        return 1;
922
        return 1;
920
      }
923
      }
921
    }
924
    }
922
  }
925
  }
923
  elsif ($str =~ /\&\&/) {
926
  elsif ($str =~ /\&\&/) {
924
    my($ret) = 1;
927
    my($ret) = 1;
925
    foreach my $v (split(/\s*\&\&\s*/, $str)) {
928
    foreach my $v (split(/\s*\&\&\s*/, $str)) {
926
      $ret &&= $self->process_compound_if($v);
929
      $ret &&= $self->process_compound_if($v);
927
      if ($ret == 0) {
930
      if ($ret == 0) {
928
        return 0;
931
        return 0;
929
      }
932
      }
930
    }
933
    }
931
    $status = 1;
934
    $status = 1;
932
  }
935
  }
933
  else {
936
  else {
934
    ## See if we need to reverse the return value
937
    ## See if we need to reverse the return value
935
    my($not) = 0;
938
    my($not) = 0;
936
    if ($str =~ /^!(.*)/) {
939
    if ($str =~ /^!(.*)/) {
937
      $not = 1;
940
      $not = 1;
938
      $str = $1;
941
      $str = $1;
939
    }
942
    }
940
 
943
 
941
    ## Get the value based on the string
944
    ## Get the value based on the string
942
    my(@cmds) = ();
945
    my(@cmds) = ();
943
    my($val)  = undef;
946
    my($val)  = undef;
944
    while ($str =~ /(\w+)\((.+)\)(.*)/) {
947
    while ($str =~ /(\w+)\((.+)\)(.*)/) {
945
      if ($3 eq '') {
948
      if ($3 eq '') {
946
        push(@cmds, $1);
949
        push(@cmds, $1);
947
        $str = $2;
950
        $str = $2;
948
      }
951
      }
949
      else {
952
      else {
950
        ## If there is something trailing the closing parenthesis then
953
        ## If there is something trailing the closing parenthesis then
951
        ## the whole thing is considered a parameter to the first
954
        ## the whole thing is considered a parameter to the first
952
        ## function.
955
        ## function.
953
        last;
956
        last;
954
      }
957
      }
955
    }
958
    }
956
 
959
 
957
    if (defined $cmds[0]) {
960
    if (defined $cmds[0]) {
958
      ## Start out calling get_xxx on the string
961
      ## Start out calling get_xxx on the string
959
      my($type) = 0x01;
962
      my($type) = 0x01;
960
      my($prefix) = 'get_';
963
      my($prefix) = 'get_';
961
 
964
 
962
      $val = $str;
965
      $val = $str;
963
      foreach my $cmd (reverse @cmds) {
966
      foreach my $cmd (reverse @cmds) {
964
        if (defined $keywords{$cmd} && ($keywords{$cmd} & $type) != 0) {
967
        if (defined $keywords{$cmd} && ($keywords{$cmd} & $type) != 0) {
965
          my($func) = "$prefix$cmd";
968
          my($func) = "$prefix$cmd";
966
          $val = $self->$func($val);
969
          $val = $self->$func($val);
967
 
970
 
968
          ## Now that we have a value, we need to switch over
971
          ## Now that we have a value, we need to switch over
969
          ## to calling doif_xxx
972
          ## to calling doif_xxx
970
          $type = 0x04;
973
          $type = 0x04;
971
          $prefix = 'doif_';
974
          $prefix = 'doif_';
972
        }
975
        }
973
        else {
976
        else {
974
          $self->warning("Unable to use $cmd in if (no $prefix method).");
977
          $self->warning("Unable to use $cmd in if (no $prefix method).");
975
        }
978
        }
976
      }
979
      }
977
    }
980
    }
978
    else {
981
    else {
979
      $val = $self->get_value($str);
982
      $val = $self->get_value($str);
980
    }
983
    }
981
 
984
 
982
    ## See if any portion of the value is defined and not empty
985
    ## See if any portion of the value is defined and not empty
983
    my($ret) = 0;
986
    my($ret) = 0;
984
    if (defined $val) {
987
    if (defined $val) {
985
      if (UNIVERSAL::isa($val, 'ARRAY')) {
988
      if (UNIVERSAL::isa($val, 'ARRAY')) {
986
        foreach my $v (@$val) {
989
        foreach my $v (@$val) {
987
          if ($v ne '') {
990
          if ($v ne '') {
988
            $ret = 1;
991
            $ret = 1;
989
            last;
992
            last;
990
          }
993
          }
991
        }
994
        }
992
      }
995
      }
993
      elsif ($val ne '') {
996
      elsif ($val ne '') {
994
        $ret = 1;
997
        $ret = 1;
995
      }
998
      }
996
    }
999
    }
997
    return ($not ? !$ret : $ret);
1000
    return ($not ? !$ret : $ret);
998
  }
1001
  }
999
 
1002
 
1000
  return $status;
1003
  return $status;
1001
}
1004
}
1002
 
1005
 
1003
 
1006
 
1004
sub handle_if {
1007
sub handle_if {
1005
  my($self)   = shift;
1008
  my($self)   = shift;
1006
  my($val)    = shift;
1009
  my($val)    = shift;
1007
  my($name)   = 'endif';
1010
  my($name)   = 'endif';
1008
 
1011
 
1009
  push(@{$self->{'lstack'}}, $self->get_line_number() . " $val");
1012
  push(@{$self->{'lstack'}}, $self->get_line_number() . " $val");
1010
  if ($self->{'if_skip'}) {
1013
  if ($self->{'if_skip'}) {
1011
    push(@{$self->{'sstack'}}, "*$name");
1014
    push(@{$self->{'sstack'}}, "*$name");
1012
  }
1015
  }
1013
  else {
1016
  else {
1014
    ## Determine if we are skipping the portion of this if statement
1017
    ## Determine if we are skipping the portion of this if statement
1015
    ## $val will always be defined since we won't get into this method
1018
    ## $val will always be defined since we won't get into this method
1016
    ## without properly parsing the if statement.
1019
    ## without properly parsing the if statement.
1017
    $self->{'if_skip'} = !$self->process_compound_if($val);
1020
    $self->{'if_skip'} = !$self->process_compound_if($val);
1018
    push(@{$self->{'sstack'}}, $name);
1021
    push(@{$self->{'sstack'}}, $name);
1019
  }
1022
  }
1020
}
1023
}
1021
 
1024
 
1022
 
1025
 
1023
sub handle_else {
1026
sub handle_else {
1024
  my($self)  = shift;
1027
  my($self)  = shift;
1025
  my(@scopy) = @{$self->{'sstack'}};
1028
  my(@scopy) = @{$self->{'sstack'}};
1026
 
1029
 
1027
  if (defined $scopy[$#scopy]) {
1030
  if (defined $scopy[$#scopy]) {
1028
    my($index) = index($scopy[$#scopy], 'endif');
1031
    my($index) = index($scopy[$#scopy], 'endif');
1029
    if ($index >= 0) {
1032
    if ($index >= 0) {
1030
      if ($index == 0) {
1033
      if ($index == 0) {
1031
        $self->{'if_skip'} ^= 1;
1034
        $self->{'if_skip'} ^= 1;
1032
      }
1035
      }
1033
      $self->{'sstack'}->[$#scopy] .= ':';
1036
      $self->{'sstack'}->[$#scopy] .= ':';
1034
    }
1037
    }
1035
 
1038
 
1036
    if (($self->{'sstack'}->[$#scopy] =~ tr/:/:/) > 1) {
1039
    if (($self->{'sstack'}->[$#scopy] =~ tr/:/:/) > 1) {
1037
      return 0, 'Unmatched else';
1040
      return 0, 'Unmatched else';
1038
    }
1041
    }
1039
  }
1042
  }
1040
 
1043
 
1041
  return 1, undef;
1044
  return 1, undef;
1042
}
1045
}
1043
 
1046
 
1044
 
1047
 
1045
sub handle_foreach {
1048
sub handle_foreach {
1046
  my($self)        = shift;
1049
  my($self)        = shift;
1047
  my($val)         = shift;
1050
  my($val)         = shift;
1048
  my($name)        = 'endfor';
1051
  my($name)        = 'endfor';
1049
  my($status)      = 1;
1052
  my($status)      = 1;
1050
  my($errorString) = undef;
1053
  my($errorString) = undef;
1051
 
1054
 
1052
  push(@{$self->{'lstack'}}, $self->get_line_number());
1055
  push(@{$self->{'lstack'}}, $self->get_line_number());
1053
  if (!$self->{'if_skip'}) {
1056
  if (!$self->{'if_skip'}) {
1054
    my($vname) = undef;
1057
    my($vname) = undef;
1055
    if ($val =~ /flag_overrides\([^\)]+\)/) {
1058
    if ($val =~ /flag_overrides\([^\)]+\)/) {
1056
    }
1059
    }
1057
    elsif ($val =~ /([^,]+),(.*)/) {
1060
    elsif ($val =~ /([^,]+),(.*)/) {
1058
      $vname = $1;
1061
      $vname = $1;
1059
      $val   = $2;
1062
      $val   = $2;
1060
      $vname =~ s/^\s+//;
1063
      $vname =~ s/^\s+//;
1061
      $vname =~ s/\s+$//;
1064
      $vname =~ s/\s+$//;
1062
      $val   =~ s/^\s+//;
1065
      $val   =~ s/^\s+//;
1063
      $val   =~ s/\s+$//;
1066
      $val   =~ s/\s+$//;
1064
 
1067
 
1065
      ## Due to the way flag_overrides works, we can't allow
1068
      ## Due to the way flag_overrides works, we can't allow
1066
      ## the user to name the foreach variable when dealing
1069
      ## the user to name the foreach variable when dealing
1067
      ## with custom types.
1070
      ## with custom types.
1068
      if ($val =~ /^custom_type\->/ || $val eq 'custom_types') {
1071
      if ($val =~ /^custom_type\->/ || $val eq 'custom_types') {
1069
        $status = 0;
1072
        $status = 0;
1070
        $errorString = 'The foreach variable can not be ' .
1073
        $errorString = 'The foreach variable can not be ' .
1071
                       'named when dealing with custom types';
1074
                       'named when dealing with custom types';
1072
      }
1075
      }
1073
      elsif ($val =~ /^grouped_.*_file\->/ || $val =~ /^grouped_.*files$/) {
1076
      elsif ($val =~ /^grouped_.*_file\->/ || $val =~ /^grouped_.*files$/) {
1074
        $status = 0;
1077
        $status = 0;
1075
        $errorString = 'The foreach variable can not be ' .
1078
        $errorString = 'The foreach variable can not be ' .
1076
                       'named when dealing with grouped files';
1079
                       'named when dealing with grouped files';
1077
      }
1080
      }
1078
    }
1081
    }
1079
 
1082
 
1080
    push(@{$self->{'sstack'}}, $name);
1083
    push(@{$self->{'sstack'}}, $name);
1081
    my($index) = ++$self->{'foreach'}->{'count'};
1084
    my($index) = ++$self->{'foreach'}->{'count'};
1082
 
1085
 
1083
    $self->{'foreach'}->{'name'}->[$index]  = $vname;
1086
    $self->{'foreach'}->{'name'}->[$index]  = $vname;
1084
    $self->{'foreach'}->{'vars'}->[$index]  = $val;
1087
    $self->{'foreach'}->{'vars'}->[$index]  = $val;
1085
    $self->{'foreach'}->{'text'}->[$index]  = '';
1088
    $self->{'foreach'}->{'text'}->[$index]  = '';
1086
    $self->{'foreach'}->{'scope'}->[$index] = {};
1089
    $self->{'foreach'}->{'scope'}->[$index] = {};
1087
    $self->{'foreach'}->{'scope_name'}->[$index] = undef;
1090
    $self->{'foreach'}->{'scope_name'}->[$index] = undef;
1088
  }
1091
  }
1089
  else {
1092
  else {
1090
    push(@{$self->{'sstack'}}, "*$name");
1093
    push(@{$self->{'sstack'}}, "*$name");
1091
  }
1094
  }
1092
 
1095
 
1093
  return $status, $errorString;
1096
  return $status, $errorString;
1094
}
1097
}
1095
 
1098
 
1096
 
1099
 
1097
sub handle_special {
1100
sub handle_special {
1098
  my($self) = shift;
1101
  my($self) = shift;
1099
  my($name) = shift;
1102
  my($name) = shift;
1100
  my($val)  = shift;
1103
  my($val)  = shift;
1101
 
1104
 
1102
  ## If $name (fornotlast, forfirst, etc.) is set to 1
1105
  ## If $name (fornotlast, forfirst, etc.) is set to 1
1103
  ## Then we append the $val onto the current string that's
1106
  ## Then we append the $val onto the current string that's
1104
  ## being built.
1107
  ## being built.
1105
  if ($self->get_value($name)) {
1108
  if ($self->get_value($name)) {
1106
    $self->append_current($val);
1109
    $self->append_current($val);
1107
  }
1110
  }
1108
}
1111
}
1109
 
1112
 
1110
 
1113
 
1111
sub handle_uc {
1114
sub handle_uc {
1112
  my($self) = shift;
1115
  my($self) = shift;
1113
  my($name) = shift;
1116
  my($name) = shift;
1114
 
1117
 
1115
  $self->append_current(uc($self->get_value_with_default($name)));
1118
  $self->append_current(uc($self->get_value_with_default($name)));
1116
}
1119
}
1117
 
1120
 
1118
 
1121
 
1119
sub handle_lc {
1122
sub handle_lc {
1120
  my($self) = shift;
1123
  my($self) = shift;
1121
  my($name) = shift;
1124
  my($name) = shift;
1122
 
1125
 
1123
  $self->append_current(lc($self->get_value_with_default($name)));
1126
  $self->append_current(lc($self->get_value_with_default($name)));
1124
}
1127
}
1125
 
1128
 
1126
 
1129
 
1127
sub handle_ucw {
1130
sub handle_ucw {
1128
  my($self) = shift;
1131
  my($self) = shift;
1129
  my($name) = shift;
1132
  my($name) = shift;
1130
  my($val)  = $self->get_value_with_default($name);
1133
  my($val)  = $self->get_value_with_default($name);
1131
 
1134
 
1132
  substr($val, 0, 1) = uc(substr($val, 0, 1));
1135
  substr($val, 0, 1) = uc(substr($val, 0, 1));
1133
  while($val =~ /[_\s]([a-z])/) {
1136
  while($val =~ /[_\s]([a-z])/) {
1134
    my($uc) = uc($1);
1137
    my($uc) = uc($1);
1135
    $val =~ s/[_\s][a-z]/ $uc/;
1138
    $val =~ s/[_\s][a-z]/ $uc/;
1136
  }
1139
  }
1137
  $self->append_current($val);
1140
  $self->append_current($val);
1138
}
1141
}
1139
 
1142
 
1140
 
1143
 
1141
sub perform_normalize {
1144
sub perform_normalize {
1142
  my($self)  = shift;
1145
  my($self)  = shift;
1143
  my($value) = shift;
1146
  my($value) = shift;
1144
  $value =~ tr/\/\\\-$()./_/;
1147
  $value =~ tr/\/\\\-$()./_/;
1145
  return $value;
1148
  return $value;
1146
}
1149
}
1147
 
1150
 
1148
 
1151
 
1149
sub handle_normalize {
1152
sub handle_normalize {
1150
  my($self) = shift;
1153
  my($self) = shift;
1151
  my($name) = shift;
1154
  my($name) = shift;
1152
  my($val)  = $self->get_value_with_default($name);
1155
  my($val)  = $self->get_value_with_default($name);
1153
 
1156
 
1154
  $self->append_current($self->perform_normalize($val));
1157
  $self->append_current($self->perform_normalize($val));
1155
}
1158
}
1156
 
1159
 
1157
 
1160
 
1158
sub perform_noextension {
1161
sub perform_noextension {
1159
  my($self)  = shift;
1162
  my($self)  = shift;
1160
  my($value) = shift;
1163
  my($value) = shift;
1161
  $value =~ s/\.[^\.]+$//;
1164
  $value =~ s/\.[^\.]+$//;
1162
  return $value;
1165
  return $value;
1163
}
1166
}
1164
 
1167
 
1165
 
1168
 
1166
sub handle_noextension {
1169
sub handle_noextension {
1167
  my($self) = shift;
1170
  my($self) = shift;
1168
  my($name) = shift;
1171
  my($name) = shift;
1169
  my($val)  = $self->get_value_with_default($name);
1172
  my($val)  = $self->get_value_with_default($name);
1170
 
1173
 
1171
  $self->append_current($self->perform_noextension($val));
1174
  $self->append_current($self->perform_noextension($val));
1172
}
1175
}
1173
 
1176
 
1174
 
1177
 
1175
sub get_dirname {
1178
sub get_dirname {
1176
  my($self)  = shift;
1179
  my($self)  = shift;
1177
  my($name)  = shift;
1180
  my($name)  = shift;
1178
  my($value) = $self->get_value_with_default($name);
1181
  my($value) = $self->get_value_with_default($name);
1179
  return (defined $value ?
1182
  return (defined $value ?
1180
              $self->doif_dirname($value) : undef);
1183
              $self->doif_dirname($value) : undef);
1181
}
1184
}
1182
 
1185
 
1183
 
1186
 
1184
sub doif_dirname {
1187
sub doif_dirname {
1185
  my($self)  = shift;
1188
  my($self)  = shift;
1186
  my($value) = shift;
1189
  my($value) = shift;
1187
 
1190
 
1188
  if (defined $value) {
1191
  if (defined $value) {
1189
    $value = $self->tp_dirname($value);
1192
    $value = $self->tp_dirname($value);
1190
    return ($value ne '.');
1193
    return ($value ne '.');
1191
  }
1194
  }
1192
  return undef;
1195
  return undef;
1193
}
1196
}
1194
 
1197
 
1195
 
1198
 
1196
sub handle_dirname {
1199
sub handle_dirname {
1197
  my($self) = shift;
1200
  my($self) = shift;
1198
  my($name) = shift;
1201
  my($name) = shift;
1199
 
1202
 
1200
  if (!$self->{'if_skip'}) {
1203
  if (!$self->{'if_skip'}) {
1201
    $self->append_current(
1204
    $self->append_current(
1202
              $self->tp_dirname($self->get_value_with_default($name)));
1205
              $self->tp_dirname($self->get_value_with_default($name)));
1203
  }
1206
  }
1204
}
1207
}
1205
 
1208
 
1206
 
1209
 
1207
sub handle_basename {
1210
sub handle_basename {
1208
  my($self) = shift;
1211
  my($self) = shift;
1209
  my($name) = shift;
1212
  my($name) = shift;
1210
 
1213
 
1211
  if (!$self->{'if_skip'}) {
1214
  if (!$self->{'if_skip'}) {
1212
    $self->append_current(
1215
    $self->append_current(
1213
              $self->basename($self->get_value_with_default($name)));
1216
              $self->basename($self->get_value_with_default($name)));
1214
  }
1217
  }
1215
}
1218
}
1216
 
1219
 
1217
 
1220
 
1218
sub handle_basenoextension {
1221
sub handle_basenoextension {
1219
  my($self) = shift;
1222
  my($self) = shift;
1220
  my($name) = shift;
1223
  my($name) = shift;
1221
  my($val)  = $self->basename($self->get_value_with_default($name));
1224
  my($val)  = $self->basename($self->get_value_with_default($name));
1222
 
1225
 
1223
  $val =~ s/\.[^\.]+$//;
1226
  $val =~ s/\.[^\.]+$//;
1224
  $self->append_current($val);
1227
  $self->append_current($val);
1225
}
1228
}
1226
 
1229
 
1227
 
1230
 
1228
sub handle_flag_overrides {
1231
sub handle_flag_overrides {
1229
  my($self)  = shift;
1232
  my($self)  = shift;
1230
  my($name)  = shift;
1233
  my($name)  = shift;
1231
  my($value) = $self->get_flag_overrides($name);
1234
  my($value) = $self->get_flag_overrides($name);
1232
 
1235
 
1233
  if (defined $value) {
1236
  if (defined $value) {
1234
    $self->append_current($value);
1237
    $self->append_current($value);
1235
  }
1238
  }
1236
}
1239
}
1237
 
1240
 
1238
 
1241
 
1239
sub handle_marker {
1242
sub handle_marker {
1240
  my($self) = shift;
1243
  my($self) = shift;
1241
  my($name) = shift;
1244
  my($name) = shift;
1242
  my($val)  = $self->{'prjc'}->get_verbatim($name);
1245
  my($val)  = $self->{'prjc'}->get_verbatim($name);
1243
 
1246
 
1244
  if (defined $val) {
1247
  if (defined $val) {
1245
    $self->append_current($val);
1248
    $self->append_current($val);
1246
  }
1249
  }
1247
}
1250
}
1248
 
1251
 
1249
 
1252
 
1250
sub handle_eval {
1253
sub handle_eval {
1251
  my($self) = shift;
1254
  my($self) = shift;
1252
  my($name) = shift;
1255
  my($name) = shift;
1253
  my($val)  = $self->get_value_with_default($name);
1256
  my($val)  = $self->get_value_with_default($name);
1254
 
1257
 
1255
  if (defined $val) {
1258
  if (defined $val) {
1256
    if ($val =~ /<%eval\($name\)%>/) {
1259
    if ($val =~ /<%eval\($name\)%>/) {
1257
      $self->warning("Infinite recursion detected in '$name'.");
1260
      $self->warning("Infinite recursion detected in '$name'.");
1258
    }
1261
    }
1259
    else {
1262
    else {
1260
      ## Enter the eval state
1263
      ## Enter the eval state
1261
      ++$self->{'eval'};
1264
      ++$self->{'eval'};
1262
 
1265
 
1263
      ## Parse the eval line
1266
      ## Parse the eval line
1264
      my($status, $error) = $self->parse_line(undef, $val);
1267
      my($status, $error) = $self->parse_line(undef, $val);
1265
      if ($status) {
1268
      if ($status) {
1266
        $self->{'built'} .= $self->{'eval_str'};
1269
        $self->{'built'} .= $self->{'eval_str'};
1267
      }
1270
      }
1268
      else {
1271
      else {
1269
        $self->warning($error);
1272
        $self->warning($error);
1270
      }
1273
      }
1271
 
1274
 
1272
      ## Leave the eval state
1275
      ## Leave the eval state
1273
      --$self->{'eval'};
1276
      --$self->{'eval'};
1274
      $self->{'eval_str'} = '';
1277
      $self->{'eval_str'} = '';
1275
    }
1278
    }
1276
  }
1279
  }
1277
}
1280
}
1278
 
1281
 
1279
 
1282
 
1280
sub handle_pseudo {
1283
sub handle_pseudo {
1281
  my($self) = shift;
1284
  my($self) = shift;
1282
  my($name) = shift;
1285
  my($name) = shift;
1283
  $self->append_current($self->{'cmds'}->{$name});
1286
  $self->append_current($self->{'cmds'}->{$name});
1284
}
1287
}
1285
 
1288
 
1286
 
1289
 
1287
sub get_duplicate_index {
1290
sub get_duplicate_index {
1288
  my($self) = shift;
1291
  my($self) = shift;
1289
  my($name) = shift;
1292
  my($name) = shift;
1290
  return $self->doif_duplicate_index($self->get_value_with_default($name));
1293
  return $self->doif_duplicate_index($self->get_value_with_default($name));
1291
}
1294
}
1292
 
1295
 
1293
 
1296
 
1294
sub doif_duplicate_index {
1297
sub doif_duplicate_index {
1295
  my($self)  = shift;
1298
  my($self)  = shift;
1296
  my($value) = shift;
1299
  my($value) = shift;
1297
 
1300
 
1298
  if (defined $value) {
1301
  if (defined $value) {
1299
    my($base) = $self->basename($value);
1302
    my($base) = lc($self->basename($value));
1300
    my($path) = $self->tp_dirname($value);
1303
    my($path) = $self->tp_dirname($value);
1301
 
1304
 
1302
    if (!defined $self->{'dupfiles'}->{$base}) {
1305
    if (!defined $self->{'dupfiles'}->{$base}) {
1303
      $self->{'dupfiles'}->{$base} = [$path];
1306
      $self->{'dupfiles'}->{$base} = [$path];
1304
    }
1307
    }
1305
    else {
1308
    else {
1306
      my($index) = 1;
1309
      my($index) = 1;
1307
      foreach my $file (@{$self->{'dupfiles'}->{$base}}) {
1310
      foreach my $file (@{$self->{'dupfiles'}->{$base}}) {
1308
        if ($file eq $path) {
1311
        if ($file eq $path) {
1309
          return $index;
1312
          return $index;
1310
        }
1313
        }
1311
        ++$index;
1314
        ++$index;
1312
      }
1315
      }
1313
 
1316
 
1314
      push(@{$self->{'dupfiles'}->{$base}}, $path);
1317
      push(@{$self->{'dupfiles'}->{$base}}, $path);
1315
      return 1;
1318
      return 1;
1316
    }
1319
    }
1317
  }
1320
  }
1318
 
1321
 
1319
  return undef;
1322
  return undef;
1320
}
1323
}
1321
 
1324
 
1322
 
1325
 
1323
sub handle_duplicate_index {
1326
sub handle_duplicate_index {
1324
  my($self) = shift;
1327
  my($self) = shift;
1325
  my($name) = shift;
1328
  my($name) = shift;
1326
 
1329
 
1327
  if (!$self->{'if_skip'}) {
1330
  if (!$self->{'if_skip'}) {
1328
    my($value) = $self->doif_duplicate_index(
1331
    my($value) = $self->doif_duplicate_index(
1329
                          $self->get_value_with_default($name));
1332
                          $self->get_value_with_default($name));
1330
    if (defined $value) {
1333
    if (defined $value) {
1331
      $self->append_current($value);
1334
      $self->append_current($value);
1332
    }
1335
    }
1333
  }
1336
  }
1334
}
1337
}
1335
 
1338
 
1336
 
1339
 
1337
sub prepare_parameters {
1340
sub prepare_parameters {
1338
  my($self)   = shift;
1341
  my($self)   = shift;
1339
  my($prefix) = shift;
1342
  my($prefix) = shift;
1340
  my($input)  = $self->get_value($prefix . '->input_file');
1343
  my($input)  = $self->get_value($prefix . '->input_file');
1341
  my($output) = undef;
1344
  my($output) = undef;
1342
 
1345
 
1343
  if (defined $input) {
1346
  if (defined $input) {
1344
    if ($self->{'cslashes'}) {
1347
    if ($self->{'cslashes'}) {
1345
      $input = $self->{'prjc'}->slash_to_backslash($input);
1348
      $input = $self->{'prjc'}->slash_to_backslash($input);
1346
    }
1349
    }
1347
    $output = $self->get_value($prefix . '->input_file->output_files');
1350
    $output = $self->get_value($prefix . '->input_file->output_files');
1348
 
1351
 
1349
    if (defined $output) {
1352
    if (defined $output) {
1350
      my($size) = scalar(@$output);
1353
      my($size) = scalar(@$output);
1351
      for(my $i = 0; $i < $size; ++$i) {
1354
      for(my $i = 0; $i < $size; ++$i) {
1352
        my($fo) = $self->get_flag_overrides($prefix . '->input_file, gendir');
1355
        my($fo) = $self->get_flag_overrides($prefix . '->input_file, gendir');
1353
        if (defined $fo) {
1356
        if (defined $fo) {
1354
          $$output[$i] = $fo . '/' . File::Basename::basename($$output[$i]);
1357
          $$output[$i] = $fo . '/' . File::Basename::basename($$output[$i]);
1355
        }
1358
        }
1356
        if ($self->{'cslashes'}) {
1359
        if ($self->{'cslashes'}) {
1357
          $$output[$i] = $self->{'prjc'}->slash_to_backslash($$output[$i]);
1360
          $$output[$i] = $self->{'prjc'}->slash_to_backslash($$output[$i]);
1358
        }
1361
        }
1359
      }
1362
      }
1360
    }
1363
    }
1361
  }
1364
  }
1362
 
1365
 
1363
  ## Set the parameters array with the determined input and output files
1366
  ## Set the parameters array with the determined input and output files
1364
  return $input, $output;
1367
  return $input, $output;
1365
}
1368
}
1366
 
1369
 
1367
 
1370
 
1368
sub process_name {
1371
sub process_name {
1369
  my($self)        = shift;
1372
  my($self)        = shift;
1370
  my($line)        = shift;
1373
  my($line)        = shift;
1371
  my($length)      = 0;
1374
  my($length)      = 0;
1372
  my($status)      = 1;
1375
  my($status)      = 1;
1373
  my($errorString) = undef;
1376
  my($errorString) = undef;
1374
 
1377
 
1375
  if ($line eq '') {
1378
  if ($line eq '') {
1376
  }
1379
  }
1377
  elsif ($line =~ /^\w+(\(([^\)]+|\".*\"|[!]?(\w+\s*,\s*)?\w+\(.+\))\)|\->\w+([\w\-\>]+)?)?%>/) {
1380
  elsif ($line =~ /^\w+(\(([^\)]+|\".*\"|[!]?(\w+\s*,\s*)?\w+\(.+\))\)|\->\w+([\w\-\>]+)?)?%>/) {
1378
    ## Split the line into a name and value
1381
    ## Split the line into a name and value
1379
    my($name, $val) = ();
1382
    my($name, $val) = ();
1380
    if ($line =~ /([^%\(]+)(\(([^%]+)\))?%>/) {
1383
    if ($line =~ /([^%\(]+)(\(([^%]+)\))?%>/) {
1381
      $name = lc($1);
1384
      $name = lc($1);
1382
      $val  = $3;
1385
      $val  = $3;
1383
    }
1386
    }
1384
 
1387
 
1385
    $length += length($name);
1388
    $length += length($name);
1386
    if (defined $val) {
1389
    if (defined $val) {
1387
      ## Check for the parenthesis
1390
      ## Check for the parenthesis
1388
      if (($val =~ tr/(//) != ($val =~ tr/)//)) {
1391
      if (($val =~ tr/(//) != ($val =~ tr/)//)) {
1389
        $status = 0;
1392
        $status = 0;
1390
        $errorString = 'Missing the closing parenthesis';
1393
        $errorString = 'Missing the closing parenthesis';
1391
      }
1394
      }
1392
 
1395
 
1393
      ## Add the length of the value plus 2 for the surrounding ()
1396
      ## Add the length of the value plus 2 for the surrounding ()
1394
      $length += length($val) + 2;
1397
      $length += length($val) + 2;
1395
    }
1398
    }
1396
 
1399
 
1397
    if ($status) {
1400
    if ($status) {
1398
      if (defined $keywords{$name}) {
1401
      if (defined $keywords{$name}) {
1399
        if ($name eq 'endif') {
1402
        if ($name eq 'endif') {
1400
          ($status, $errorString) = $self->handle_endif($name);
1403
          ($status, $errorString) = $self->handle_endif($name);
1401
        }
1404
        }
1402
        elsif ($name eq 'if') {
1405
        elsif ($name eq 'if') {
1403
          $self->handle_if($val);
1406
          $self->handle_if($val);
1404
        }
1407
        }
1405
        elsif ($name eq 'endfor') {
1408
        elsif ($name eq 'endfor') {
1406
          ($status, $errorString) = $self->handle_endfor($name);
1409
          ($status, $errorString) = $self->handle_endfor($name);
1407
        }
1410
        }
1408
        elsif ($name eq 'foreach') {
1411
        elsif ($name eq 'foreach') {
1409
          ($status, $errorString) = $self->handle_foreach($val);
1412
          ($status, $errorString) = $self->handle_foreach($val);
1410
        }
1413
        }
1411
        elsif ($name eq 'fornotlast'  || $name eq 'forlast' ||
1414
        elsif ($name eq 'fornotlast'  || $name eq 'forlast' ||
1412
               $name eq 'fornotfirst' || $name eq 'forfirst') {
1415
               $name eq 'fornotfirst' || $name eq 'forfirst') {
1413
          if (!$self->{'if_skip'}) {
1416
          if (!$self->{'if_skip'}) {
1414
            $self->handle_special($name, $self->process_special($val));
1417
            $self->handle_special($name, $self->process_special($val));
1415
          }
1418
          }
1416
        }
1419
        }
1417
        elsif ($name eq 'else') {
1420
        elsif ($name eq 'else') {
1418
          ($status, $errorString) = $self->handle_else();
1421
          ($status, $errorString) = $self->handle_else();
1419
        }
1422
        }
1420
        elsif ($name eq 'comment') {
1423
        elsif ($name eq 'comment') {
1421
          ## Ignore the contents of the comment
1424
          ## Ignore the contents of the comment
1422
        }
1425
        }
1423
        else {
1426
        else {
1424
          if (!$self->{'if_skip'}) {
1427
          if (!$self->{'if_skip'}) {
1425
            my($func) = 'handle_' . $name;
1428
            my($func) = 'handle_' . $name;
1426
            $self->$func($val);
1429
            $self->$func($val);
1427
          }
1430
          }
1428
        }
1431
        }
1429
      }
1432
      }
1430
      elsif (defined $self->{'cmds'}->{$name}) {
1433
      elsif (defined $self->{'cmds'}->{$name}) {
1431
        if (!$self->{'if_skip'}) {
1434
        if (!$self->{'if_skip'}) {
1432
          $self->handle_pseudo($name);
1435
          $self->handle_pseudo($name);
1433
        }
1436
        }
1434
      }
1437
      }
1435
      else {
1438
      else {
1436
        if (!$self->{'if_skip'}) {
1439
        if (!$self->{'if_skip'}) {
1437
          if (defined $val && !defined $self->{'defaults'}->{$name}) {
1440
          if (defined $val && !defined $self->{'defaults'}->{$name}) {
1438
            $self->{'defaults'}->{$name} = $self->process_special($val);
1441
            $self->{'defaults'}->{$name} = $self->process_special($val);
1439
          }
1442
          }
1440
          $self->append_current($self->get_value_with_default($name));
1443
          $self->append_current($self->get_value_with_default($name));
1441
        }
1444
        }
1442
      }
1445
      }
1443
    }
1446
    }
1444
  }
1447
  }
1445
  else {
1448
  else {
1446
    my($error)  = $line;
1449
    my($error)  = $line;
1447
    my($length) = length($line);
1450
    my($length) = length($line);
1448
    for(my $i = 0; $i < $length; ++$i) {
1451
    for(my $i = 0; $i < $length; ++$i) {
1449
      my($part) = substr($line, $i, 2);
1452
      my($part) = substr($line, $i, 2);
1450
      if ($part eq '%>') {
1453
      if ($part eq '%>') {
1451
        $error = substr($line, 0, $i + 2);
1454
        $error = substr($line, 0, $i + 2);
1452
        last;
1455
        last;
1453
      }
1456
      }
1454
    }
1457
    }
1455
    $status = 0;
1458
    $status = 0;
1456
    $errorString = "Unable to parse line starting at '$error'";
1459
    $errorString = "Unable to parse line starting at '$error'";
1457
  }
1460
  }
1458
 
1461
 
1459
  return $status, $errorString, $length;
1462
  return $status, $errorString, $length;
1460
}
1463
}
1461
 
1464
 
1462
 
1465
 
1463
sub collect_data {
1466
sub collect_data {
1464
  my($self)  = shift;
1467
  my($self)  = shift;
1465
  my($prjc)  = $self->{'prjc'};
1468
  my($prjc)  = $self->{'prjc'};
1466
  my($cwd)   = $self->getcwd();
1469
  my($cwd)   = $self->getcwd();
1467
 
1470
 
1468
  ## Set the current working directory
1471
  ## Set the current working directory
1469
  if ($self->{'cslashes'}) {
1472
  if ($self->{'cslashes'}) {
1470
    $cwd = $prjc->slash_to_backslash($cwd);
1473
    $cwd = $prjc->slash_to_backslash($cwd);
1471
  }
1474
  }
1472
  $self->{'values'}->{'cwd'} = $cwd;
1475
  $self->{'values'}->{'cwd'} = $cwd;
1473
 
1476
 
1474
  ## Collect the components into {'values'} somehow
1477
  ## Collect the components into {'values'} somehow
1475
  foreach my $key (keys %{$prjc->{'valid_components'}}) {
1478
  foreach my $key (keys %{$prjc->{'valid_components'}}) {
1476
    my(@list) = $prjc->get_component_list($key);
1479
    my(@list) = $prjc->get_component_list($key);
1477
    if (defined $list[0]) {
1480
    if (defined $list[0]) {
1478
      $self->{'values'}->{$key} = \@list;
1481
      $self->{'values'}->{$key} = \@list;
1479
    }
1482
    }
1480
  }
1483
  }
1481
 
1484
 
1482
  ## If there is a staticname and no sharedname then this project
1485
  ## If there is a staticname and no sharedname then this project
1483
  ## 'type_is_static'.  If we are generating static projects, let
1486
  ## 'type_is_static'.  If we are generating static projects, let
1484
  ## all of the templates know that we 'need_staticflags'.
1487
  ## all of the templates know that we 'need_staticflags'.
1485
  ## If there is a sharedname then this project 'type_is_dynamic'.
1488
  ## If there is a sharedname then this project 'type_is_dynamic'.
1486
  my($sharedname) = $prjc->get_assignment('sharedname');
1489
  my($sharedname) = $prjc->get_assignment('sharedname');
1487
  my($staticname) = $prjc->get_assignment('staticname');
1490
  my($staticname) = $prjc->get_assignment('staticname');
1488
  if (!defined $sharedname && defined $staticname) {
1491
  if (!defined $sharedname && defined $staticname) {
1489
    $self->{'override_target_type'} = 1;
1492
    $self->{'override_target_type'} = 1;
1490
    $self->{'values'}->{'type_is_static'}   = 1;
1493
    $self->{'values'}->{'type_is_static'}   = 1;
1491
    $self->{'values'}->{'need_staticflags'} = 1;
1494
    $self->{'values'}->{'need_staticflags'} = 1;
1492
  }
1495
  }
1493
  elsif ($prjc->get_static() == 1) {
1496
  elsif ($prjc->get_static() == 1) {
1494
    $self->{'values'}->{'need_staticflags'} = 1;
1497
    $self->{'values'}->{'need_staticflags'} = 1;
1495
  }
1498
  }
1496
  elsif (defined $sharedname) {
1499
  elsif (defined $sharedname) {
1497
    $self->{'values'}->{'type_is_dynamic'} = 1;
1500
    $self->{'values'}->{'type_is_dynamic'} = 1;
1498
  }
1501
  }
1499
 
1502
 
1500
  ## If there is a sharedname or exename then this project
1503
  ## If there is a sharedname or exename then this project
1501
  ## 'type_is_binary'.
1504
  ## 'type_is_binary'.
1502
  if (defined $sharedname ||
1505
  if (defined $sharedname ||
1503
      defined $prjc->get_assignment('exename')) {
1506
      defined $prjc->get_assignment('exename')) {
1504
    $self->{'values'}->{'type_is_binary'} = 1;
1507
    $self->{'values'}->{'type_is_binary'} = 1;
1505
  }
1508
  }
1506
 
1509
 
1507
  ## A tiny hack (mainly for VC6 projects)
1510
  ## A tiny hack (mainly for VC6 projects)
1508
  ## for the workspace creator.  It needs to know the
1511
  ## for the workspace creator.  It needs to know the
1509
  ## target names to match up with the project name.
1512
  ## target names to match up with the project name.
1510
  $prjc->update_project_info($self, 0, ['project_name']);
1513
  $prjc->update_project_info($self, 0, ['project_name']);
1511
 
1514
 
1512
  ## This is for all projects
1515
  ## This is for all projects
1513
  $prjc->update_project_info($self, 1, ['after']);
1516
  $prjc->update_project_info($self, 1, ['after']);
1514
 
1517
 
1515
  ## VC7 Projects need to know the GUID.
1518
  ## VC7 Projects need to know the GUID.
1516
  ## We need to save this value in our known values
1519
  ## We need to save this value in our known values
1517
  ## since each guid generated will be different.  We need
1520
  ## since each guid generated will be different.  We need
1518
  ## this to correspond to the same guid used in the workspace.
1521
  ## this to correspond to the same guid used in the workspace.
1519
  my($guid) = $prjc->update_project_info($self, 1, ['guid']);
1522
  my($guid) = $prjc->update_project_info($self, 1, ['guid']);
1520
  $self->{'values'}->{'guid'} = $guid;
1523
  $self->{'values'}->{'guid'} = $guid;
1521
 
1524
 
1522
  ## Some Windows based projects can't deal with certain version
1525
  ## Some Windows based projects can't deal with certain version
1523
  ## values.  So, for those we provide a translated version.
1526
  ## values.  So, for those we provide a translated version.
1524
  my($version) = $prjc->get_assignment('version');
1527
  my($version) = $prjc->get_assignment('version');
1525
  if (defined $version) {
1528
  if (defined $version) {
1526
    $self->{'values'}->{'win_version'} =
1529
    $self->{'values'}->{'win_version'} =
1527
                        WinVersionTranslator::translate($version);
1530
                        WinVersionTranslator::translate($version);
1528
  }
1531
  }
1529
}
1532
}
1530
 
1533
 
1531
 
1534
 
1532
sub parse_line {
1535
sub parse_line {
1533
  my($self)        = shift;
1536
  my($self)        = shift;
1534
  my($ih)          = shift;
1537
  my($ih)          = shift;
1535
  my($line)        = shift;
1538
  my($line)        = shift;
1536
  my($status)      = 1;
1539
  my($status)      = 1;
1537
  my($errorString) = undef;
1540
  my($errorString) = undef;
1538
  my($startempty)  = (length($line) == 0 ? 1 : 0);
1541
  my($startempty)  = (length($line) == 0 ? 1 : 0);
1539
 
1542
 
1540
  ## If processing a foreach or the line only
1543
  ## If processing a foreach or the line only
1541
  ## contains a keyword, then we do
1544
  ## contains a keyword, then we do
1542
  ## not need to add a newline to the end.
1545
  ## not need to add a newline to the end.
1543
  if (!$self->{'eval'} && $self->{'foreach'}->{'processing'} == 0) {
1546
  if (!$self->{'eval'} && $self->{'foreach'}->{'processing'} == 0) {
1544
    if ($line !~ /^[ ]*<%(\w+)(\(((\w+\s*,\s*)?\w+\(.+\)|[^\)]+)\))?%>$/ ||
1547
    if ($line !~ /^[ ]*<%(\w+)(\(((\w+\s*,\s*)?\w+\(.+\)|[^\)]+)\))?%>$/ ||
1545
        !defined $keywords{$1}) {
1548
        !defined $keywords{$1}) {
1546
      $line .= $self->{'crlf'};
1549
      $line .= $self->{'crlf'};
1547
    }
1550
    }
1548
  }
1551
  }
1549
 
1552
 
1550
  if (!$self->{'eval'} && $self->{'foreach'}->{'count'} < 0) {
1553
  if (!$self->{'eval'} && $self->{'foreach'}->{'count'} < 0) {
1551
    $self->{'built'} = '';
1554
    $self->{'built'} = '';
1552
  }
1555
  }
1553
 
1556
 
1554
  my($start) = index($line, '<%');
1557
  my($start) = index($line, '<%');
1555
  if ($start >= 0) {
1558
  if ($start >= 0) {
1556
    my($append_name) = 0;
1559
    my($append_name) = 0;
1557
    if ($start > 0) {
1560
    if ($start > 0) {
1558
      if (!$self->{'if_skip'}) {
1561
      if (!$self->{'if_skip'}) {
1559
        $self->append_current(substr($line, 0, $start));
1562
        $self->append_current(substr($line, 0, $start));
1560
      }
1563
      }
1561
      $line = substr($line, $start);
1564
      $line = substr($line, $start);
1562
    }
1565
    }
1563
    foreach my $item (split('<%', $line)) {
1566
    foreach my $item (split('<%', $line)) {
1564
      my($name)   = 1;
1567
      my($name)   = 1;
1565
      my($length) = length($item);
1568
      my($length) = length($item);
1566
      for(my $i = 0; $i < $length; ++$i) {
1569
      for(my $i = 0; $i < $length; ++$i) {
1567
        my($part) = substr($item, $i, 2);
1570
        my($part) = substr($item, $i, 2);
1568
        if ($part eq '%>') {
1571
        if ($part eq '%>') {
1569
          ++$i;
1572
          ++$i;
1570
          $name = 0;
1573
          $name = 0;
1571
          if ($append_name) {
1574
          if ($append_name) {
1572
            $append_name = 0;
1575
            $append_name = 0;
1573
            if (!$self->{'if_skip'}) {
1576
            if (!$self->{'if_skip'}) {
1574
              $self->append_current($part);
1577
              $self->append_current($part);
1575
            }
1578
            }
1576
          }
1579
          }
1577
          if ($length != $i + 1) {
1580
          if ($length != $i + 1) {
1578
            if (!$self->{'if_skip'}) {
1581
            if (!$self->{'if_skip'}) {
1579
              $self->append_current(substr($item, $i + 1));
1582
              $self->append_current(substr($item, $i + 1));
1580
            }
1583
            }
1581
            last;
1584
            last;
1582
          }
1585
          }
1583
        }
1586
        }
1584
        elsif ($name) {
1587
        elsif ($name) {
1585
          my($substr)  = substr($item, $i);
1588
          my($substr)  = substr($item, $i);
1586
          my($efcheck) = ($substr =~ /^endfor\%\>/);
1589
          my($efcheck) = ($substr =~ /^endfor\%\>/);
1587
          my($focheck) = ($efcheck ? 0 : ($substr =~ /^foreach\(/));
1590
          my($focheck) = ($efcheck ? 0 : ($substr =~ /^foreach\(/));
1588
 
1591
 
1589
          if ($focheck && $self->{'foreach'}->{'count'} >= 0) {
1592
          if ($focheck && $self->{'foreach'}->{'count'} >= 0) {
1590
            ++$self->{'foreach'}->{'nested'};
1593
            ++$self->{'foreach'}->{'nested'};
1591
          }
1594
          }
1592
 
1595
 
1593
          if ($self->{'foreach'}->{'count'} < 0 ||
1596
          if ($self->{'foreach'}->{'count'} < 0 ||
1594
              $self->{'foreach'}->{'processing'} > $self->{'foreach'}->{'nested'} ||
1597
              $self->{'foreach'}->{'processing'} > $self->{'foreach'}->{'nested'} ||
1595
              (($efcheck || $focheck) &&
1598
              (($efcheck || $focheck) &&
1596
               $self->{'foreach'}->{'nested'} == $self->{'foreach'}->{'processing'})) {
1599
               $self->{'foreach'}->{'nested'} == $self->{'foreach'}->{'processing'})) {
1597
            my($nlen) = 0;
1600
            my($nlen) = 0;
1598
            ($status,
1601
            ($status,
1599
             $errorString,
1602
             $errorString,
1600
             $nlen) = $self->process_name($substr);
1603
             $nlen) = $self->process_name($substr);
1601
 
1604
 
1602
            if ($status && $nlen == 0) {
1605
            if ($status && $nlen == 0) {
1603
              $errorString = "Could not parse this line at column $i";
1606
              $errorString = "Could not parse this line at column $i";
1604
              $status = 0;
1607
              $status = 0;
1605
            }
1608
            }
1606
            if (!$status) {
1609
            if (!$status) {
1607
              last;
1610
              last;
1608
            }
1611
            }
1609
 
1612
 
1610
            $i += ($nlen - 1);
1613
            $i += ($nlen - 1);
1611
          }
1614
          }
1612
          else  {
1615
          else  {
1613
            $name = 0;
1616
            $name = 0;
1614
            if (!$self->{'if_skip'}) {
1617
            if (!$self->{'if_skip'}) {
1615
              $self->append_current('<%' . substr($item, $i, 1));
1618
              $self->append_current('<%' . substr($item, $i, 1));
1616
              $append_name = 1;
1619
              $append_name = 1;
1617
            }
1620
            }
1618
          }
1621
          }
1619
 
1622
 
1620
          if ($efcheck && $self->{'foreach'}->{'nested'} > 0) {
1623
          if ($efcheck && $self->{'foreach'}->{'nested'} > 0) {
1621
            --$self->{'foreach'}->{'nested'};
1624
            --$self->{'foreach'}->{'nested'};
1622
          }
1625
          }
1623
        }
1626
        }
1624
        else {
1627
        else {
1625
          if (!$self->{'if_skip'}) {
1628
          if (!$self->{'if_skip'}) {
1626
            $self->append_current(substr($item, $i, 1));
1629
            $self->append_current(substr($item, $i, 1));
1627
          }
1630
          }
1628
        }
1631
        }
1629
      }
1632
      }
1630
    }
1633
    }
1631
  }
1634
  }
1632
  else {
1635
  else {
1633
    if (!$self->{'if_skip'}) {
1636
    if (!$self->{'if_skip'}) {
1634
      $self->append_current($line);
1637
      $self->append_current($line);
1635
    }
1638
    }
1636
  }
1639
  }
1637
 
1640
 
1638
  if (!$self->{'eval'} && $self->{'foreach'}->{'count'} < 0) {
1641
  if (!$self->{'eval'} && $self->{'foreach'}->{'count'} < 0) {
1639
    ## If the line started out empty and we're not
1642
    ## If the line started out empty and we're not
1640
    ## skipping from the start or the built up line is not empty
1643
    ## skipping from the start or the built up line is not empty
1641
    if ($startempty ||
1644
    if ($startempty ||
1642
        ($self->{'built'} ne $self->{'crlf'} && $self->{'built'} ne '')) {
1645
        ($self->{'built'} ne $self->{'crlf'} && $self->{'built'} ne '')) {
1643
      push(@{$self->{'lines'}}, $self->{'built'});
1646
      push(@{$self->{'lines'}}, $self->{'built'});
1644
    }
1647
    }
1645
  }
1648
  }
1646
 
1649
 
1647
  return $status, $errorString;
1650
  return $status, $errorString;
1648
}
1651
}
1649
 
1652
 
1650
 
1653
 
1651
sub parse_file {
1654
sub parse_file {
1652
  my($self)  = shift;
1655
  my($self)  = shift;
1653
  my($input) = shift;
1656
  my($input) = shift;
1654
 
1657
 
1655
  $self->collect_data();
1658
  $self->collect_data();
1656
  my($status, $errorString) = $self->cached_file_read($input);
1659
  my($status, $errorString) = $self->cached_file_read($input);
1657
 
1660
 
1658
  if ($status) {
1661
  if ($status) {
1659
    my($sstack) = $self->{'sstack'};
1662
    my($sstack) = $self->{'sstack'};
1660
    if (defined $$sstack[0]) {
1663
    if (defined $$sstack[0]) {
1661
      my($lstack) = $self->{'lstack'};
1664
      my($lstack) = $self->{'lstack'};
1662
      $status = 0;
1665
      $status = 0;
1663
      $errorString = "Missing an '$$sstack[0]' starting at $$lstack[0]";
1666
      $errorString = "Missing an '$$sstack[0]' starting at $$lstack[0]";
1664
    }
1667
    }
1665
  }
1668
  }
1666
 
1669
 
1667
  if (!$status) {
1670
  if (!$status) {
1668
    my($linenumber) = $self->get_line_number();
1671
    my($linenumber) = $self->get_line_number();
1669
    $errorString = "$input: line $linenumber:\n$errorString";
1672
    $errorString = "$input: line $linenumber:\n$errorString";
1670
  }
1673
  }
1671
 
1674
 
1672
  return $status, $errorString;
1675
  return $status, $errorString;
1673
}
1676
}
1674
 
1677
 
1675
 
1678
 
1676
sub get_lines {
1679
sub get_lines {
1677
  my($self) = shift;
1680
  my($self) = shift;
1678
  return $self->{'lines'};
1681
  return $self->{'lines'};
1679
}
1682
}
1680
 
1683
 
1681
 
1684
 
1682
1;
1685
1;
1683
 
1686