How to make the script to return with specified value in Perl debugger? - perl

I tried various ways, but none works...
DB<4> T
. = main::t() called from file `dbg' line 6
DB<4> return;
DB<5> T
. = main::t() called from file `dbg' line 6
DB<5> return 1;
DB<6> T
. = main::t() called from file `dbg' line 6
DB<6> eval('return')
DB<7> T
. = main::t() called from file `dbg' line 6
The point is I don't want the subsequent code to be run, just return with specified value.
So it's not r.

This is obviously ghetto but you could wait until you pop back out of routine and then manually set the lvalue before proceeding in the calling routine.

Related

Device::BlinkyTape::SimulationPort error: 'x' outside of string in unpack

I am trying to get started using Device::BlinkyTape::SimulationPort, but when executing the simple example script below, I get the error:
'x' outside of string in unpack at /home/pi/perl5/lib/perl5/Device/BlinkyTape/SimulationPort.pm line 70.
Any idea how I can get it to work?
#!/usr/bin/env perl
use lib '../lib';
use Device::BlinkyTape::WS2811; # BlinkyTape uses WS2811
my $bb = Device::BlinkyTape::WS2811->new(simulate => 1);
$bb->all_on();
sleep 2;
$bb->all_off();
sleep 2;
$bb->send_pixel(255,255,255);
$bb->show();
sleep 2;
$bb->send_pixel(255,0,0);
$bb->show();
sleep 2;
$bb->send_pixel(240,0,0);
$bb->show();
sleep 2;
# Go crazy
for (my $b=0; $b<=1000; $b++) {
for (my $a=0; $a<=59; $a++) {
$bb->send_pixel(int(rand(254)),int(rand(254)),int(rand(254)));
}
$bb->show(); # shows the sent pixel row
}
sleep 2;
It looks like a bug in the module.
The Device::BlinkyTape POD BUGS section states:
The device is not yet available so the module has been implemented by
inspecting partly undocumented and unfinished code in other languages.
The module was last updated 8 years ago (2013); perhaps it is just a work-in-progress.
The module has no meaningful tests, as can be seen from the CPAN Testers results and the lack of Coverage results. Thus, there is no public evidence that the module works.
The code posted in the Question is from the simulate.pl example. Here is a minimal example which reproduces the problem:
use diagnostics;
use Device::BlinkyTape::WS2811;
my $bb = Device::BlinkyTape::WS2811->new(simulate => 1);
$bb->all_on();
I added diagnostics to get more information about the error. Here is my output:
simulation on. at lib/perl5/Device/BlinkyTape.pm line 114.
'x' outside of string in unpack at
lib/perl5/Device/BlinkyTape/SimulationPort.pm line 70 (#1)
(F) You had a pack template that specified a relative position after
the end of the string being unpacked. See "pack" in perlfunc.
Uncaught exception from user code:
'x' outside of string in unpack at lib/perl5/Device/BlinkyTape/SimulationPort.pm line 70.
Device::BlinkyTape::SimulationPort::write(Device::BlinkyTape::SimulationPort=HASH(0x348b050), "\x{fe}") called at lib/perl5/Device/BlinkyTape/WS2811.pm line 34
Device::BlinkyTape::WS2811::send_pixel(Device::BlinkyTape::WS2811=HASH(0x3481fe0), 255, 255, 255) called at lib/perl5/Device/BlinkyTape.pm line 137
Device::BlinkyTape::all_on(Device::BlinkyTape::WS2811=HASH(0x3481fe0)) called at line 4
Here is line 70:
my $b = unpack("x2 C1", $color);
The next step is to report this issue and try to get an update on the status of the module.

Perl hash while loop cannot find the key value

I am confused by one perl question, anyone has some idea?
I use one hash structure to store the keys and values like:
$hash{1} - > a;
$hash{2} - > b;
$hash{3} - > c;
$hash{4} - > d;
....
more than 1000 lines. I give a name like %hash
and then, I plan to have one loop statement to search for all keys to see whether it will match with the value from the file.
for example, below is the file content:
first line 1
second line 2
nothing
another line 3
my logic is:
while(read line){
while (($key, $value) = each (%hash))
{
if ($line =~/$key/i){
print "found";
}
}
so my expectation is :
first line 1 - > return found
second line 2 - > return found
nothing
another line 3 - > return found
....
However, during my testing, only first line and second line return found, for 'another line3', the
program does not return 'found'
Note: the hash has more than 1000 records.
So I try to debug it and add some count inside and find out for those found case, the loop has run like 600 or 700 times, but for the 'another line3' case, it only runs around 300 times and just exit the loop and did not return found.
any idea why it happens like that?
and I have done one more testing is if my hash structure is small, like only 10 keys, the logic works.
and I try to use foreach, and It looks like foreach does not have this kind of issue.
The pseudo code you give should work fine, but there might be a subtle problem.
If after you found your key and print it out you end the while loop, the next time each is called, it will continue where you left. Put it in other words "each" is an iterator that stores its state in the hash it iterates over.
In http://blogs.perl.org/users/rurban/2014/04/do-not-use-each.html the author explains this in more detail. His conclusion:
So each should be treated as in php: Avoid it like a plague. Only use it in optimized cases where you know what you are doing.
The problem is not very well articulated by OP, provided sample data are poor for demonstration purpose.
Following sample code is an attempt based on provided problem description by OP.
Recreate filter hash from DATA block, compose $re_filter consisting of filter hash keys, walk through a file given as an argument on command line to filter out lines matching $re_filter.
use strict;
use warnings;
my $data = do { local $/; <DATA> };
my %hash = split ' ', $data;
my $re_filter = join('|',keys %hash);
/$re_filter/ && print for <>;
__DATA__
1 a
2 b
3 c
4 d
Input data file content
first line 1
second line 2
nothing
another line 3
Output
first line 1
second line 2
another line 3

Multiple text parsing and writing using the while statement, the diamond operator <> and $ARGV variable in Perl

I have some text files, inside a directory and i want to parse their content and write it to a file. So far the code i am using is this:
#!/usr/bin/perl
#The while loop repeats the execution of a block as long as a certain condition is evaluated true
use strict; # Always!
use warnings; # Always!
my $header = 1; # Flag to tell us to print the header
while (<*.txt>) { # read a line from a file
if ($header) {
# This is the first line, print the name of the file
**print "========= $ARGV ========\n";**
# reset the flag to a false value
$header = undef;
}
# Print out what we just read in
print;
}
continue { # This happens before the next iteration of the loop
# Check if we finished the previous file
$header = 1 if eof;
}
When i run this script i am only getting the headers of the files, plus a compiled.txt entry.
I also receive the following message in cmd : use of uninitialized $ARGV in concatenation <.> or string at concat.pl line 12
So i guess i am doing something wrong and $ARGV isn't used at all. Plus instead of $header i should use something else in order to retrieve the text.
Need some assistance!
<*.txt> does not read a line from a file, even if you say so in a comment. It runs
glob '*.txt'
i.e. the while loop iterates over the file names, not over their contents. Use empty <> to iterate over all the files.
BTW, instead of $header = undef, you can use undef $header.
As I understand you want to print a header with the filename just before the first line, and concatenate them all to a new one. Then a one-liner could be enough for the task.
It checks first line with variable $. and closes the filehandle to reset its value between different input files:
perl -pe 'printf qq|=== %s ===\n|, $ARGV if $. == 1; close ARGV if eof' *.txt
An example in my machine yields:
=== file1.txt ===
one
=== file2.txt ===
one
two

Add to Perl hash yields puzzling results

I am somewhat new to Perl, and this bug has puzzled me for a couple of days. I've had difficulty finding anything on Google for a problem this specific. I will try to present the "clues" as clearly as possible. I am using Perl v5.16.1. The relevant lines in my code are these:
my %result = ();
...
$result{'TABLENAME'} = $tableName;
...
for my $i (1..$numberOfColumns) {
$result{$columnNames[$i-1]} = $columnValues[$i-1];
}
In my test, $numberOfColumns is 7. The problem is that the for-loop does not create the key-value pairs as I expect. I will explain. I've tried debugging using Perl's debugger with perl -d. The debugger output below shows things going fine until the last line.
DB<2> c 219
testcode::testsub(modules/testcode.pm:219):
219: $result{'TABLENAME'} = $tableName;
DB<3> c 239
testcode::testsub(modules/testcode.pm:239):
239: for my $i (1..$numberOfColumns) {
DB<4> p %result
TABLENAMEmyowntableitis
DB<5> p $result{TABLENAME}
myowntableitis
DB<6> s
testcode::testsub(modules/testcode.pm:240):
240: $result{$columnNames[$i-1]} = $columnValues[$i-1];
DB<6> p $i
1
DB<7> p $columnNames[0]
id
DB<8> p $columnValues[0]
1
DB<9> s
testcode::testsub(modules/testcode.pm:240):
240: $result{$columnNames[$i-1]} = $columnValues[$i-1];
DB<9> p $i
2
DB<10> p %result
TABLENAMEmyowntableitisid
1
DB<11> p $result{TABLENAME}
myowntableitis
DB<12> p $result{id}
DB<13>
I expected the last p $result{id} to return 1 instead of nothing. Does anyone have an idea what could be happening here?
If we look at DB<10>, we see that the 1 is printed on the next line:
DB<10> p %result
TABLENAMEmyowntableitisid
1
This means that $result{"id\n"} eq "1", and you are using an undefined key.
A style note: foreaching over two arrays to build a hash is possible, of course. But then again, Perl has slices, which makes life much easier (unless you are processing incredible large amounts of data)
#result{#columnNames} = #columnValues;
(assuming #columnNames <= #columnValues)
The problem is that columnnames[0] is set to "id\n" and not just id. Notice the newline after the id. I guess you were reading these from a file and not removing the newlines. The same is true for the values. Add to your loop:
chomp $columnNames[$i-1];
chomp $columnValues[$i-1];
and that should fix your problem. Alternatively, you could chomp the values when you read them from the file.
On a side note, it's customary to have the loop counter be the index itself. That is loop from 0 to $numberOfColumns - 1 or (even to $#columnNames).
If $result{id} is empty, what does $result{"id\n"} return? You might be not chomping the lines.

Script dies if a module that doesnt exist is used during sort() - DateTime::TimeZone::Local example

use DateTime::TimeZone::Local;
use Test::More tests => 1;
my #input = (1 .. 10 );
my (#output) = sort {
DateTime::TimeZone::Local->TimeZone();
$a cmp $b
} #input;
is_deeply(\#output, \#input);
Output:
1..1
Can't return outside a subroutine at /usr/local/share/perl/5.8.8/DateTime/TimeZone/Local.pm line 72.
# Looks like your test exited with 9 before it could output anything.
shell returned 9
I have checked and it definitely is inside a sub routine. It doesn't appear to be anything to do with the module used, this code also causes the same error:
my #output = sort {
sub1();
} (1 .. 5);
sub sub1 {
eval "use ModuleDoesntExist";
return 1; # remove this and get a seg fault
}
Looks like it is a bug in perl more than anything. Any ideas? More interested in why this is happening than a workaround - it only occurs if the module doesn't exist.
It looks as though it is actually a bug in Perl. See this thread on the Perl Porters list.