[comp.sources.bugs] Making perl 2.0 core dump

tytso@athena.mit.edu (Theodore Y. Ts'o) (08/14/88)

I'm running perl 2.0 at patchlevel 13, and the following perl script
causes it to core dump on a Vax....

#!/mit/watchmaker/vaxbin/perl

$foo[0] = 4;
$foo[1] = 6;
$foo[2] = 13;
$foo[3] = 17;

do Bargraph("foo", @foo, 0, $#foo, 1, 0, 20, 1);

# This subroutine does bar graphs....
# Usage is as follows:
#
# do Bargraph($title, @array, $x_min, $x_max, $x_step, 
#			      $y_min, $y_max, $y_step)

sub Bargraph {
	local ($title, @array, $x_min, $x_max, $x_step,
			       $y_min, $y_max, $y_step) = @_;
	local($x, $y);

	for ($y=$y_max; $y < $y_min; $y += $y_step) {
		for ($x=$x_min; $x < $x_max; $x += $x_step) {
			if ($array[$x] <= $y) {
				print " ";
			} else {
				print "#";
			}
		}
		printf(" %2d\n", $y);
	}
}

What is the correct way of passing an array to a subroutine in Perl?
(Is there a way?).  Even if I'm doing it wrong, it probably shouldn't
be core dumping....  which it does on the "local($title.....) = @_;".

I haven't had a chance to analyze what's going wrong; but if anyone
has a fix or workaround for the problem, I'd appreciate it.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Theodore Ts'o				mit-eddie!mit-athena!tytso
3 Ames St., Cambridge, MA 02139		tytso@athena.mit.edu
   Everybody playing the game; but nobody rules are the same!

jgreely@banjo.cis.ohio-state.edu (J Greely) (08/15/88)

In article <6670@bloom-beacon.MIT.EDU> tytso@athena.mit.edu writes:
>[original code deleted]

The first problem is that you misunderstood how parameters are
passed to a subroutine:  "Any arguments passed to the routine come
in as array @_, ...".  You assumed that when you say 
"do some_sub($foo,@bar,$baz)", that "local($var1,@var2,$var3) = @_;"
would get back what you put in.  What really happens is that the
subroutine receives "@_ = ($foo,$bar[0] ... $bar[$#bar],$baz)."  Perl
doesn't understand what you were trying to do (but I think it
*should* have been an error rather than a core dump).

  The correct way to pass arrays is something like this: 
"do some_sub($foo,$#bar,@bar,$baz,'string')", and parse it like this:

  $local($var1,$v2count,$var3,$var4); #note: local arrays don't work
  $var1 = shift(@_);
  $v2count = shift(@_) + 1;
  while ($v2count--) {
    push(@var2,shift(@_));
  }
  ($var3,$var4) = @_;

The other problems were mostly simple bugs that you would have
caught fairly quickly.  Below is a functioning version of your
program (with a few little extras tossed in):

-------------------- cut here --------------------
#!/usr/local/bin/perl

@foo = (4,6,17,13);
do Bargraph("foo", $#foo,@foo, 0, $#foo, 1, 0, do max(@foo), 1);

#bargraph:
# print a primitive bargraph
#usage:
# do Bargraph($title, $count, $array[0] ... $array[$count], $x_min,
#             $x_max, $x_step, $y_min, $y_max, $y_step)

sub Bargraph {
  @printchars = ("#","%","*","$");
  local ($title, $count, $x_min, $x_max, $x_step,
                 $x, $y, $y_min, $y_max, $y_step);
  $title = shift(@_);
  $count = shift(@_) + 1;
  while ($count--) {
    push(@array,shift(@_));
  }
  ($x_min,$x_max,$x_step,$y_min,$y_max,$y_step) = @_;

  for ($y=$y_max; $y >= $y_min; $y -= $y_step) {
    for ($x=$x_min; $x <= $x_max; $x += $x_step) {
      if ($array[$x] < $y) {
        print "  ";
      } else {
        print " ",$printchars[$x];
      }
    }
    printf(" %2d\n", $y);
  }
}

#max:
# return largest numeric value in passed array
#
sub max {
  @_ = sort comp @_;
  return($_[$#_]);
}

#comp:
# numeric comparison routine for sort
#
sub comp {
  $a < $b ? -1 : $a > $b ? 1 : 0;
}
-------------------- cut here --------------------
-=-
J Greely  "...but would it be kidnapping, or grand theft auto?"
	  jgreely@cis.ohio-state.edu, 
	  {att,pyramid,killer}!cis.ohio-state.edu!jgreely

mkp@luna.UUCP (Michael Peterson) (08/15/88)

In article <6670@bloom-beacon.MIT.EDU> tytso@athena.mit.edu 
(Theodore Y. Ts'o) writes:
>I'm running perl 2.0 at patchlevel 13, and the following perl script
>causes it to core dump on a Vax....

[Original script... ]

Here's a script that works.

-------------------8<-------------------8<----------------------------------
#! /usr/bin/perl

# test case.
@foo = (4, 6, 3, 17);
do Bargraph("foo", 0, $#foo, 1, 0, 20, 1, @foo);

#
# This subroutine does bar graphs....
# Usage is as follows:
#
# do Bargraph($title, $x_min, $x_max, $x_step, 
#		      $y_min, $y_max, $y_step, @data)
sub Bargraph 
{
	local($x, $y);
	local($title = shift(@_));
	local($x_min = shift(@_));
	local($x_max = shift(@_));
	local($x_step = shift(@_));
	local($y_min = shift(@_));
	local($y_max = shift(@_));
	local($y_step = shift(@_));
	local(@data = @_);

	for ($y = $y_max; $y >= $y_min; $y -= $y_step) 
	{
		for ($x = $x_min; $x <= $x_max; $x += $x_step) 
		{
			$c = ($data[$x] <= ($y - 1)) ? " " : "#";
			print "$c";
		}
		printf(" %2d\n", $y);
	}
}


-- 
Michael K. Peterson		Internet: mkp@hac2arpa.hac.com
Space & Communications Group	UUCP: ....!{scgvaxd,hacgate.hac.com}!mkp
Hughes Aircraft Company
213 416-0323