cdeloos has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I've been using this site quite extensively, especially the tutorials have been very usefull to me. But now I have come across a problem which I have been unable to solve so far, and any help on this issue would be very much appreciated. I am trying to read a config from a Cisco router and get it into a hash so I can use it later on. For the IP address I have written a module that just stores the IP address (as a string of 32 1's and 0's) and the mask (as a value between 0 and 33). The IP field in my data structure should contain a reference to the object, but somehow it doesn't work as I think it should. I have a feeling the problem has to do with scoping, even though I haven't been able to pinpoint it exactly.
#!/usr/bin/perl use strict; use warnings; use Switch; use MyIP; my %int; my $cur_int=""; open (CONF, "ipplan.cfg") or die "file does not exist\n"; while (<CONF>) { switch ($_) { case /^interface / { (undef, $cur_int, undef) = split / /; $int{$cur_int}{ip}=""; } case /^ ip address [\d\.]+ [\d\.]+$/ { my (undef, undef, $ip, $mask, undef) = split / /; $int{$cur_int}{ip}=new MyIP ($ip, $mask) or die "incorrect IP addr +ess: $ip $mask\n"; print "$cur_int: $ip $mask = ", $int{$cur_int}{ip}->print_cidr(), +"\n"; } } close CONF; foreach my $key (keys %int) { print "int $key \n"; print " ip address ",$int{$key}{ip}->print_cidr(), "\n"; }
The problem is in the output of $int{$key}{ip}-print_cidr(). When I call it from within the block that created the object it works fine, but when I do so from another block, later on in the program I get an error message: Can't call method "print_cidr" without a package or object reference output:
Loopback0: 172.25.10.10 255.255.255.255 = 172.25.10.10/32 int Loopback0 Can't call method "print_cidr" without a package or object reference a +t ./conf.pl line 83.
but, when removing the call to print_cidr and just printing the object, i.e.:
foreach my $key (keys %int) { print "int $key \n"; print " ip address ",$int{$key}{ip}, "\n"; }
a reference to a MyIP object does appear...
Loopback0: 172.25.10.10 255.255.255.255 = 172.25.10.10/32 int Loopback0 ip address MyIP=HASH(0x84eeef4)
so my question is what i am doing wrong here... and of course what I can do to fix this! Your help is much appreciated.

Replies are listed 'Best First'.
Re: object scope problem?
by kyle (Abbot) on Feb 12, 2008 at 17:26 UTC

    I don't see a problem related to your object, but I know that Switch can cause some strange problems. I'd recommend rewriting the code that uses it, and see if the problem persists. Also, you could be capturing the fields you want during regex matches instead of doing a separate split.

    while (<CONF>) { if ( /^interface (\S+)/ ) { $cur_int = $1; $int{$cur_int}{ip}=""; } elsif ( /^ ip address ([\d\.]+) ([\d\.]+)$/ ) { my ( $ip, $mask ) = ( $1, $2 ); $int{$cur_int}{ip}=MyIP->new($ip, $mask) or die "incorrect IP address: $ip $mask\n"; print "$cur_int: $ip $mask = ", $int{$cur_int}{ip}->print_cidr(), +"\n"; } }
Re: object scope problem?
by chromatic (Archbishop) on Feb 12, 2008 at 19:06 UTC

    Here's a problem:

    $int{$cur_int}{ip}="";

    Your hash may have empty strings as values, if there's a line starting interface not followed with an  ip address line. You can remove this block of code entirely. If you really need to keep it, change it to delete $int{$cur_int}{ip};

Re: object scope problem?
by FunkyMonk (Bishop) on Feb 12, 2008 at 23:04 UTC
    Expanding on what kyle said, source filters are evil and break often. I avoid them at all costs.

    See

    • "How do I create a switch or case statement" in perlfaq7
    • given/when, the perl 5.10 equivalent of switch
    for alternatives.