Search code examples
perlunicodeutf-8

perl debugger and utf8 variable names


I'm having troubles debugging a Perl program where variable names (or hash key) are UTF-8 strings. The program compiles ok (and runs) but whenever I want to debug it, the debugger is quite unhappy with the variable/hash key names if I need to use them.

Here is a (very simple) MWE:

use strict;

use utf8;
use warnings  qw(FATAL utf8);
use open      qw(:std :encoding(UTF-8));
use charnames qw(:full :short);

my $unité = 125;
my %hash = ( 'Quantité' => 18 );

printf "%d\n", $unité*$unité;
printf "%d\n", $hash{Quantité};

When running, no problem :

$ perl test.pl 
15625
18

But when debugging, the debugger is very sad :

$ perl -d test.pl

Loading DB routines from perl5db.pl version 1.77
Editor support available.

Enter h or 'h h' for help, or 'man perldebug' for more help.

            HistFile = '/home/XXX/.perldb.hist'
Éxécution afterinit
main::(test.pl:10):     my $unité = 125;
  DB<100> n
main::(test.pl:11):     printf "%d\n", $unité*$unité;
  DB<100> p $unité
Unrecognized character \xC3; marked by <-- HERE after T}   $unit<-- HERE near column 120 at (eval 10)[/usr/lib64/perl5/5.38/perl5db.pl:742] line 2.
 at (eval 10)[/usr/lib64/perl5/5.38/perl5db.pl:742] line 2.
        eval 'no strict; ($@, $!, $^E, $,, $/, $\\, $^W) = @DB::saved;package main; $^D = $^D | $DB::db_stop;
print {$DB::OUT}   $unité;
' called at /usr/lib64/perl5/5.38/perl5db.pl line 742
        DB::eval called at /usr/lib64/perl5/5.38/perl5db.pl line 3451
        DB::DB called at test.pl line 11

So, how can I access an UTF8-named variable (same problem with the hash key)?


Solution

  • Have you set the debuggers input layer correctly? The debugger has its own in/out handles named $DB::IN and $DB::OUT

    For me setting the :utf8 layer for $DB::IN works (with a utf-8 terminal):

    main::(test.pl:10): my $unité = 125;
      DB<1> n
    main::(test.pl:11): my %hash = ( 'Quantité' => 18 );
      DB<1> p unité
    Unrecognized character \xC3; marked by <-- HERE after UT}   unit<-- HERE near column 119 at (eval 10)[/home/chris/perl5/perlbrew/perls/perl-5.32.0/lib/5.32.0/perl5db.pl:738] line 2.
     at (eval 10)[/home/chris/perl5/perlbrew/perls/perl-5.32.0/lib/5.32.0/perl5db.pl:738] line 2.
        eval 'no strict; ($@, $!, $^E, $,, $/, $\\, $^W) = @DB::saved;package main; $^D = $^D | $DB::db_stop;
    print {$DB::OUT}   unité;
    ' called at /home/chris/perl5/perlbrew/perls/perl-5.32.0/lib/5.32.0/perl5db.pl line 738
        DB::eval called at /home/chris/perl5/perlbrew/perls/perl-5.32.0/lib/5.32.0/perl5db.pl line 3138
        DB::DB called at test.pl line 11
    
      DB<2> binmode($DB::IN, ':utf8');
    
      DB<3> p $unité    
    125
      DB<4> 
    

    You can use a .perldb file to always run code on startup in the debugger. For example a .perldb file containing the following will always switch your $DB::IN/OUT handles to utf-8:

    sub afterinit{
        binmode($DB::IN, ':utf8');
        binmode($DB::OUT, ':utf8');
    }
    

    .perldb must not be writable by anyone except the owner (which has to be the current user). See the documentation.