⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 templateparser.pm

📁 这是广泛使用的通信开源项目,对于大容量,高并发的通讯要求完全能够胜任,他广泛可用于网络游戏医学图像网关的高qos要求.更详细的内容可阅读相应的材料
💻 PM
📖 第 1 页 / 共 2 页
字号:
package TemplateParser;

# ************************************************************
# Description   : Parses the template and fills in missing values
# Author        : Chad Elliott
# Create Date   : 5/17/2002
# ************************************************************

# ************************************************************
# Pragmas
# ************************************************************

use strict;

use Parser;

use vars qw(@ISA);
@ISA = qw(Parser);

# ************************************************************
# Data Section
# ************************************************************

my(%keywords) = ('if'              => 1,
                 'else'            => 1,
                 'endif'           => 1,
                 'noextension'     => 1,
                 'dirname'         => 1,
                 'basename'        => 1,
                 'basenoextension' => 1,
                 'foreach'         => 1,
                 'forfirst'        => 1,
                 'fornotfirst'     => 1,
                 'fornotlast'      => 1,
                 'forlast'         => 1,
                 'endfor'          => 1,
                 'comment'         => 1,
                 'flag_overrides'  => 1,
                 'marker'          => 1,
                 'uc'              => 1,
                 'lc'              => 1,
                );

# ************************************************************
# Subroutine Section
# ************************************************************

sub new {
  my($class) = shift;
  my($prjc)  = shift;
  my($self)  = Parser::new($class);

  $self->{'prjc'}     = $prjc;
  $self->{'ti'}       = $prjc->get_template_input();
  $self->{'cslashes'} = $prjc->convert_slashes();
  $self->{'addtemp'}  = $prjc->get_addtemp();
  $self->{'crlf'}     = $prjc->crlf();
  $self->{'clen'}     = length($self->{'crlf'});
  $self->{'values'}   = {};
  $self->{'defaults'} = {};
  $self->{'lines'}    = [];
  $self->{'built'}    = '';
  $self->{'sstack'}   = [];
  $self->{'lstack'}   = [];
  $self->{'if_skip'}  = 0;

  $self->{'foreach'}  = {};
  $self->{'foreach'}->{'count'}      = -1;
  $self->{'foreach'}->{'nested'}     = 0;
  $self->{'foreach'}->{'name'}       = [];
  $self->{'foreach'}->{'names'}      = [];
  $self->{'foreach'}->{'text'}       = [];
  $self->{'foreach'}->{'scope'}      = [];
  $self->{'foreach'}->{'temp_scope'} = [];
  $self->{'foreach'}->{'processing'} = 0;

  return $self;
}


sub basename {
  my($self) = shift;
  my($file) = shift;
  for(my $i = length($file) - 1; $i >= 0; --$i) {
    my($ch) = substr($file, $i, 1);
    if ($ch eq '/' || $ch eq '\\') {
      ## The template file may use this value (<%basename_found%>)
      ## to determine whether a basename removed the directory or not
      $self->{'values'}->{'basename_found'} = 1;
      return substr($file, $i + 1);
    }
  }
  delete $self->{'values'}->{'basename_found'};
  return $file;
}


sub dirname {
  my($self) = shift;
  my($file) = shift;
  for(my $i = length($file) - 1; $i != 0; --$i) {
    my($ch) = substr($file, $i, 1);
    if ($ch eq '/' || $ch eq '\\') {
      ## The template file may use this value (<%dirname_found%>)
      ## to determine whether a dirname removed the basename or not
      $self->{'values'}->{'dirname_found'} = 1;
      return substr($file, 0, $i);
    }
  }
  delete $self->{'values'}->{'dirname_found'};
  return '.';
}


sub strip_line {
  my($self) = shift;
  my($line) = shift;

  ## Override strip_line() from Parser.
  ## We need to preserve leading space and
  ## there is no comment string in templates.
  ++$self->{'line_number'};
  $line =~ s/\s+$//;

  return $line;
}


## Append the current value to the line that is being
## built.  This line may be a foreach line or a general
## line without a foreach.
sub append_current {
  my($self)  = shift;
  my($value) = shift;
  my($index) = $self->{'foreach'}->{'count'};

  if ($index >= 0) {
    $self->{'foreach'}->{'text'}->[$index] .= $value;
  }
  else {
    $self->{'built'} .= $value;
  }
}


sub adjust_value {
  my($self)  = shift;
  my($name)  = shift;
  my($value) = shift;

  ## Perform any additions, subtractions
  ## or overrides for the template values.
  my($addtemp) = $self->{'addtemp'};
  foreach my $at (keys %$addtemp) {
    if ($at eq $name) {
      my($val) = $$addtemp{$at};
      if ($$val[0] > 0) {
        if (UNIVERSAL::isa($value, 'ARRAY')) {
          $value = [ $$val[1], @$value ];
        }
        else {
          $value = "$$val[1] $value";
        }
      }
      elsif ($$val[0] < 0) {
        my($parts) = undef;
        if (UNIVERSAL::isa($value, 'ARRAY')) {
          my(@copy) = @$value;
          $parts = \@copy;
        }
        else {
          $parts = $self->create_array($value);
        }

        $value = '';
        foreach my $part (@$parts) {
          if ($part ne $$val[1] && $part ne '') {
            $value .= "$part ";
          }
        }
        $value =~ s/^\s+//;
        $value =~ s/\s+$//;
      }
      else {
        $value = $$val[1];
      }
    }
  }

  return $value;
}


sub set_current_values {
  my($self) = shift;
  my($name) = shift;
  my($set)  = 0;

  ## If any value within a foreach matches the name
  ## of a hash table within the template input we will
  ## set the values of that hash table in the current scope
  if (defined $self->{'ti'}) {
    my($counter) = $self->{'foreach'}->{'count'};
    if ($counter >= 0) {
      my($value) = $self->{'ti'}->get_value($name);
      if (defined $value && UNIVERSAL::isa($value, 'HASH')) {
        my(%copy) = ();
        foreach my $key (keys %$value) {
          $copy{$key} = $self->adjust_value($key, $$value{$key});
        }
        $self->{'foreach'}->{'temp_scope'}->[$counter] = \%copy;
        $set = 1;
      }
    }
  }
  return $set;
}


sub get_nested_value {
  my($self)  = shift;
  my($name)  = shift;
  my($value) = undef;

  if ($name =~ /^(.*)\->(\w+)/) {
    my($pre)  = $1;
    my($post) = $2;
    my($base) = $self->get_value($pre);
    if (defined $base) {
      $value = $self->{'prjc'}->get_special_value($pre, $post, $base);
    }
  }

  return $value;
}


sub get_value {
  my($self)    = shift;
  my($name)    = shift;
  my($value)   = undef;
  my($counter) = $self->{'foreach'}->{'count'};

  ## First, check the temporary scope (set inside a foreach)
  if ($counter >= 0) {
    while(!defined $value && $counter >= 0) {
      $value = $self->{'foreach'}->{'temp_scope'}->[$counter]->{$name};
      --$counter;
    }
    $counter = $self->{'foreach'}->{'count'};
  }

  if (!defined $value) {
    ## Next, check for a template value
    if (defined $self->{'ti'}) {
      $value = $self->{'ti'}->get_value($name);
      if (defined $value) {
        $value = $self->adjust_value($name, $value);
      }
    }

    if (!defined $value) {
      ## Next, check the inner to outer foreach
      ## scopes for overriding values
      while(!defined $value && $counter >= 0) {
        $value = $self->{'foreach'}->{'scope'}->[$counter]->{$name};
        --$counter;
      }

      ## Then get the value from the project creator
      if (!defined $value) {
        $value = $self->{'prjc'}->get_assignment($name);

        ## Then get it from our known values
        if (!defined $value) {
          $value = $self->{'values'}->{$name};
          if (!defined $value) {
            ## Call back onto the project creator to allow
            ## it to fill in the value before defaulting to undef.
            $value = $self->{'prjc'}->fill_value($name);
            if (!defined $value && $name =~ /\->/) {
              $value = $self->get_nested_value($name);
            }
          }
        }
      }
    }
  }

  return $self->{'prjc'}->relative($value);
}


sub get_value_with_default {
  my($self)  = shift;
  my($name)  = shift;
  my($value) = $self->get_value($name);

  if (defined $value) {
    if (UNIVERSAL::isa($value, 'ARRAY')) {
      $value = "@$value";
    }
  }
  else {
    $value = $self->{'defaults'}->{$name};
    if (!defined $value) {
#      print "DEBUG: WARNING: $name defaulting to empty string\n";
      $value = '';
    }
    else {
#      print "DEBUG: WARNING: $name using default value of $value\n";
      $value = $self->adjust_value($name, $value);
    }
    $value = $self->{'prjc'}->relative($value);
  }

  return $value;
}


sub process_foreach {
  my($self)   = shift;
  my($index)  = $self->{'foreach'}->{'count'};
  my($text)   = $self->{'foreach'}->{'text'}->[$index];
  my($status) = 1;
  my($errorString) = '';
  my(@values) = ();
  my($names)  = $self->create_array($self->{'foreach'}->{'names'}->[$index]);
  my($name)   = $self->{'foreach'}->{'name'}->[$index];

  foreach my $n (@$names) {
    my($vals) = $self->get_value($n);
    if (defined $vals && $vals ne '') {
      if (!UNIVERSAL::isa($vals, 'ARRAY')) {
        $vals = $self->create_array($vals);
      }
      push(@values, @$vals);
    }
    if (!defined $name) {
      $name = $n;
      $name =~ s/s$//;
    }
  }

  ## Reset the text (it will be regenerated by calling parse_line
  $self->{'foreach'}->{'text'}->[$index] = '';

  if (defined $values[0]) {
    my($scope) = $self->{'foreach'}->{'scope'}->[$index];

    $$scope{'forlast'}     = 0;
    $$scope{'fornotlast'}  = 1;
    $$scope{'forfirst'}    = 1;
    $$scope{'fornotfirst'} = 0;

    ## If the foreach values are mixed (HASH and SCALAR), then
    ## remove the SCALAR values.
    my($pset) = undef;
    for(my $i = 0; $i <= $#values; ++$i) {
      my($set) = $self->set_current_values($values[$i]);
      if (!defined $pset) {
        $pset |= $set;
      }
      else {
        if ($pset && !$set) {
          splice(@values, $i, 1);
          $i = 0;
          $pset = undef;
        }
      }
    }

    for(my $i = 0; $i <= $#values; ++$i) {
      my($value) = $values[$i];

      ## Set the corresponding values in the temporary scope
      $self->set_current_values($value);

      ## Set the special values that only exist
      ## within a foreach
      if ($i != 0) {
        $$scope{'forfirst'}    = 0;
        $$scope{'fornotfirst'} = 1;
      }
      if ($i == $#values) {
        $$scope{'forlast'}    = 1;
        $$scope{'fornotlast'} = 0;
      }
      $$scope{'forcount'} = $i + 1;

      ## We don't use adjust_value here because these names
      ## are generated from a foreach and should not be adjusted.
      $$scope{$name} = $value;

      ## A tiny hack for VC7
      if ($name eq 'configuration') {
        $self->{'prjc'}->update_project_info($self, 1,
                                             ['configuration', 'platform'],
                                             '|');
      }

      ## Now parse the line of text, each time
      ## with different values
      ++$self->{'foreach'}->{'processing'};
      ($status, $errorString) = $self->parse_line(undef, $text);
      --$self->{'foreach'}->{'processing'};
      if (!$status) {
        last;
      }
    }
  }

  return $status, $errorString;
}


sub handle_end {
  my($self)        = shift;
  my($name)        = shift;
  my($status)      = 1;
  my($errorString) = '';
  my($end)         = pop(@{$self->{'sstack'}});
  pop(@{$self->{'lstack'}});

  if (!defined $end) {
    $status = 0;
    $errorString = "ERROR: Unmatched $name\n";
  }
  elsif ($end eq 'endif') {
    $self->{'if_skip'} = 0;
  }
  elsif ($end eq 'endfor') {
    my($index) = $self->{'foreach'}->{'count'};
    ($status, $errorString) = $self->process_foreach();
    if ($status) {
      --$self->{'foreach'}->{'count'};
      $self->append_current($self->{'foreach'}->{'text'}->[$index]);
    }
  }

  return $status, $errorString;
}


sub get_flag_overrides {
  my($self)  = shift;
  my($name)  = shift;
  my($type)  = shift;
  my($value) = undef;
  my($file)  = $self->get_value($name);
  my($prjc)  = $self->{'prjc'};
  my($fo)    = $prjc->{'flag_overrides'};

  if (defined $file) {
    ## Replace the custom_type key with the actual custom type
    if ($name =~ /^custom_type\->/) {
      my($ct) = $self->get_value('custom_type');
      if (defined $ct) {
        $name = $ct;
      }
    }

    foreach my $key (keys %$fo) {
      if ($key =~ /^$name/) {
        foreach my $of (keys %{$$fo{$key}}) {
          my($cv) = $of;
          if ($self->{'cslashes'}) {
            $cv = $prjc->slash_to_backslash($of);
          }
          if ($cv eq $file) {
            foreach my $ma (keys %{$prjc->{'matching_assignments'}}) {
              if ($ma eq $key) {
                foreach my $aname (@{$prjc->{'matching_assignments'}->{$ma}}) {
                  if ($aname eq $type &&
                      defined $$fo{$key}->{$of}->{$aname}) {
                    $value = $$fo{$key}->{$of}->{$aname};
                    last;
                  }
                }
                last;
              }
            }
            last;
          }
        }
        last;
      }
    }
  }

  return $prjc->relative($value);
}


sub handle_if {
  my($self)   = shift;
  my($val)    = shift;
  my($name)   = 'endif';

  push(@{$self->{'lstack'}}, $self->get_line_number() . " $val");
  if (!$self->{'if_skip'}) {
    my($true)  = 1;
    push(@{$self->{'sstack'}}, $name);
    if ($val !~ /\|\|/ && $val =~ /^!(.*)/) {
      $val = $1;
      $val =~ s/^\s+//;
      $true = 0;
    }

    if ($val =~ /flag_overrides\(([^\)]+),\s*([^\)]+)\)/) {
      $val = $self->get_flag_overrides($1, $2);
    }
    else {
      if ($val =~ /\|\|/) {
        my($str) = $val;
        $val = undef;
        foreach my $v (split(/\s*\|\|\s*/, $str)) {
          my($p) = 0;
          if ($v =~ /^!(.*)/) {
            $p = $self->get_value($v);
            if (defined $p) {
              $p = undef;
            }
            else {
              $p = 'some value';

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -