1

我想要达到的目标:

###############CODE########
old_procedure(arg1, arg2);
#############CODE_END######

我有一个巨大的代码,其中有一个旧程序。我希望对 old_procedure 的调用转到对具有相同参数的新过程 (new_procedure(arg1, arg2)) 的调用。现在我知道了,这个问题似乎很愚蠢,但诀窍是我不允许更改代码或 bad_function。所以我唯一能做的就是在外部创建一个程序来读取代码流或其他东西,然后每当它找到 bad_function 时,它就会用 new_function 替换它。它们具有 void 类型,因此不必担心返回值。我正在使用 perl。如果有人知道如何至少从这个方向开始......请发表评论或回答。如果新代码可以用 perl 或 C 来完成,那就太好了,但其他已知的语言也很好。C++,Java。

编辑:代码是用 shell 脚本和 perl 编写的。我无法编辑代码,也没有 old_function 的位置,我的意思是我可以找到它……但它真的很难。所以我可以使用指出的包的东西,但是如果有办法解决它......这样我就可以用那个函数解析线程并替换函数调用。请不要删除标签,因为我还需要 java、C++ 专家的建议。

编辑:@mirod 所以我试了一下,你的回答做了一个新的子程序,现在没有办法访问旧的子程序。我创建了一个变量,它检查值以决定走哪条路(old_sub 或 new_sub)...有没有办法在新代码中添加变量...如果未设置,它将控制发送回 old_function ... 喜欢:

use BadPackage; # sub is defined there
BEGIN
{ package BapPackage;
  no warnings; # to avoid the "Subroutine bad_sub redefined" message
# check for the variable and send to old_sub if the var is not set
  sub bad_sub
    { # good code
    }
}
# Thanks @mirod
4

4 回答 4

4

这在 Perl 中比在许多其他语言中更容易做到,但这并不意味着它很容易,而且我不知道这是否是你想听到的。这是一个概念验证:

让我们看一些损坏的代码:

# file name: Some/Package.pm
package Some::Package;
use base 'Exporter';
our @EXPORT = qw(forty_two nineteen);
sub forty_two { 19 }
sub nineteen { 19 }
1;

# file name: main.pl
use Some::Package;
print "forty-two plus nineteen is ", forty_two() + nineteen();

运行程序perl main.pl会产生输出:

forty-two plus nineteen is 38

假设文件Some/Package.pmmain.pl已损坏且不可变。我们如何纠正他们的行为?

我们可以将任意代码插入perl命令的一种方法是使用-M命令行开关。让我们制作一个修复模块:

# file: MyRepairs.pm
CHECK {
    no warnings 'redefine';  
    *forty_two = *Some::Package::forty_two = sub { 42 };
};
1;

现在运行程序perl -MMyRepairs main.pl会产生:

forty-two plus nineteen is 61

我们的修复模块使用一个CHECK块在编译时和运行时阶段之间执行代码。我们希望我们的代码是在编译时运行的最后一个代码,这样它就会覆盖一些已经加载的函数。-M命令行开关将首先运行我们的代码,因此该块CHECK延迟执行我们的修复,直到运行所有其他编译时代码。有关perlmod更多详细信息,请参阅。

这个解决方案很脆弱。require ...对于在运行时加载的模块(使用or eval "use ..."(这些很常见)或在其他CHECK块中定义的子例程(这些很少见)),它不能做太多事情。

如果我们假设运行的 shell 脚本main.pl也是不可变的(即,我们不允许更改perl main.plperl -MMyRepairs main.pl),那么我们上移一级并-MMyRepairsPERL5OPT环境变量中传递 :

PERL5OPT="-I/path/to/MyRepairs -MMyRepairs" bash the_immutable_script_that_calls_main_pl.sh
于 2013-07-18T16:26:17.770 回答
1

这些被称为自动重构工具,在其他语言中很常见。对于 Perl,尽管您可能处于非常糟糕的状态,因为解析 Perl 以找到所有引用几乎是不可能的。

于 2013-07-18T15:38:30.533 回答
1

旧程序在哪里定义?

如果是在包中定义的,你可以切换到包,在它被used之后,重新定义子:

use BadPackage; # sub is defined there
BEGIN
{ package BapPackage;
  no warnings; # to avoid the "Subroutine bad_sub redefined" message
  sub bad_sub
    { # good code
    }
}

如果代码在同一个包中但在不同的文件中(通过 a 加载require),您可以执行相同的操作而无需切换包。

如果所有代码都在同一个文件中,则更改它。

于 2013-07-18T15:46:39.943 回答
0

sed -i 's/old_procedure/new_procedure/g 代码文件

你是这个意思吗?

于 2013-07-18T15:40:10.157 回答