# See copyright, etc in below POD section.
######################################################################
package Verilog::Getopt; # package name, 其中Verilog是目录
require 5.000; # 需要perl5.0以上
require Exporter; # Exporter 使得能够导出各个函数
use strict;
use vars qw($VERSION $Debug %Skip_Basenames); # 等同于our声明,导出变量
use Carp; # package中使用warning或者die类似的功能。
use IO::File;
use File::Basename;
use File::Spec;
use Cwd;
######################################################################
#### Configuration Section
$VERSION = '3.305';
# Basenames we should ignore when recursing directories,
# Because they contain large files of no relevance
foreach ( '.', '..',
'CVS',
'.svn',
'.snapshot',
'blib',
) {
$Skip_Basenames{$_} = 1;
}
#######################################################################
#######################################################################
#######################################################################
# 类成员(可以有初值),本质是hash表。成员函数不再其中,凡是package声明的sub函数都是成员函数。
# 一般我们推荐将internal的成员(private) 声明成 _member 的形式。这些类成员和后面声明的函数可以同名,
# 但是他们是完全不同的东西。一般同名的函数会把返回的值放入这些同名的的成员中(如匿名数组或hash表)
# 在perl中哪些变量会声明成类成员呢? 一般用于configuration变量以及在各个函数中传递(即多个函数使用的
# 变量)。 @_ 指明从new参数中给出的值。这样可以给成员赋新值,或者加入新的成员。本例中就是options
# 如 $Opt = new Verilog::Getopt(gcc_style=>0)
sub new {
@_ >= 1 or croak 'usage: Verilog::Getopt->new ({options})';
my $class = shift; # Class (Getopt Element) 类名
$class ||= "Verilog::Getopt"; # 进一步确定类名
my $self = {defines => {},
incdir => ['.', ],
module_dir => ['.', ],
libext => ['.v', ],
library => [ ],
gcc_style => 1,
vcs_style => 1,
fileline => 'Command_Line',
unparsed => [],
define_warnings => 1,
depend_files => {},
@_
};
bless $self, $class; #洗礼成为类
return $self; #返回类指针
}
#######################################################################
# Option parsing
sub _filedir {
my $self = shift;
my $path = shift;
$path =~ s![/\\][^/\\]*$!! # ~~== my @dirs = File::Spec->splitdir( $path );
or $path = ".";
return "." if $path eq '';
return $path
}
sub parameter_file {
my $self = shift;
my $filename = shift;
my $relative = shift;
print "*parameter_file $filename\n" if $Debug;
my $optdir = ".";
if ($relative) { $optdir = $self->_filedir($filename); }
my $fh = IO::File->new("<$filename") or die "%Error: ".$self->fileline().": $! $filename\n";
my $hold_fileline = $self->fileline();
while (my $line = $fh->getline()) {
chomp $line;
$line =~ s/\/\/.*$//;
next if $line =~ /^\s*$/;
$self->fileline ("$filename:$.");
my @p = (split /\s+/,"$line ");
$self->_parameter_parse($optdir, @p);
}
$fh->close();
$self->fileline($hold_fileline);
}
sub parameter {
my $self = shift;
# Parse VCS like parameters, and perform standard setup based on it
# Return list of leftover parameters
@{$self->{unparsed}} = ();
$self->_parameter_parse('.', @_);
return @{$self->{unparsed}};
}
sub _parameter_parse {
my $self = shift;
my $optdir = shift;
# Internal: Parse list of VCS like parameters, and perform standard setup based on it
foreach my $param (@_) {
next if ($param =~ /^\s*$/);
print " parameter($param)\n" if $Debug;
### GCC & VCS style
if ($param eq '-F'
|| $param eq '-f') {
$self->{_parameter_next} = $param;
}
### VCS style
elsif (($param eq '-v'
|| $param eq '-y') && $self->{vcs_style}) {
$self->{_parameter_next} = $param;
}
elsif ($param =~ /^\+libext\+(.*)$/ && $self->{vcs_style}) {
my $ext = $1;
foreach (split /\+/, $ext) {
$self->libext($_);
}
}
elsif ($param =~ /^\+incdir\+(.*)$/ && $self->{vcs_style}) {
$self->incdir($self->_parse_file_arg($optdir, $1));
}
elsif (($param =~ /^\+define\+([^+=]*)[+=](.*)$/
|| $param =~ /^\+define\+(.*?)()$/) && $self->{vcs_style}) {
$self->define($1,$2,undef,1);
}
# Ignored
perl高级用法--通过学习Verilog::Getopt掌握package的写法
本文介绍了如何使用perl的Verilog::Getopt模块来处理Verilog命令行选项。该模块提供了类似VCS和GCC的参数解析功能,包括设置库扩展、包含目录、模块目录等,并提供了方便的访问器方法。文章详细讲解了package的写法,包括配置部分、类成员定义、解析选项的方法以及各种访问器方法的用法。
摘要由CSDN通过智能技术生成