in reply to Re: screen out an untained array from a special array
in thread screen out an untained array from a special array

Thanks for everyone above replied.
The max value is always 31, and those input are read from a parsed file.
The output should be (\d+:\d+) so which is required by the Verilog syntax I had to use.
Here is what I have tried.
sub get_reserved { my $bits_ref = shift; my @bits = @{$bits_ref}; my @digits = map { chomp; if ( m/(\d+):(\d+)/) { ($1 > $2) ? ($2 .. $1) : ($1 .. $2); } else { $_; } } @bits; my @reg32set = map {0} 0 .. 31; my @index; if (@digits ne '') { map {$reg32set[$_] = 1;} @digits; @index = grep {if ($reg32set[$_] == 0) {$_;}} 0..31; } else { undef @index; } }

Replies are listed 'Best First'.
Re^3: screen out an untained array from a special array
by graff (Chancellor) on Feb 08, 2009 at 03:38 UTC
    The output should be (\d+:\d+) so which is required by the Verilog syntax I had to use.

    Does the "Verilog syntax" have some sort of specification that says an N1..N2 range should be presented sometimes as "N1:N2" and other times as "N2:N1"? Do you know whether there is some reason for this fluctuation?

    Regarding the code you posted, you are missing some fundamental points of Perl syntax. What do you think  @digits ne '' is supposed to do? (Hint: an array in a scalar context always returns the number of elements in the array, which will never be the same as an empty string.)

    If "Verilog syntax" supports the use of a consistent ordering of range components, I think this will be close to what you're looking for:

    use strict; use warnings; my @test = qw/1 5:10 18:14 21 24:25 31:28/; print get_reserved( \@test ), "\n"; sub get_reserved { my ( $bits_ref ) = @_; # should be an array ref return "bad call to get_reserved()" unless ( ref( $bits_ref ) eq 'ARRAY' and @$bits_ref ); my @reg32set; for my $spec ( @$bits_ref ) { if ( $spec =~ /(\d+):(\d+)/) { my ( $bgn, $end ) = sort {$a<=>$b} ( $1, $2 ); $reg32set[$_] = 1 for ( $bgn .. $end ); } else { $reg32set[$spec] = 1; } } my $verilog_string = ''; for my $seq ( 0 .. $#reg32set ) { if ( defined( $reg32set[$seq] )) { $verilog_string .= ", "; } else { $verilog_string .= "$seq:"; } } return "no intervals to report from get_reserved()" unless ( $verilog_string =~ /\d/ ); $verilog_string =~ s/(?<=\d):[\d:]+:(?=\d)/:/g; # e.g. "2:3:4:5:6 + -> 2:6 $verilog_string =~ s/^(?:, )+//; $verilog_string =~ s/:(?:, )*$//; $verilog_string =~ s/:,(?: ,)*/,/g; return $verilog_string; }
    (updated to add diagnostic messages for a couple of edge conditions)
      Thanks Graff for your patient instruction and comments.
      For the verilog syntax, you can check here: http://www.sutherland-hdl.com/online_verilog_ref_guide/vlog_ref_top.html
      In the section of "6.0 Module Port Declarations" you will know the port size definition.

      my code @digits ne '' might be a mistake, thanks for pointing it out. I supposed to do nothing if @digits contains no vars. You know otherwise, it would be warning msg prompted saying not a number index assign to $reg32set

      Regarding to your code, I think you idear is great. But I had to change the code $#reg32set in  for my $seq (0 .. $#reg32set) to 31 get what I need. The max index is always 32. By the way, you coding style is pretty good and I am trying to learn from you.

      Thanks again for everyone comments, and tolerating my confusing explanation. :)

      Hanken