Perl到Tcl代码转换

时间:2016-01-15 08:39:05

标签: perl tcl

我需要将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");

感谢您的支持。

1 个答案:

答案 0 :(得分:2)

好吧,让我们在您的第一个文件中考虑您的代码:

my @GPO_regs = qw(0x70034 0x70038 0x7003C 0x70040 0x70044);

这(创建一个从未使用过的有效全局变量?)将被翻译成:

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变量将不存在。在这种情况下,最简单的方法是使用变量的完全限定名称。

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&#39; exec,所以这个:

`./write_phy.pl ${phy} ${register} ${value}`;

成为这个:

exec ./write_phy.pl $phy $register $value

您通常可以从Tcl变量名称周围省略{大括号};你只需要它们就会导致一个不必要的解析。

把这些放在一起,我得到:

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&#39; s $并不意味着“这是一个变量”,它意味着“从这个变量中读取”。变量名称传递给操纵的东西变量本身 - 例如setlassign - 通常不应该在前面有$。)

此外,Perl的die与Tcl的error非常相似,而Tcl的exec会自动执行chomp - 喜欢操作它的结果。