Regular expression segmentation Fault with in-place substitution

R

Riad KACED

Dear Perl Fellows,

I'm trying to Find and Replace a pattern with in-place edit.
I have opened the file using the Tie::File module as advised in
perlfaq5.
My regular expression is quite simple :
s/\b$find\b/$replace/g, i.e global substitution of word anchored
pattern.
I found that the above fails whenever the pattern shows up more than
once in a line.
The Segmentation fault goes off by removing either the global modifier
or the word anchors. This is not what I want though. I spent entire
morning trying to figure it out but I have failed I'm afraid :-(

Anyway, my script is:

#!/usr/local/bin/perl -w

use strict;
use Tie::File;
use File::Copy;

my $spectreModelFile=shift;
my $spectreSubcktName=shift;
my @newpinNames=@ARGV;

my @spectreSubcktpinNames = getSpectreSubcktTerminals
($spectreModelFile,$spectreSubcktName);

my $newpinNamesLngth = @newpinNames;
my $spectreSubcktpinNamesLngth = @spectreSubcktpinNames;

unless ($newpinNamesLngth == $spectreSubcktpinNamesLngth)
{
die "Port Number mismatch: Given=$newpinNamesLngth, Needed=
$spectreSubcktpinNamesLngth\n" ;
}

copy($spectreModelFile,"$spectreModelFile.bak");
for (my $i=0; $i<$newpinNamesLngth ; $i++)
{
my $find=$spectreSubcktpinNames[$i];
my $replace=$newpinNames[$i];
print("Step # $i : find=$find, replace=$replace\n");
unless($find eq $replace)
{
findAndReplace($spectreModelFile,$find,$replace);
}
}



#-----------------------------------------------------------
# subroutine : findAndReplace
#-----------------------------------------------------------
sub findAndReplace
{
my ($inputFile,$find,$replace)=@_;
print("Attempting to replace $find by $replace ... ");
tie my @inputFile,'Tie::File',$inputFile or die "$inputFile : $!\n";
for (@inputFile)
{
s/\b$find\b/$replace/g; # This comes with a Segmentation fault
#s/\b$find\b/$replace/; # This is fine but it is not why I want
#s/$find/$replace/g; # This is fine but it is not why I want
}
untie @inputFile;
print("OK\n");
}
#-----------------------------------------------------------
# subroutine : getSpectreSubcktTerminals
#-----------------------------------------------------------
sub getSpectreSubcktTerminals
{
my ($spectreModelFile,$spectreSubcktName)=@_;
open(SPECTREMODELFILE,"< $spectreModelFile") or die "cannot read-
open $spectreModelFile : $!";
my @subcktTerminals;

while (my $line=<SPECTREMODELFILE>)
{
# Skip the commented lines. Blank lines : m/^\s*$/ are left
next if ($line =~ m/^\s*$/); # Skip blank lines
next if ($line =~ m/^s*\*/); # Skip commented lines, starting
with a leading Opt WS + '*'
next if ($line =~ m/^s*\/\//);# Skip commented lines, starting
with a leading Opt WS + '//'
# subckt and2 A B Vdd Vss Y
if ($line =~ m/^\s*subckt\s+\b$spectreSubcktName\b((?:\s+\w+)+)/)
{
my $subcktTerminals=$1;
$subcktTerminals =~ s/^\s+//;
@subcktTerminals=split(/\s+/,$subcktTerminals);
last;
}
}
close(SPECTREMODELFILE);
@subcktTerminals;
}

# EOF script

The script could be run as following :

myScript.pl myInFile mySubckt p1 p2 p3 p4 p5

myInFile is a text file (a Spectre subcircuit to be more precise):
// File starts here
subckt mySubckt a1 a12 vdd vss out
m0 vdd a1 2 vss myNmos l=1u w=10u
m1 vss a12 out vss myPmos l=1u w=10u
m2 2 a12 out out myPmos l=1u w=10u
ends mySubckt
// file ends here

FYI:
Perl Version: v5.8.0 (5.008)
OS = Suse Linux ES 9, Patch 3, kernel release 2.6.5-7.287.3.PTF.
363939.1-smp

Thanks in advance for your help !

regards,
Riad.
 
S

Sylvain

Dear Perl Fellows,

I'm trying to Find and Replace a pattern with in-place edit.
I have opened the file using the Tie::File module as advised in
perlfaq5.
My regular expression is quite simple :
s/\b$find\b/$replace/g, i.e global substitution of word anchored
pattern.
I found that the above fails whenever the pattern shows up more than
once in a line.
The Segmentation fault goes off by removing either the global modifier
or the word anchors. This is not what I want though. I spent entire
morning trying to figure it out but I have failed I'm afraid :-(

Anyway, my script is:

#!/usr/local/bin/perl -w

use strict;
use Tie::File;
use File::Copy;

my $spectreModelFile=shift;
my $spectreSubcktName=shift;
my @newpinNames=@ARGV;

my @spectreSubcktpinNames = getSpectreSubcktTerminals
($spectreModelFile,$spectreSubcktName);

my $newpinNamesLngth = @newpinNames;
my $spectreSubcktpinNamesLngth = @spectreSubcktpinNames;

unless ($newpinNamesLngth == $spectreSubcktpinNamesLngth)
{
  die "Port Number mismatch: Given=$newpinNamesLngth, Needed=
$spectreSubcktpinNamesLngth\n" ;

}

copy($spectreModelFile,"$spectreModelFile.bak");
for (my $i=0; $i<$newpinNamesLngth ; $i++)
{
  my $find=$spectreSubcktpinNames[$i];
  my $replace=$newpinNames[$i];
  print("Step # $i : find=$find, replace=$replace\n");
  unless($find eq $replace)
  {
    findAndReplace($spectreModelFile,$find,$replace);
  }

}

#-----------------------------------------------------------
# subroutine : findAndReplace
#-----------------------------------------------------------
sub findAndReplace
{
  my ($inputFile,$find,$replace)=@_;
  print("Attempting to replace $find by $replace ... ");
  tie my @inputFile,'Tie::File',$inputFile or die "$inputFile : $!\n";
  for (@inputFile)
  {
    s/\b$find\b/$replace/g; # This comes with a Segmentation fault
    #s/\b$find\b/$replace/;  # This is fine but it is not why I want
    #s/$find/$replace/g; # This is fine but it is not why I want
  }
  untie @inputFile;
  print("OK\n");}

#-----------------------------------------------------------
# subroutine : getSpectreSubcktTerminals
#-----------------------------------------------------------
sub getSpectreSubcktTerminals
{
  my ($spectreModelFile,$spectreSubcktName)=@_;
  open(SPECTREMODELFILE,"< $spectreModelFile") or die "cannot read-
open $spectreModelFile : $!";
  my @subcktTerminals;

  while (my $line=<SPECTREMODELFILE>)
  {
    # Skip the commented lines. Blank lines : m/^\s*$/ are left
    next if ($line =~ m/^\s*$/);  # Skip blank lines
    next if ($line =~ m/^s*\*/);  # Skip commented lines, starting
with a leading Opt WS + '*'
    next if ($line =~ m/^s*\/\//);# Skip commented lines, starting
with a leading Opt WS + '//'
    # subckt and2 A B Vdd Vss Y
    if ($line =~ m/^\s*subckt\s+\b$spectreSubcktName\b((?:\s+\w+)+)/)
    {
      my $subcktTerminals=$1;
      $subcktTerminals =~ s/^\s+//;
      @subcktTerminals=split(/\s+/,$subcktTerminals);
      last;
    }
  }
  close(SPECTREMODELFILE);
  @subcktTerminals;

}

# EOF script

The script could be run as following :

 myScript.pl myInFile mySubckt p1 p2 p3 p4 p5

myInFile is a text file (a Spectre subcircuit to be more precise):
// File starts here
subckt mySubckt a1 a12 vdd vss out
m0 vdd a1 2 vss myNmos l=1u w=10u
m1 vss a12 out vss myPmos l=1u w=10u
m2 2 a12 out out myPmos l=1u w=10u
ends mySubckt
// file ends here

FYI:
Perl Version: v5.8.0 (5.008)
OS = Suse Linux ES 9, Patch 3, kernel release 2.6.5-7.287.3.PTF.
363939.1-smp

Thanks in advance for your help !

regards,
Riad.

Hello my Friend Riad,

You're using the \b to find the word begin/end.
Have you tried this expression by changing "\b" to "\s+" ?
Does chrash also ?


Regards,

Sylvain
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,056
Messages
2,570,443
Members
47,091
Latest member
IsaacLuna

Latest Threads

Top