R
robic0
Hello, last month I wrote a rather large 10,000 line program that
parses xml (expat). The data is read into compound structures
then analyzed later. Below is one of the subroutines. I would like
to make it smaller so that its easier to read and understand and
also make the regular expressions less complicated for performance.
Any ideas?
---------------------------
sub eCHK_RegDel ## -- checks Redundant Regkey Delete // Regkey
exists --
{
my ($details) = @_;
return 1 if (@{$details} == 0);
my @regdel = ();
for (@$details) {
my $aref = $_->[0];
push (@regdel, $aref) if ($aref->[5] eq $REGISTRY && $aref->[6] eq
$DELETE);
}
if (@regdel)
{
## check that KeyName exists
for (@regdel) {
my $aref = $_;
next if (exists ($aref->[4]{$KEYNAME}) &&
length($aref->[4]{$KEYNAME}) > 0);
# log error
## 0701 -- test 07,01
ReportItem ('E', $CLOGINFO, $CERRLOG, '0701', glicn($aref), (0,0),
'', $XML_File, 1,0,1);
}
## check redundant regkey deletes
my $first_kname = '';
my $first_vname_exists = 0;
my $aref_first = undef;
my @regx_esc_codes = ( "\\", '/', '(', ')', '[', ']', '?', '|',
'+', '.', '*', '$', '^', '{',
'}', '@' );
for (@regdel)
{
my $aref = $_;
next if (!(exists ($aref->[4]{$KEYNAME}) &&
length($aref->[4]{$KEYNAME}) > 0));
my $kname = $aref->[4]{$KEYNAME};
my $vname = '';
my $kv = 'key (branch)';
if (exists ($aref->[4]{$VALUENAME})) {
if (length($aref->[4]{$VALUENAME}) > 0) {
$vname = $aref->[4]{$VALUENAME};
# strip leading spaces
while ($vname =~ s/^ //) {}
}
$kv = 'value';
}
for (@regx_esc_codes)
{
my $tc = $_;
my $xx = "\$kname =~ s/\\$tc/\\\\\\$tc/g;"; # code template for
regex
eval $xx;
#print "$xx\n";
}
$kname = $kname."\\\\";
my $fnd = 0;
# -- #
my $ctmpl = "if (\$kname =~ /^$first_kname/i) {\$fnd = 1;}"; #
code template for first key name
eval $ctmpl;
# -- #
#print
"-------------\n$fnd,$ctmpl\nkname=$kname\n--------------\n\n";
#print
"-------------\n$fnd,$ctmpl\nkname=$kname\nfirst=$first_kname\n--------------\n\n";
if ($@) {
## Check the $ctmpl, get the control code, log this error as a code
issue.
## This shouldn't happen ... the compiler will show the escape
char, add
## the char to "@regx_esc_codes", now its fixed!
$@ =~ s/^[\x20\n\t]+//; $@ =~ s/[\x20\n\t]+$//;
## 0702 -- test 07,02
ReportItem ('E', $CLOGINFO, $CERRLOG, '0702', (0,0,0,0), $@,
$XML_File, 1,0,1);
}
if ((!$fnd || length ($first_kname) == 0))
{
# because of sort,the first non valuename
# will always be in the new keyname action
$first_kname = uc($kname);
for (@regx_esc_codes)
{
my $tc = $_;
my $xx = "\$first_kname =~ s/\\$tc/\\\\\\$tc/g;"; # code
template for regex
eval $xx;
}
$aref_first = $aref;
if (length ($vname) > 0) {$first_vname_exists = 1} else {
$first_vname_exists = 0}
next;
}
next if ($first_vname_exists);
if (length($vname) == 0) {
if ($fnd) {
# log error, this sub-key is already being deleted
## 0703 -- test 07,03
ReportItem ('E', $CLOGINFO, $CERRLOG, '0703', glicn($aref),
glicn($aref_first), '', $XML_File, 1,0,1);
}
next;
}
# log error, the key for this value is already being deleted
## 0704 -- test 07,04
ReportItem ('E', $CLOGINFO, $CERRLOG, '0704', glicn($aref),
glicn($aref_first), '', $XML_File, 1,0,1);
}
}
}
-----------------------------
parses xml (expat). The data is read into compound structures
then analyzed later. Below is one of the subroutines. I would like
to make it smaller so that its easier to read and understand and
also make the regular expressions less complicated for performance.
Any ideas?
---------------------------
sub eCHK_RegDel ## -- checks Redundant Regkey Delete // Regkey
exists --
{
my ($details) = @_;
return 1 if (@{$details} == 0);
my @regdel = ();
for (@$details) {
my $aref = $_->[0];
push (@regdel, $aref) if ($aref->[5] eq $REGISTRY && $aref->[6] eq
$DELETE);
}
if (@regdel)
{
## check that KeyName exists
for (@regdel) {
my $aref = $_;
next if (exists ($aref->[4]{$KEYNAME}) &&
length($aref->[4]{$KEYNAME}) > 0);
# log error
## 0701 -- test 07,01
ReportItem ('E', $CLOGINFO, $CERRLOG, '0701', glicn($aref), (0,0),
'', $XML_File, 1,0,1);
}
## check redundant regkey deletes
my $first_kname = '';
my $first_vname_exists = 0;
my $aref_first = undef;
my @regx_esc_codes = ( "\\", '/', '(', ')', '[', ']', '?', '|',
'+', '.', '*', '$', '^', '{',
'}', '@' );
for (@regdel)
{
my $aref = $_;
next if (!(exists ($aref->[4]{$KEYNAME}) &&
length($aref->[4]{$KEYNAME}) > 0));
my $kname = $aref->[4]{$KEYNAME};
my $vname = '';
my $kv = 'key (branch)';
if (exists ($aref->[4]{$VALUENAME})) {
if (length($aref->[4]{$VALUENAME}) > 0) {
$vname = $aref->[4]{$VALUENAME};
# strip leading spaces
while ($vname =~ s/^ //) {}
}
$kv = 'value';
}
for (@regx_esc_codes)
{
my $tc = $_;
my $xx = "\$kname =~ s/\\$tc/\\\\\\$tc/g;"; # code template for
regex
eval $xx;
#print "$xx\n";
}
$kname = $kname."\\\\";
my $fnd = 0;
# -- #
my $ctmpl = "if (\$kname =~ /^$first_kname/i) {\$fnd = 1;}"; #
code template for first key name
eval $ctmpl;
# -- #
"-------------\n$fnd,$ctmpl\nkname=$kname\n--------------\n\n";
"-------------\n$fnd,$ctmpl\nkname=$kname\nfirst=$first_kname\n--------------\n\n";
if ($@) {
## Check the $ctmpl, get the control code, log this error as a code
issue.
## This shouldn't happen ... the compiler will show the escape
char, add
## the char to "@regx_esc_codes", now its fixed!
$@ =~ s/^[\x20\n\t]+//; $@ =~ s/[\x20\n\t]+$//;
## 0702 -- test 07,02
ReportItem ('E', $CLOGINFO, $CERRLOG, '0702', (0,0,0,0), $@,
$XML_File, 1,0,1);
}
if ((!$fnd || length ($first_kname) == 0))
{
# because of sort,the first non valuename
# will always be in the new keyname action
$first_kname = uc($kname);
for (@regx_esc_codes)
{
my $tc = $_;
my $xx = "\$first_kname =~ s/\\$tc/\\\\\\$tc/g;"; # code
template for regex
eval $xx;
}
$aref_first = $aref;
if (length ($vname) > 0) {$first_vname_exists = 1} else {
$first_vname_exists = 0}
next;
}
next if ($first_vname_exists);
if (length($vname) == 0) {
if ($fnd) {
# log error, this sub-key is already being deleted
## 0703 -- test 07,03
ReportItem ('E', $CLOGINFO, $CERRLOG, '0703', glicn($aref),
glicn($aref_first), '', $XML_File, 1,0,1);
}
next;
}
# log error, the key for this value is already being deleted
## 0704 -- test 07,04
ReportItem ('E', $CLOGINFO, $CERRLOG, '0704', glicn($aref),
glicn($aref_first), '', $XML_File, 1,0,1);
}
}
}
-----------------------------