У меня есть файл C, в котором мы перемещаем инфраструктуру ведения журнала. ТакУсловно изменение выражений C в исходном файле C
if (logging_level >= LEVEL_FINE)
printf("Value at %p is %d\n", p, i);
становится
do_log2(LEVEL_FINE, "Value at %p is %d\n", _ptr(p), _num(i));
do_log2 означает журнал с 2-мя аргументами.
Для этого мне нужна инфраструктура синтаксического анализа и модификации C.
Какой инструмент я могу использовать, чтобы выполнить это наиболее легко?
Примечание: Printf может также появиться в файле как:
if (logging_level >= LEVEL_FINE)
{
printf("Value at %p is %d\n",
p,
i);
}
(с отступом и в блоке). Так что это будет трудно сделать из простого синтаксического анализа текста в perl.
EDIT: Это мой окончательный код Perl, который делает то, что я хочу
#!/usr/bin/perl -W
$source=<<'END';
include etc
if (logging_level >= LEVEL_DEBUG)
{
printf("1:Value at %p is %d\n",
p(1),
i(2));
}
hello();
if (logging_level >= LEVEL_FINE)
{
printf("2:Value is %d\n", i);
printf("3:Value is %d\n", i);
}
if (logging_level >= LEVEL_FINE)
{
printf("2:Value is %d\n"
"and other info", i);
}
other();
if(logging_level>=LEVEL_INFO){printf("4:Value at %p is %d %d\n",p(x),i,j);}
if(logging_level>=LEVEL_FINE) printf("5:Just sayin\"\n");
printf("not logging statement\n").
END
while($source =~ m/\G(.*?\n)\s* if \s* \(\s* logging_level \s* >= \s* ([A-Z_0-9]+) \s* \) \s*(\{?)/sgxc)
{
my $othercode = $1;
my $loglevel=$2;
my $inblock = $3;
print("$othercode");
while($source =~ m/\G\s*printf \(([^;]*) \) \;/sgxc)
{
my $insideprint = $1;
unless ($insideprint =~ /((\"([^\"\\]|\\.)*\")(\s*(\"([^\"\\]|\\.)*\"))*)/g) #fixing stackoverflow quote problem "
{
die "First arg not string literal";
}
my $formatstr = $1;
my $remain = substr($insideprint, pos($insideprint));
$remain =~ tr/\n \t//d;
my @args = split(",", $remain);
shift @args;
my $numargs = @args;
print "do_log${numargs}($loglevel, $formatstr";
for (my $i=0; $i < $numargs; $i++)
{
unless ($formatstr =~ /%([a-z]+)/g)
{
die "Not enough format for args : $formatstr, args = ", join(",", @args), "\n";
}
my $lastchar = substr($1, length($1) -1);
my $wrapper = "";
if ($lastchar eq "u" || $lastchar eq "d")
{ $wrapper = "_numeric";}
elsif($lastchar eq "p"){ $wrapper = "_ptr";}
elsif($lastchar eq "s"){ $wrapper = "_str";}
else { die "Unknown format char %$lastchar in $formatstr"; }
print ", ${wrapper}($args[$i])";
}
print ");";
last unless ($inblock);
}
# eat trailing }
if ($inblock)
{
if ($source =~ m/\G \s* \} /sgxc)
{
}
else
{
}
}
}
#whatever is left
print substr($source, pos($source));
выход:
include etc
do_log2(LEVEL_DEBUG, "1:Value at %p is %d\n", _ptr(p(1)), _numeric(i(2)));
hello();
do_log1(LEVEL_FINE, "2:Value is %d\n", _numeric(i));
do_log1(LEVEL_FINE, "3:Value is %d\n", _numeric(i));
do_log1(LEVEL_FINE, "2:Value is %d\n"
"and other info", _numeric(i));
other();
do_log3(LEVEL_INFO, "4:Value at %p is %d %d\n", _ptr(p(x)), _numeric(i), _numeric(j));
do_log0(LEVEL_FINE, "5:Just sayin\"\n");
printf("not logging statement\n").
Woohoo! Теперь применим к фактическому исходному коду.
Я не думаю, что это такая трудная проблема для Perl. Но вам придется заплатить мне деньги, чтобы написать решение для вас. – 2009-10-13 04:21:05