Perl 到 Tcl 代码转换
Perl to Tcl code conversion
我需要将 perl 脚本转换为 Tcl 脚本。我以前在 Python 工作过,但这是一个新的挑战,因为我在 perl 和 tcl 方面都是新手。
谁能给我一些关于如何在 Tcl 中表示以下行的指示:
my @GPO_regs = qw(0x70034 0x70038 0x7003C 0x70040 0x70044);
sub write_phy {
my($phy, $register, $value) = @_;
$value = oct($val) if $value =~ /^0/;
if ($DEBUG) { printf("Write PHY ${phy} register ${register} =
0x%0.8X\n", $value); };
`./write_phy.pl ${phy} ${register} ${value}`;
}
在另一个 Perl 文件中:
my ($phyAddr, $regAddr) = @ARGV;
if($phyAddr =~ /0x/) {
$phyAddr = oct($phyAddr);
}
if($regAddr =~ /0x/) {
$regAddr = oct($regAddr);
}
my $registerValue = 1 << 31 | $phyAddr << 25 | $regAddr << 20 | 2 << 1;
my $registerHex = sprintf("0x%X", $registerValue);
`./read_write_spi_reg -a 0x070064 -w ${registerHex}`;
my $value = `./read_write_spi_reg -a 0x070068 -r`;
if( $value >> 16 != 0 ) {
die "Error reading PHY register";
}
chomp($value);
printf("${value}\n");
感谢您的支持。
好吧,让我们考虑一下第一个文件中的代码:
my @GPO_regs = qw(0x70034 0x70038 0x7003C 0x70040 0x70044);
这(它正在创建一个从未使用过的 effectively-global 变量?)将被翻译成:
set GPO_regs {0x70034 0x70038 0x7003C 0x70040 0x70044}
而这个:
sub write_phy {
my($phy, $register, $value) = @_;
# Stuff...
}
变为:
proc write_phy {phy register value} {
# Translation of Stuff...
}
继续查看子程序的内容(应用明显的更正后):
$value = oct($value) if $value =~ /^0/;
如果该字符串以前导零开头,则此行解码该字符串的八进制值。 Tcl 在某些情况下默认这样做,但让我们明确一点。我将使用正则表达式来执行“如果该字符串以前导零开头”,尽管我通常不会这样做,因为这将帮助您翻译其他文件:
if { [regexp {^0} $value] } {
# The [scan] command is a lot like the C sscanf() function, if you know that
scan $value "%o" value
}
翻译这个唯一棘手的事情:
if ($DEBUG) { printf("Write PHY ${phy} register ${register} = 0x%0.8X\n", $value); };
是Tcl和Perl有不同的变量作用域规则,所以DEBUG
变量会不存在。在这种情况下,最简单的技术是使用变量的 fully-qualified 名称。
if {$::DEBUG} {
puts [format "Write PHY ${phy} register ${register} = 0x%0.8X" $value]
### However, I recommend this instead:
# puts [format "Write PHY %s register %s = 0x%0.8X" $phy $register $value]
### As unexpected % symbols in phy or register won't make it choke. The equivalent
### advice would apply if you were sticking with Perl.
}
最后,Perl 中的反引号直接转换为 Tcl 的 exec
,因此:
`./write_phy.pl ${phy} ${register} ${value}`;
变成这样:
exec ./write_phy.pl $phy $register $value
您通常可以省略 Tcl 变量名周围的 {
大括号 }
;您只需要在会导致 otherwise-unwanted 解析的地方使用它们。
将这些放在一起,我得到:
set GPO_regs {0x70034 0x70038 0x7003C 0x70040 0x70044}
proc write_phy {phy register value} {
if { [regexp {^0} $value] } {
scan $value "%o" value
}
if {$::DEBUG} {
puts [format "Write PHY %s register %s = 0x%0.8X" $phy $register $value]
}
exec ./write_phy.pl $phy $register $value
}
请注意,另一个文件中的代码潜伏着一些讨厌的错误!我不会深入探讨它,但您需要了解的关键是,不用作 if
条件的表达式应包含在 expr
中,如下所示:
set registerValue [expr {1 << 31 | $phyAddr << 25 | $regAddr << 20 | 2 << 1}]
将脚本的参数拆分为变量的推荐方法如下:
lassign $argv phyAddr regAddr
(Tcl 的 $
并不意味着“这是一个变量”,它的意思是“从这个变量中读取”。变量 names 传递给操作变量本身——例如 set
和 lassign
——前面通常不应有 $
。)
此外,Perl 的 die
很像 Tcl 的 error
,而 Tcl 的 exec
会自动对其结果执行类似 chomp
的操作。
我需要将 perl 脚本转换为 Tcl 脚本。我以前在 Python 工作过,但这是一个新的挑战,因为我在 perl 和 tcl 方面都是新手。
谁能给我一些关于如何在 Tcl 中表示以下行的指示:
my @GPO_regs = qw(0x70034 0x70038 0x7003C 0x70040 0x70044);
sub write_phy {
my($phy, $register, $value) = @_;
$value = oct($val) if $value =~ /^0/;
if ($DEBUG) { printf("Write PHY ${phy} register ${register} =
0x%0.8X\n", $value); };
`./write_phy.pl ${phy} ${register} ${value}`;
}
在另一个 Perl 文件中:
my ($phyAddr, $regAddr) = @ARGV;
if($phyAddr =~ /0x/) {
$phyAddr = oct($phyAddr);
}
if($regAddr =~ /0x/) {
$regAddr = oct($regAddr);
}
my $registerValue = 1 << 31 | $phyAddr << 25 | $regAddr << 20 | 2 << 1;
my $registerHex = sprintf("0x%X", $registerValue);
`./read_write_spi_reg -a 0x070064 -w ${registerHex}`;
my $value = `./read_write_spi_reg -a 0x070068 -r`;
if( $value >> 16 != 0 ) {
die "Error reading PHY register";
}
chomp($value);
printf("${value}\n");
感谢您的支持。
好吧,让我们考虑一下第一个文件中的代码:
my @GPO_regs = qw(0x70034 0x70038 0x7003C 0x70040 0x70044);
这(它正在创建一个从未使用过的 effectively-global 变量?)将被翻译成:
set GPO_regs {0x70034 0x70038 0x7003C 0x70040 0x70044}
而这个:
sub write_phy {
my($phy, $register, $value) = @_;
# Stuff...
}
变为:
proc write_phy {phy register value} {
# Translation of Stuff...
}
继续查看子程序的内容(应用明显的更正后):
$value = oct($value) if $value =~ /^0/;
如果该字符串以前导零开头,则此行解码该字符串的八进制值。 Tcl 在某些情况下默认这样做,但让我们明确一点。我将使用正则表达式来执行“如果该字符串以前导零开头”,尽管我通常不会这样做,因为这将帮助您翻译其他文件:
if { [regexp {^0} $value] } {
# The [scan] command is a lot like the C sscanf() function, if you know that
scan $value "%o" value
}
翻译这个唯一棘手的事情:
if ($DEBUG) { printf("Write PHY ${phy} register ${register} = 0x%0.8X\n", $value); };
是Tcl和Perl有不同的变量作用域规则,所以DEBUG
变量会不存在。在这种情况下,最简单的技术是使用变量的 fully-qualified 名称。
if {$::DEBUG} {
puts [format "Write PHY ${phy} register ${register} = 0x%0.8X" $value]
### However, I recommend this instead:
# puts [format "Write PHY %s register %s = 0x%0.8X" $phy $register $value]
### As unexpected % symbols in phy or register won't make it choke. The equivalent
### advice would apply if you were sticking with Perl.
}
最后,Perl 中的反引号直接转换为 Tcl 的 exec
,因此:
`./write_phy.pl ${phy} ${register} ${value}`;
变成这样:
exec ./write_phy.pl $phy $register $value
您通常可以省略 Tcl 变量名周围的 {
大括号 }
;您只需要在会导致 otherwise-unwanted 解析的地方使用它们。
将这些放在一起,我得到:
set GPO_regs {0x70034 0x70038 0x7003C 0x70040 0x70044}
proc write_phy {phy register value} {
if { [regexp {^0} $value] } {
scan $value "%o" value
}
if {$::DEBUG} {
puts [format "Write PHY %s register %s = 0x%0.8X" $phy $register $value]
}
exec ./write_phy.pl $phy $register $value
}
请注意,另一个文件中的代码潜伏着一些讨厌的错误!我不会深入探讨它,但您需要了解的关键是,不用作 if
条件的表达式应包含在 expr
中,如下所示:
set registerValue [expr {1 << 31 | $phyAddr << 25 | $regAddr << 20 | 2 << 1}]
将脚本的参数拆分为变量的推荐方法如下:
lassign $argv phyAddr regAddr
(Tcl 的 $
并不意味着“这是一个变量”,它的意思是“从这个变量中读取”。变量 names 传递给操作变量本身——例如 set
和 lassign
——前面通常不应有 $
。)
此外,Perl 的 die
很像 Tcl 的 error
,而 Tcl 的 exec
会自动对其结果执行类似 chomp
的操作。