Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

The Monastery Gates

( #131=superdoc: print w/replies, xml ) Need Help??

If you're new here please read PerlMonks FAQ
and Create a new user.

Quests
poll ideas quest 2021
Starts at: Jan 01, 2021 at 00:00
Ends at: Dec 31, 2021 at 23:59
Current Status: Active
2 replies by pollsters
    First, read How do I create a Poll?. Then suggest your poll here. Complete ideas are more likely to be used.

    Note that links may be used in choices but not in the title.

Perl News
Quadmath builds of perl for MS Windows
on Feb 20, 2021 at 23:14
2 replies by syphilis
    Not sure that anyone here is particularly interested in this, but I'll mention it anyway that, as of the release (on 20.01.2021) of perl-5.33.6, it's possible to build perl on MS Windows with an NV type of __float128.
    And it has become a little easier in 5.33.7 with a change to GNUmakefile that removed the need for a somewhat cumbersome configuration argument.
    With the release of perl-5.22.0, the NV type of long double was enabled on Windows, and now we finally get the additional option of having the __float128 NV type.
    All of this does, of course, rely on using mingw-w64 ports of gcc to build your Windows perl.

    I think that many of us, accustomed to simply using Strawberry Perl, don't realize just how easy it is to build perl from source on Windows.
    Strawberry Perl, itself, does provide us with the toolchain that's capable of building any recent version of perl (including blead releases) from source.
    The latest blead source can be obtained with:
    $ git clone https://github.com/sisyphus/perl5.git blead_clone
    or the perl-5.33.7 development tarball is available from:
    https://cpan.metacpan.org/authors/id/R/RE/RENEEB/perl-5.33.7.tar.gz
    Then, I place my C:\_64\strawberry-5.32.0\c\bin folder at the beginning of my PATH, and I have all that I need to build perl.
    Simply cd to the perl source's win32 folder and run:
    gmake INST_TOP=C:\bleadstraw CCHOME=C:\_64\strawberry-5.32.0\c CCTYPE= +GCC I_QUADMATH=define USE_QUADMATH=define test
    Then, to install perl into the location specified by INST_TOP, just run:
    gmake INST_TOP=C:\bleadstraw CCHOME=C:\_64\strawberry-5.32.0\c CCTYPE= +GCC I_QUADMATH=define USE_QUADMATH=define install
    And that's it - in C:\bleadstraw I now have a Windows perl that has __float128 as its NV.

    You may want to alter INST_TOP, and you probably need to alter CCHOME which should specify the full path to gcc's bin directory.
    NOTE that CCHOME does not include "\bin". (Failure to get CCHOME right will cause some test failures, but will not affect the perl that has been built.)

    If you want to do a 'long double' build instead, you would just remove the 2 gmake arguments that include the string "QUADMATH", and insert the USE_LONG_DOUBLE=define argument.
    If you don't request either a 'long double' or a 'quadmath' build, then the nvtype will be 'double'.

    If you're using a 32-bit compiler, you'll also need to insert the argument WIN64=undef, and you might also want to add the argument USE_64_BIT_INT=define if you want 64-bit integers and pointers.
    With 64-bit compilers, perl's integer and pointer will inevitably be 64-bit.

    I think that covers the most commonly exercised options ... but you'll find additional options laid out in the GNUmakefile.

    I don't know if it's a general issue, but (on 64-bit builds only) there's usually a couple of test scripts in cpan/IO-Compress/t that hang for me .
    Update: This issue is a long-standing one for me, and is not limited to just the "quadmath" builds.
    It's generally (but not always) the same test scripts that hang, and it has been happening for a few years. In perl-5.33.7, I'm finding that the problem has moved to a different couple of files.
    The Strawberry project have never, to my knowledge, complained about such an issue - so I'm hoping that it's just something in my particular environment.
    It would be nice to find out if it is "just me".
    It's quite annoying - I have to kill these hangs using process explorer in order to get the test suite to run to completion. (Killing them with Ctrl-C kills the entire 'gmake test' process.)
    These test scripts have always passed when run outside of the testing harness, and they've also passed even when I've run make test in the cpan/IO-Compress folder.
    There's also the same thing happening in the cpan/IPC-Cmd tests with t/01_IPC-Cmd.t.
    If I can find any evidence that it's also an issue for others then I'll try to get it fixed.

    Oh, one last thing - if you build a 32-bit perl with I_QUADMATH=define USE_QUADMATH=define but without USE_64_BIT_INT=define, then expect some failing tests in Math::BigFloat due to a Math::BigInt::Calc bug.
    This issue has been reported, with a proposed simple fix to Calc.pm.

    Cheers,
    Rob
berrybrew version 1.33 released!
on Feb 12, 2021 at 18:10
1 reply by stevieb

    I've released berrybrew version 1.33. This version has significant enhancements, along with some bug fixes and handling of some uncaught exceptions. The changes reflect versions 1.30 to 1.33.

    Major changes include:

    UI:

    • Allows you to install, switch to, remove and use Strawberry Perls directly
    • Can now spawn a CLI window for any Perl you have installed
    • Allows you to spawn a CLI window for the currently active Perl
    • Provides access to modify several of the core configuration options (debug, file association etc)
    • Allows you to disable all berrybrew Perls and restore to system default

    Installer:

    • Performs an upgrade on any previous berrybrew install
    • Adds any new configuration options, while preserving the values of any previously set existing ones
    • Provides facility to install the most recent version of Strawberry Perl
    • Allows you to have berrybrew manage the .pl file association
    • Allows you to have the UI run at system startup
    • Aborts if trying to install the same version that's already installed

    Functionality:

    • You can now leave off the _32/_64 bit prefix on a Perl name, and we'll default to _64
    • All execution paths return a proper exit code
    • Added new berrybrew hidden command, lists all, well, hidden commands

    For all other changes, please refer to the Changes file.

    Cheers!

    -stevieb

Supplications
Introspecting function signatures
2 direct replies — Read more / Contribute
by szabgab
on Mar 05, 2021 at 09:45
    Given a function using signatures like this:
    use strict; use warnings; use 5.020; use feature 'signatures'; no warnings 'experimental::signatures'; sub hello($name, $age) { print "$name\n"; }
    I am looking for a way to list the variables it is expecting during run time. Using the solution from this post using
    B::Deparse->new->coderef2text(\&hello);
    I managed to write some code that works for me that I can turn into a CPAN module, but I wonder if there is already one that does that and I missed it?
How can I combine these two regular expressions?
5 direct replies — Read more / Contribute
by thirtySeven
on Mar 04, 2021 at 21:41
    I have a bunch of file paths that look like $path. I want to get the yyyy_mm_dd_hh_mm out of the end of the path. I currently have a working solution ... but I want to know if it is possible to combine the entire thing into one expression if only for learning purposes. I am wondering if it can't work because of the way I am mixing in a list context.
    # This works my $path = '/.snapshots123/yabsm/root/hourly/day=2021_03_04,time=21:20 +'; my $end_of_path = $1 if $path =~ m/([^\/]+$)/; my @nums = $end_of_path =~ m/([0-9]{2,4})/g;
    I have tried to quite literally combine them but it did not work:
    # This does not work my @nums = m/([0-9]+)/g =~ $1 if $path =~ m/([^\/]+$)/;
    I would appreciate insight.
goto &method and skipping call frame
3 direct replies — Read more / Contribute
by LanX
on Mar 04, 2021 at 15:12
    Hi

    goto &NAME is a way to call a sub NAME() while autoloading and transparently skipping the actual frame for sub AUTOLOAD() on the call stack.

    Hence caller wouldn't show AUTOLOAD but the line which triggered it.

    That's also of practical importance when using carp() et al from Carp , because you don't wanna get the error shown inside the AUTOLOAD's code.

    But what if I want to delegate to a method from an autoloaded sub?

    My best guess is to call it as a normal sub and to prepend the object to @_

    sub AUTOLOAD { #warn pp "$AUTOLOAD $OBJ=>",\@_; (my $meth = $AUTOLOAD) =~ s/^.*://; if (my $c_ref = $OBJ->can($meth)) { unshift @_,$OBJ; goto &$c_ref; } }

    And - to my big surprise - this is even respecting inheritance, i.e. if the method belongs to a super-class of OBJ, it's properly delegated.

    Questions:

    • Any cleaner way to do this?
    • Any side effects I forgot?

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

    PS: Hey Mike can't wait to hear about your huge "expertise" from JAVA, bread-trucks and millions of lines of PHP ...

    UPDATE

    2 monks msged me Where does $OBJ come from?

    In this simplified example you can consider it a global, like

    our $OBJ = SomeClass->new();

    The real use case is a more complicated implementation of a with construct (like in with), where $OBJ is a closure var and AUTOLOAD is localized to a blocks context.

STDERR and CGI::CARP
4 direct replies — Read more / Contribute
by Schmunzie
on Mar 04, 2021 at 08:15
    Dear Wise Monks, I use CGI::Carp to view errors in the web browser during development. In production, I would like to divert STDERR to a logfile. I after bright ideas for an efficient and reliable way of switching between the two. Thanks
Problem filling Excel cells with Solid Colour
1 direct reply — Read more / Contribute
by merrymonk
on Mar 03, 2021 at 05:29
    I want to fill the background of excel cells with colours made up from the known red, green and blue components of the colours. To do this I found I needed to use:
    $sheet->Range($rng)->Interior -> {PatternColor} = rgb colour value
    $sheet->Range($rng)->Interior -> {Pattern} = pattern value
    This site https://docs.microsoft.com/en-us/office/vba/api/Excel.XlPattern gives ‘values’ for 20 patterns including xlPatternSolid which I thought would give me the whole cell filled with that colour. This was not the case as the Perl below shows.
    This code gives an Excel spreadsheet where:
    Column C is the key to a hash which holds the pattern ‘names’ such as xlPatternSolid
    Column D gives the cell filled with the colour and effect of the pattern
    Column E gives the value of the pattern ‘names’ as shown on the web-site.
    Cell D20 is where the xlPatternSolid has been used. This has no colour instead of the solid colour I was hoping for. Also cell D3 has no colour – the name of this colour pattern xlPatternAutomatic – I was not sure what to expect for this.
    I did notice that the sides of cells D20 and D3 are no longer there.
    How can I get cells filled with the solid colour?
    use strict "vars"; use OLE; use Win32::OLE::Const "Microsoft Excel"; sub RGB ($$$$) { my ($jr, $jg, $jb, $ret_c) =@_; $$ret_c = $jr + $jg * 256 + $jb *256** 2; } my ($excel, $workbook, $sheet, $rng, $jh); my ($jr, $jg, $jb, $patterncolour, $jq, $jqa); my %cell_interior_pattern; # list from https://docs.microsoft.com/en-us/office/vba/api/Excel.XlPa +ttern $cell_interior_pattern{1} = xlPatternAutomatic; $cell_interior_pattern{2} = xlPatternChecker; $cell_interior_pattern{3} = xlPatternCrissCross; $cell_interior_pattern{4} = xlPatternDown; $cell_interior_pattern{5} = xlPatternGray16; $cell_interior_pattern{6} = xlPatternGray25; $cell_interior_pattern{7} = xlPatternGray50; $cell_interior_pattern{8} = xlPatternGray75; $cell_interior_pattern{9} = xlPatternGray8; $cell_interior_pattern{10}= xlPatternGrid; $cell_interior_pattern{11}= xlPatternHorizontal; $cell_interior_pattern{12}= xlPatternLightDown; $cell_interior_pattern{13}= xlPatternLightHorizontal; $cell_interior_pattern{14}= xlPatternLightUp; $cell_interior_pattern{15}= xlPatternLightVertical; $cell_interior_pattern{16}= xlPatternNone; $cell_interior_pattern{17}= xlPatternSemiGray75; $cell_interior_pattern{18}= xlPatternSolid; $cell_interior_pattern{19}= xlPatternUp; $cell_interior_pattern{20}= xlPatternVertical; $excel = CreateObject OLE "Excel.Application"; $excel -> {Visible} = 1; $workbook = $excel -> Workbooks -> Add; $sheet = $workbook -> Worksheets("Sheet1"); $sheet -> Activate; $sheet -> Range('C2') -> {Value} = 'Index'; $sheet -> Range('D2') -> {Value} = 'Colour'; $sheet -> Range('E2') -> {Value} = 'Value of array index'; $jr = 120; $jg = 140; $jb = 55; RGB($jr, $jg, $jb, \$patterncolour); for $jq (sort {$a <=> $b} keys %cell_interior_pattern) { $jqa = $jq + 2; $rng = 'D' . $jqa; $sheet->Range($rng)->Interior -> {PatternColor} = $patternco +lour; $sheet->Range($rng)->Interior -> {Pattern} = $cell_interior_ +pattern{$jq}; $rng = 'E' . $jqa; $sheet -> Range($rng) -> {Value} = $cell_interior_pattern{$jq}; $rng = 'c' . $jqa; $sheet -> Range($rng) -> {Value} = $jq; }
How to use Plack::Middleware::Static
1 direct reply — Read more / Contribute
by vhein79
on Mar 03, 2021 at 05:11
    Hi!

    I run a website, changing now from FCGI to PSGI using Plack as server. The behaviour should be the same as with the old Apache website, (which I configured with .htaccess files for each directory) so I want to use js when it is needed, and show it as text/plain when someone clicks such a non binary file in my download directory.

    I don't want to use dancer etc now, because I had to make big changes to the website then (FCGI and PSGI are quite similar to use). I tested a bit and the behaviour seems to be version dependent (on Windows it works, on CentOS not), but I want a safe way using different Plack::MIME instances for different directories.

    What I have now uses the same Plack::MIME instance and doesn't work correctly when I include .html, .css etc there:

    use Plack::Builder; use Plack::MIME; # normal behaviour /html/ # special behaviour /html/downloads/ for my $expr ( ".c", ".cpp",".csv", ".dat", ".dpl" , ".gp", ".h", ".hpp", ".ini" , ".java", "makefile", ".m", ".mac" , ".pl", ".pm", ".pod", ".py" , "README", ".sch", ".sh", ".txt") { Plack::MIME->add_type($expr => 'text/plain'); } builder { enable 'Plack::Middleware::Static', path => qr{/html/}, root => '.'; # normal behaviour: # needs a new content_type instance! how doing this? # enable 'Plack::Middleware::Static', # path => qr{^/html/(?!downloads).*\. # (css|gif|jpg|js|pdf|png)$}, root => '.'; mount "/" => $app1; mount "/imggenerator.pl" => $app2; };
    I could treat every single file in my $app1, but I think configuring that with Plack should be possible.

Use of do() to run lots of perl scripts
8 direct replies — Read more / Contribute
by chrestomanci
on Mar 02, 2021 at 12:34

    I am working on an legacy perl application that frequently invokes other perl scripts. The application runs as a server, and in response to each remote connection it does a fork and the child invokes another worker script via a system call. Most but not all of these scripts are perl.

    There are about 500 perl scripts that could be run, and most are trivial. The volume of incoming connections is high, and the application has performance issues, which I suspect are in part caused by the overhead of invoking a fresh perl interpreter for each of these trivial scripts.

    I searched online and found the do builtin in perl and this article about it.

    Would it make sense to modify my application so that worker perl scripts are invoked via do() instead of system calls?

    I am running perl 5.10 via Carton (The legacy app is not compatible with more recent perl versions due to use of Storable)

    Would there be any issue with non-trivial perl scripts?

    Do I need to wrapper the call to do() in an eval block or does that happen automatically?

    Bear in mind that the caller of each worker script is a forked child from the main server process, so if the worker script goes wrong in some way such as leaking memory, the main server process is in the parent so should not be affected.

    There are no security concerns here. All the code is trusted, and was written by company employees, so I only have to worry about mistakes, not malice.

Adding to legacy application: does it make sense to use PSGI in CGI mode
6 direct replies — Read more / Contribute
by hotpelmen
on Mar 01, 2021 at 22:07

    Hello Monks,

    There's a 20 yr old Perl/CGI web application that currently runs on Apache 2.4 and uses Perl 5.16. Linux box it runs on has one IP address and has no associated domain name.

    It is still being actively used inside my company by a dozen of employees, and I was asked to add a new page to it (standard interaction with database and displaying of results in the browser). I may have to add a page or two again within a year or two, so looking ahead I want to use something better and newer than 'use CGI' and print.

    Looks like in my situation I can't just add Dancer2-based scripts to legacy application as Dancer's routing seems to require a separate VirtualHost that I can't create in this no-domain single-IP situation. So I am thinking to use middle path: Template for HTML part of it, and I was advised to use PSGI in CGI mode for interacting with Apache instead of using CGI.pm.

    Using PSFI in CGI mode looks easy to do, but I am new to it and I am trying to avoid any path that may make me regretful later. Based on your experience and wisdom, what will be the immediate benefits of using PSGI/Plack for the new page, and is there anything I should beware of? Other thoghts?

    Thank you!

Three argument version of open '>-' (updated)
4 direct replies — Read more / Contribute
by choroba
on Mar 01, 2021 at 16:42
    In an ancient part of the code at work, we use
    open my $output, '>-' or die $!;

    Perl::Critic complains about it and wants us to replace it with a three argument variant. But, what's the 3-arg variant of >-?

    I thought

    open my $output, '>&', *STDOUT or die $!;
    might be the same, but it isn't, cf.
    open my $output, '>-' or die $!; close *STDOUT; print {$output} "This fails with Bad file descriptor";
    versus
    open my $output, '>&', *STDOUT or die $!; close *STDOUT; print {$output} "This prints OK\n";

    Then I tried with

    my $output = *STDOUT;
    but it's different, too:
    close STDOUT; print {$output} 'Besides Bad file descriptor, this will also warn "print() on clos +ed filehandle STDOUT"';

    Is there a three-argument version of open that behaves the same as '>-'?

    Update: Here's a SSCCE. Closing STDOUT is a global state, so call this with an argument (1, 2, 3, 4) to test a particular implementation.

    #!/usr/bin/perl use strict; use warnings; sub original { open my $output, '>-' or die $!; $output } sub assign { my $output = *STDOUT; $output } sub dup { open my $output, '>&', *STDOUT or die $!; $output } sub fn { open my $output, '>>&=', *STDOUT->fileno or die $!; $output } use Test::More; sub test { my ($open) = @_; my @W; local $SIG{__WARN__} = sub { push @W, @_ }; my $output = $open->(); close *STDOUT; my $v = print {$output} "abc\n"; isnt $v, 1, 'fails'; like $!, qr/Bad file descriptor/, 'Exception'; is scalar @W, 0, 'no warnings'; chomp, diag "($_)" for @W; done_testing(); } my %dispatch = (1 => \&original, 2 => \&assign, 3 => \&dup, 4 => \&fn); my $what = shift; my $code = $dispatch{$what} or die 'Not associated'; test($code);

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Controlling resize of Tk::Panedwindow
7 direct replies — Read more / Contribute
by hv
on Mar 01, 2021 at 13:47

    I am very new to Tk - and to anything graphical in general - so I may well be missing fundamentals.

    I'm trying to create a view showing a fragment of a larger world (A), with a pane below for control options (C), and a pane to the right showing details of an element in the world (B):

      +-------+---+
      |       |   |
      |   A   | B |
      |       |   |
      +-------+---+
      |     C     |
      +-----------+
    

    I'm using a horizontal Panedwindow for A, B, and a vertical Panedwindow for A+B, C, so the user can control the width of B and the height of C. When the window is resized, I want the width of B and height of C to stay constant, and the primary window A to shrink or grow as needed, hopefully with some event I can bind to update its contents. However the opposite is happening: A stays constant, and the other two resize.

    I suspect this is the nature of a Panedwindow: if I swap the order I add A and B to the upper pane, for example, the size of B stays fixed on resizing (but it's now on the left). However I don't see anything in the docs for Panedwindow to control this, nor do I see in the code how it handles resizing events. Can someone suggest how to achieve the effect I want?

    Update: as pointed out by choroba, this is the nature of a Panedwindow. So can someone point to how that is implemented, so I can create a variant of a different nature?

    Another update: in Tk-8.5, panes in a Panedwindow acquired a new stretch attribute that controls how new space is allocated among them. 8.5 also includes ttk, which has its own variant of Panedwindow; this one lets you specify a weight attribute on panes for even finer-grained control. Current Perl-Tk is based on Tk-8.4, so I guess I need to go bug Slaven. I did this in issue 75, which got a comment from chrstphrchvz.

    More: tybalt89++ offered a solution in Re: Controlling resize of Tk::Panedwindow which looks to do exactly what I want; I'll be going with that for now. An Anonymous monk looking a lot like zentara also pointed me at a couple of alternative Panedwindow implementations in Re: Controlling resize of Tk::Panedwindow (IDELayout IDEpanedwindow), but the one of those I looked at seems quite buggy. kcott also offered a decent cut-down solution in Re: Controlling resize of Tk::Panedwindow if I didn't mind losing the user-controllable aspect of paned windows.

    Hugo

    #!perl use strict; use warnings; use Tk; my $main_window = MainWindow->new; my $top_container = $main_window->Panedwindow(-orient => 'vertical'); $top_container->pack( -side => 'top', -expand => 'yes', -fill => 'both', -padx => '2m', -pady => '2', ); my $world_container = $top_container->Panedwindow(-orient => 'horizont +al'); $world_container->pack( -side => 'top', -expand => 'yes', -fill => 'both', -padx => '2', -pady => '2m', ); $top_container->add($world_container); my $world_view = $world_container->Canvas(); $world_view->pack( -side => 'left', -fill => 'both', -expand => 1, ); $world_container->add($world_view); my $entity_view = $world_container->Frame(); $entity_view->pack( -side => 'right', -fill => 'y', -expand => 0, ); $world_container->add($entity_view); my $control_view = $top_container->Frame; $control_view->pack( -side => 'bottom', -fill => 'x', -expand => 0, ); $top_container->add($control_view); my $quit_button = $control_view->Button( -text => 'Quit', -command => sub { $main_window->destroy }, ); $quit_button->pack( -side => 'right', -expand => 'no', -pady => 2, ); Tk::MainLoop();
Verbose Tk Code
7 direct replies — Read more / Contribute
by LanX
on Feb 28, 2021 at 13:22
    Hi

    I was meditating about designing DSLs and especially how to robustly implement with like in JS to a have clearer and less verbose code.

    So I thought to use Tk as a use case and found this 20 year old https://www.perl.com/media/_pub_1999_10_perltk_index/sld001.htm demo.

    The code is extremely verbose and I'm asking myself if this is really state of the art.

    For instance the code from https://www.perl.com/media/_pub_1999_10_perltk_index/sld010.htm

    Is it really necessary to always repeat ...

    • -background => 'cyan'
    • ->pack()
    • and finally my $t1 looks like sloppy code which will generate warnings

    my $t1 = $left1->Label(-text => ' ', -background => 'cyan')->pack(); my $t1 = $left1->Label(-text => ' Day ', -background => 'cyan')->pack(); my $t1 = $left1->Label(-text => ' Week ', -background => 'cyan')->pack(); my $t1 = $left1->Label(-text => ' Month ', -background => 'cyan')->pack(); my $t1 = $left1->Label(-text => ' Year ', -background => 'cyan')->pack();

    If needed I'd rather implement a helper like:

    with ($left1) { default -background => 'cyan'; chain { pack() }; Label(-text => ' '); Label(-text => ' Day '); Label(-text => ' Week '); Label(-text => ' Month '); Label(-text => ' Year '); }

    (pseudocode)

    But before reinventing the wheel I'd like to discuss my doubts. =)

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

SQL Placeholders - clarification
6 direct replies — Read more / Contribute
by Bod
on Feb 28, 2021 at 06:57

    Over on Re^6: Splitting the records into multiple worksheets, hippo pointed out the error of my ways and I have been going through some code that's being produced to implement placeholders. Can I please check that I am now on the right lines and doing things better...

    I had this line of code...

    $dbh->do("INSERT INTO Web_Page SET template = '$request', test = '$tes +t', source = '$data{'source'}', Visitor_idVisitor = $cookie{'_ls_visi +t'}") unless $$vars{'testpage'};
    All the variables are generated within the code except $data{'source'} which is derived from the HTTP query string and therefore potentially unsafe.

    I have replaced that line of code with this...

    unless ($vars->{'testpage'}) { my $query = $dbh->prepare("INSERT INTO Web_Page SET template = '$r +equest', test = '$test', source = ?, Visitor_idVisitor = $cookie{'_ls +_visit'}"); $query->execute($data{'source'}); }
    Is that the best approach or should I be using placeholders for every variable, even those I have declared and therefore know are safe?

Cool Uses for Perl
Simple CLI calculator based on Perl's eval()
6 direct replies — Read more / Contribute
by reisinge
on Mar 03, 2021 at 12:27

    Sometimes I need to do a quick calculation. I'm too lazy to open a GUI calculator and I never remember whether it's bc or dc (not mentioning the syntax). So I placed this code into ~/bin/calc:

    #!/usr/bin/perl -sT use strict; use warnings; use bignum; # Command line options... our ($h, $b, $x, $c, $l); # Help message... if ($h) { print <<'EOF'; Simple CLI calculator based on Perl's eval() calc [options] <expression> -h help -b convert expression (or its result) to binary -x convert expression (or its result) to hexadecimal -c convert expression (or its result) to character -l calculate base 2 logarithm of expression calc 149,600,000/299 792 458*1000/60 # comma or space are thousands + separator calc 2x2 + 2*2 # x is the same as * (multipli +cation) calc 'sqrt(V(3+3+3) * 3)' # V is the same as sqrt (squar +e root) calc -b 2^8 # ^ is the same as ** (exponen +tiation) calc -x $RANDOM calc -c 2**17-3030 calc -l 256 EOF exit 0; } # Allowed input characters regex... my $allowed = qr'\d\+\-\/\*\.x(sqrt)V'; # Transform input a bit... @ARGV = ( "@ARGV" =~ /[$allowed]/g ); # un-taint my $expr = "@ARGV"; $expr =~ s/\s+//g; # allow whitespace in input $expr =~ s/x/*/gi; # allow x for multiplication $expr =~ s/\^/**/g; # allow ^ for exponentiation $expr =~ s/V/sqrt/g; # allow V for square root $expr =~ s/sqrt/sqrt /g; # Do the calculation... my $res = eval "$expr"; die "Does not compute...$expr\n" unless defined $res; if ($b) { # Show result in binary... printf "%s = %b\n", $expr, $res; exit } elsif ($x) { # Show result in hex... printf "%s = %x\n", $expr, $res; exit } elsif ($c) { # Show result as character... binmode(STDOUT, ':utf8'); printf "%s = %c\n", $expr, $res; exit } if ($l) { # Calculate base 2 logarithm... $res = log($res)/log(2.0); } # Show thousands in result but not in the decimal part... my ( $before_dot, $after_dot ) = split /\./, $res; $before_dot =~ s/(\d{1,3}?)(?=(\d{3})+$)/$1 /g; printf "%s = %s.%s\n", $expr, $before_dot, $after_dot // 0;
    Solve the biggest problem you can. -- Nick Hanauer
Log In?
Username:
Password:

What's my password?
Create A New User
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (3)
As of 2021-03-06 10:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    My favorite kind of desktop background is:











    Results (116 votes). Check out past polls.

    Notices?