This section is the place to post your general code offerings -- everything from one-liners to full-blown frameworks and apps.

CUFP's
Announcing WWW::KeePassHttp
No replies — Read more | Post response
by pryrt
on Nov 17, 2021 at 09:53

    Some years ago, I saw and bookmarked the discussion at Best way to store passwords, for making use of KeePass for accessing passwords in a perl script. I recently had a script where I was hardcoding a password to access one machine at $work which wouldn't allow me to set up ssh-key-based login, and decided to try to make it work with WWW::KeePassRest. I had it mostly working when I happened to glance again at the plugin page and noticed its license required a SmartFTP Ultimate or Enterprise license, which I didn't have. Since $work would frown on using unlicensed software, and I'm not making $work pay for a license just to access my free password manager's passwords for my own convenience, I deleted that KeePassRest plugin. Looking through the KeePass plugins list, I found a few that looked promising for me having the skills to communicate with, and I got my script at $work correctly interfacing with KeePassHttp.

    I then took the same concepts, and re-wrote it at home with all the trappings of a public module and unit testing, and as of last night, released it to CPAN as WWW::KeePassHttp v0.01


    NAME

    WWW::KeePassHttp - Interface with KeePass PasswordSafe through the KeePassHttp plugin

    SYNOPSIS

    use WWW::KeePassHttp; my $kph = WWW::KeePassHttp->new(Key => $key); $kph->associate() unless $kph->test_associate(); my $entries = $kph->get_logins($search_string); print "$_ => $entries->[0]{$_}\n" for qw/Name Login Password/;

    DESCRIPTION

    Interface with KeePass PasswordSafe through the KeePassHttp plugin. Allows reading entries based on URL or TITLE. Allows creating a new entry as well.

    REQUIREMENTS

    You need to have KeePass (or compatible) on your system, with the KeePassHttp plugin installed.


    Yes, I know that the returned entries should be objects rather than plain-old-hashes. That was the first issue I created as I was getting ready to release last night. I needed a sense of accomplishment, so decided to do a v0.01 release. Right now, the entry-object is my primary task before considering this module good enough for a "v1.0" release. But if anyone else has suggestions, let me know. Also, I don't have any of the linux ports for KeePass, so I don't know if the KeePassHttp plugin works on the linux port... but if it does, and if any of you could test with a live linux+KeePass+KeePassHttp system, that would be great.

    I also had the fun when developing my test coverage of this being my first foray into mocking another module during testing: KeePassHttp uses HTTP requests for communicating with the plugin, but I didn't want to require that CI and smoketesting machines have KeePass+KeePassHttp installed and working before I could get test coverage. I really like Test::MockObject's ability to queue up a list of return values, so that I can easily define my list of HTTP::Tiny->get() replies without having to have an HTTP server available to give me the answers that I want to test.

Simple data-store with Perl
1 direct reply — Read more / Contribute
by bliako
on Nov 10, 2021 at 07:38

    I was in need of a data-store for clients to read and write short blobs (Edit: i.e. share data between them, that data can be simple strings, including json, or binary data. If the clients are in Perl, serialised nested perl data structure is also a possibility). A shared-memory hashtable seems ideal in my case. A DB seems far-fetched, especially because I need to keep these operations ultra-fast and do not need persistency, ACIDity, and frankly, neither I want to think how to do SQL which invariably, in my case, is googled out and ends up a hit-and-miss and inefficient. OTOH, building a C shared-memory framework with IPC from scratch will take long time. I am leaning towards using Redis especially because it has a C api as my app is in C. It also has a Perl api.

    But here is a Pure Perl solution (yet another example of programming sitting on the hunched shoulders of Giants). It seems very fast to me with 100_000 inserts in 0.35 secs within same machine:

    # simple-perl-server.pl package MyPackage; # base reapped from (with thanks): # https://metacpan.org/pod/Net::Server use base qw(Net::Server); my %Store; my $port = shift or die "No port\n"; sub process_request { my $self = shift; while (<STDIN>) { s/[\r\n]+$//; if( /^(.+?)=(.+?)$/ ){ my $x = $1; my $y = $2; #print "Added '$x' => '$y'\015\012"; print STDERR "Added '$x' => '$y'\n"; $Store{$x} = $y; } elsif( /^(.+?)=$/ ){ my $x = $1; if( exists $Store{$x} ){ print "'$x' => '".$Store{$x}."'\015\012"; } else { print "'$x' => <undef>\015\012"; } } elsif( /quit/i ){ print STDERR "$0 : quitting ...\n"; exit(0); } } # while <STDIN> } MyPackage->run(port => $port, ipv => '*');
    # simple-perl-client.pl # EDIT: this has been edited an hour after posting to set N=100_000 # time reported is correct though # mostly from here: # https://codereview.stackexchange.com/questions/106421/network-chat +-in-perl # and here: # https://gist.github.com/chankeypathak/1b1b9b3a27799eb5e277 use strict; use warnings; use IO::Socket::INET; use Time::HiRes qw/gettimeofday/; my $N = 100_000; # number of inserts my $start_time = Time::HiRes::gettimeofday(); my $server = shift or die "No server\n"; my $port = shift or die "No port\n"; my $client_socket = IO::Socket::INET->new( PeerPort => $port, PeerAddr => $server, Proto => 'tcp' ) or die "Can't create send socket: $!!\n"; print "Connected to $server:$port!\n"; my $child; if($child = fork) { while( 1 ){ my $received = <$client_socket>; exit unless defined $received; print $received; } } die "fork: $!\n" unless defined $child; # set print "$0 : doing $N sets ...\n"; for my $i (1..$N){ $client_socket->send("x$i=$i\n"); } print "$0 : done $N sets.\n"; print "$0 : doing $N gets ...\n"; # get for my $i (1..$N){ $client_socket->send("x$i=\n"); } print "$0 : done $N gets.\n"; my $end_time = Time::HiRes::gettimeofday(); print "Closing connection ...\n"; $client_socket->send("quit\n\n"); close $client_socket; sleep(1); print "$0 : done $N sets/gets in ".($end_time-$start_time)." seconds.\ +n";

    Run the server as: perl simple-perl-server.pl 16001

    Run the client as: perl simple-perl-client.pl 127.0.0.1 16001

    It's quite fast: 0.345 secs for 100_000 inserts, (out-of-the-box redis needed 10x that)

    bw, bliako

Connecting OBS to my home automation network
1 direct reply — Read more / Contribute
by cavac
on Nov 04, 2021 at 11:05

    There are always two principle ways to implement a project:
    a) Do a clean, well-designed, easy-to-understand project by investing a lot of time and money
    b) Fudge it in an evening

    I sometimes stream on Youtube. Sometimes i play early access games that are rather allergic to tabbing out. So, controlling my streaming software, OBS, has always been a bit complicated. But what i DO have is my Apollo DSKY inspired home automation console next to my main keyboard, which is connected to rest rest of my house via Net::Clacks.

    Implementing the GUI is a whole other story for another day. The DSKY project code is weird, even for my standards. This time, we are just looking into controlling some functionality of OBS via Net::Clacks.

    First, you'll need to install OBS, install the OBS websocket plugin and configure OBS to your liking (scenes, sources, streaming config and whatever else).

    Next, we'll write some config files.

    obsconfig.xml:

    <obs> <ip>10.0.0.17</ip> <port>4444</port> <password>secretobspassword</password> </obs>

    dskyconfig.xml (or rather only the relevant parts of it):

    <dsky> <clackssocket>/home/monastery/temp/clacksproxy.sock</clackssocket> <clacksuser>monasterygates</clacksuser> <clackspassword>opensesame</clackspassword> ... </dsky>

    Start with the usual boilerplate stuff:

    #!/usr/bin/env perl #---AUTOPRAGMASTART--- use 5.020; use strict; use warnings; use diagnostics; use mro 'c3'; use English qw(-no_match_vars); use Carp; our $VERSION = 2.4; use Fatal qw( close ); use Array::Contains; #---AUTOPRAGMAEND--- use IO::Socket::IP; use Data::Dumper; use Protocol::WebSocket::Frame; use Time::HiRes qw[sleep]; use JSON::XS; use XML::Simple; use Net::Clacks::Client; use Crypt::Digest::SHA256 qw[sha256_b64]; use Encode qw[encode_utf8 decode_utf8 is_utf8];

    Next step is to try to connect to the OBS websocket. If this doesn't work, we just sleep for a bit and try again. This way, the client can just run in the background all the time and we can start OBS when we need it.

    my $clacksconfig = XMLin('dskyconfig.xml'); my $obsconfig = XMLin('obsconfig.xml'); my $sock; while(1) { $sock = IO::Socket::IP->new( PeerHost => $obsconfig->{ip}, PeerPort => $obsconfig->{port}, Type => SOCK_STREAM, Blocking => 1, ); last if(defined($sock)); print "OBS not available...\n"; sleep(10); } binmode($sock); $sock->blocking(0);

    perl -e 'use Crypt::Digest::SHA256 qw[sha256_hex]; print substr(sha256_hex("the Answer To Life, The Universe And Everything"), 6, 2), "\n";'
Moon phase on historical events
2 direct replies — Read more / Contribute
by bliako
on Oct 07, 2021 at 07:55

    While I was watching the moon at a place away from civilisation I wondered what phase was the moon on certain historical events. I am not into astrology. I was curious to see how military planners make use of the moon and its effect on illumination and the tides. Invasions primarily...

    Thankfully Perl and the wonderful playground of CPAN provide all the tools one needs for an application which calculates the moon phase given date and, optionally, time and timezone or location. Thank you Astro::MoonPhase and DateTime and Geo::Location::TimeZone. All is needed is the date. Time defaults to the beginning of the day (00:00:01) and the timezone defaults to UTC. If the event's time is critical then supply it along with a timezone to make the conversion to unix-epoch-seconds (assumes UTC) accurate. In starting this I was not aware that Moon phase for a specific time is more-or-less the same for anywhere on the surface of our planet, irrespective of standpoint. With the caveat that our antipodean fellows will see it, well ... , antipodeanly.

    It looks that some military invasions took advantage of the full moon (invasion of Libya/2011, invasion of Iraq/2003 which, btw, both happened on the same day 8 years apart) while others planned for a "dark" moon (Invasion of Bay of Pigs, Cuba/1961). Normandy Landing/1944 (D-Day) planners chose a full moon (in the output: illuminated fraction: 99.4 % of full disc and also Moon age: 14.0637595011504 days which is just about half the moon cycle, i.e. full-moon) because the way it affected the tide, although the illumination would have been unwanted.

    The basic module used is Astro::MoonPhase and seems to work fine as I confirmed its output with an online calculator. Although its input is unix-epoch-seconds, it seems to handle well cases older than 1970, with a negative epoch.

    A moon phase calculator has also been posted here some time in 2007, phoon - show the phase of the moon by jima, based on previous program by Jef Poskanzer.

    Some results:

    Normandy Landing on 1944-06-06T05:00:00 (-806965200 seconds unix-epoch +) timezone: Europe/Paris (lat: 49.18, lon: -0.37) Moon age: 14.0637595011504 days Moon phase: 47.6 % of cycle (birth-to-death) Moon's illuminated fraction: 99.4 % of full disc important moon phases around the event: New Moon = Mon May 22 08:14:24 1944 First quarter = Tue May 30 02:06:14 1944 Full moon = Tue Jun 6 20:59:37 1944 Last quarter = Tue Jun 13 17:57:49 1944 New Moon = Tue Jun 20 19:01:26 1944 end event. US Invasion of Cuba, Bay of Pigs on 1961-04-15T05:00:00 (-274975200 se +conds unix-epoch) timezone: America/Havana Moon age: 0.207041969010797 days Moon phase: 0.7 % of cycle (birth-to-death) Moon's illuminated fraction: 0.0 % of full disc end event. Invasion of Libya on 2011-03-19T05:00:00 (1300503600 seconds unix-epoc +h) timezone: Africa/Tripoli Moon age: 14.0213525003449 days Moon phase: 47.5 % of cycle (birth-to-death) Moon's illuminated fraction: 99.4 % of full disc end event. Invasion of Iraq on 2003-03-19T05:00:00 (1048039200 seconds unix-epoch +) timezone: Asia/Baghdad Moon age: 15.4878029842796 days Moon phase: 52.4 % of cycle (birth-to-death) Moon's illuminated fraction: 99.4 % of full disc end event.

    Edit: caveat: the most reliable way to get the timezone right is to set it manually using a string that DateTime::TimeZone understands. Getting timezone from coordinates via Geo::Location::TimeZone is less reliable (case in point is Cuba's Bay of Pigs which gets the timezone of Pacific/Norfolk, I have edited the results to correct this.). Another edit: made example output terse and added readmore tags around the code. And added some more thanks to the existing modules my lame app relies on because they deserve it.

    The driver script follows. The input is provided in-script by an event hash which specifies a name and date, optional are time, timezone, location coordinates. Enjoy:

    bw, bliako

KenKen puzzle helper
No replies — Read more | Post response
by toolic
on Sep 16, 2021 at 17:51
    The most common mistake I make when solving KenKen puzzles is that I fail to enumerate all the correct combinations that could fill a cage. It can be tedious (and hence error-prone) to think up all the combinations for larger addition and multiplication cages.

    This is not intended to be part of a complete puzzle solver. I just want to use it to "check my math" after I realize I made a mistake while working on a puzzle.

    Since I don't have tests for the code, there could be bugs. One limitation is that it does not account for the shape of a cage. Depending on the shape, some cages forbid the same number appearing more than once, while others allow one or more numbers to appear multiple times. There is an option to control the number of duplicates to some degree.

    Here is an example output for a 9x9 grid with a cage size of 5, and the numbers adding up to 29:

    kenken -c 5 -n 29 -r 2 Grid size: 9 Cage size: 5 Operator : a Number : 29 Reject : 2 29+ = 1 + 4 + 7 + 8 + 9 29+ = 1 + 5 + 6 + 8 + 9 29+ = 2 + 3 + 7 + 8 + 9 29+ = 2 + 4 + 6 + 8 + 9 29+ = 2 + 5 + 6 + 7 + 9 29+ = 3 + 4 + 5 + 8 + 9 29+ = 3 + 4 + 6 + 7 + 9 29+ = 3 + 5 + 6 + 7 + 8 Combinations = 8

    For this run, I rejected all duplicates. If I rerun allowing numbers to appear twice, the number of combinations jumps up to 48.

    I was surprised at how little of my own code I had to write because it leverages so heavily on CPAN and Core modules.

Generate graphviz visualisation of interrelationships between variables using Graph and GraphViz2
No replies — Read more | Post response
by etj
on Aug 28, 2021 at 22:27
    This also currently lives on GitHub at https://github.com/PDLPorters/pdl/blob/master/Example/doc-pp. It helps me see at a glance what PP parameters get data from each other, but the principle should be widely applicable:
    use strict; use warnings; use PDL::PP; use Graph; use GraphViz2; my $g = Graph->new; # should really be hypergraph but GraphViz2 not do + yet for my $r (@{$PDL::PP::deftbl}) { for my $t (@{$r->{targets}}) { $g->add_edge($t, $_) for map s/_//gr, @{$r->{conditions}||[]}; } } my ($fmt) = $ARGV[0] =~ /\.([^.]+)$/; $g->set_graph_attribute(graphviz=>{graph=>{rankdir=>'LR'}}); GraphViz2->from_graph($g)->run(format=>$fmt,output_file=>$ARGV[0]); =head1 NAME doc-pp - Generate graph of pp_def key dependencies with graphviz =head1 SYNOPSIS doc-pp deps.svg =head1 DESCRIPTION Uses L<Graph> and L<GraphViz2> to visualise the dependencies between keys in L<PDL::PP/pp_def>.
One-liner to show C struct sizes using Inline
No replies — Read more | Post response
by etj
on Aug 28, 2021 at 22:15
    This uses the superb Inline, and specifically the use Inline with =>... feature, to show the size of C data structures. The sample shown is from PDL.

    perl -Mblib -MInline=with,PDL -MInline=C,'size_t f() { return sizeof(struct pdl); }' -E 'say f()'

A BASIC interpreter to run StarTrek
5 direct replies — Read more / Contribute
by GrandFather
on Aug 11, 2021 at 08:03

    Many years ago I spent a chunk of time playing StarTrek written in BASIC on a PDP11. I stumbled on BASIC source for the game recently and thought it might be cool to write a BASIC interpreter in Perl to run it. This is the result (click the Readmore to see the code).

    There are bound to be bugs in the code still, but I've spent a little time playing the game and it seems to substantially work (i.e. I haven't seen any breakage).

    The BASIC script for the StarTrek program is given in a reply to this node.

    Update: Changed chomp to s/\r?\n// per roboticus's suggestion. Thank's too to cavac for also picking up on the issue.
    Commented out srand 1 used to get a consistent game world for debugging.
    Update to make parser case agnostic for key words and identifiers.
    Fix parameter parsing bug,

    Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond
Inline::CUDA : looking for feedback
2 direct replies — Read more / Contribute
by bliako
on Jul 28, 2021 at 05:52

    Hi all,

    I have placed a preliminary version of Inline::CUDA at https://github.com/hadjiprocopis/perl-inline-cuda, it has only been installed on my machine (Linux, GeForce 650). I would be grateful for comments from anybody who would try to install it in their machines: OSX, Windows, other Linux versions with different NVIDIA GPU versions.

    It's a lot of work to download the huge NVIDIA CUDA SDK and it is very likely that you will also need to install a specific compiler version (additional to your system compiler). So, be prepared to spend a few hours on it! I apologise!

    Hopefully, with your insight and feedback I will be able to create a better installation workflow. I have Alien::Build in mind.

    Comments and feedback on the actual code and style are very welcome as well.

    Many Thanks

    bw, bliako

    Edit: I have got a bit more into git and I think I have managed to master a git-commit-push workflow. I hope from now on it will not copy all files back to the repository but only those with changes.

Linux/Perl Cabrillo to ADIF Conversion Script
1 direct reply — Read more / Contribute
by jmlynesjr
on Jul 21, 2021 at 16:15

    Script to convert an Amateur Radio Cabrillo format log file into to an ADIF(Amateur Data Interchange Format) logfile.

    A Cabrillo file has space delimited fields. An ADIF file has tag delimited fields and field order is not important. A Cabrillo file is used for entry into Ham radio contests like the ARRL Field Day. ADIF files are used to import contact data into logging software like QRZ.com. This process was used to create(with QRZlogfmt.pl) a Cabrillo log of 200+ entries and then import this file into my log on QRZ.com. I prefer to log on paper and I will use this process to enter and import contact data as I fill a log sheet.

    Posted here so it can be found by the search engines. Other utilities that I have found are for Windows only.

    James

    There's never enough time to do it right, but always enough time to do it over...

Linux/Perl Cabrillo Logfile Creation Script
1 direct reply — Read more / Contribute
by jmlynesjr
on Jul 21, 2021 at 16:12

    Script to create a simple Amateur Radio Cabrillo Format Log File

    Not much out there for Linux users, had to roll my own. Log file created with 200+ entries then converted to ADIF format and uploaded to QRZ.com. Posted here so it can be found by the search engines.

    James

    There's never enough time to do it right, but always enough time to do it over...

Ajax voting and modern formatting on PerlMonks
No replies — Read more | Post response
by Your Mother
on Jul 18, 2021 at 20:23

    (I reserve the right to make *sensible* silent updates or corrections in code and formatting for a day or two; until I remove this line. No one wants a post that has ďupdate: ÖĒ repeated 20 times and if I have to proof this for an hour right now, I wonít post it.) :P

    This code will give the site a more modern layout and appearance. You can thank tobyink for that part.

    Fair warning

    This code was just written for me. Itís not bombproof, it has no automatic tests, and including external files is a security risk if the source/host decides to exploit it or is itself hacked. I only address problems as they arise so there may be edge cases galore that I donít know. I did not clean-up or check anything and I wrote 95% of it like 2 years ago; generally speaking, I cannot remember code I wrote last week.

    I may not explain much of any of it,

    As it stands, you will have to have a webserver. I am using plackup with https support. If you have your own host or something, you can definitely use that. Without supporting https this stuff wonít work unless you unblock the sources with your browser (a PITA and not a good idea).

    This code does a skosh of dynamic handling of the Chatterbox.

    Nodelet settings

    In your Free Nodelet Settings you will need to add several lines.

    <script src="//code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo= +" crossorigin="anonymous"></script> <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.mi +n.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.2/highlig +ht.min.js"></script> <script src="//buzzword.org.uk/2014/pm/pm2.js"></script> <script src="//localhost:8282/pm/he.js"></script> <script src="//localhost:8282/pm/pm.2.0.js"></script> <script src="//localhost:8282/pm/pm.2.0.cb.js"></script> <link rel="stylesheet" href="//localhost:8282/pm/pm.2.0.css" type="tex +t/css" />

    The jQuery and Bootstrap are from, I think, reliable CDNs. he.js is a library for handling characters and HTML entities; hence ďhe.Ē The main formatting script, pm2.js, is from tobyinkís buzzword.org.uk. The next JS and CSS are mine and youíll have to serve them yourself from somewhere. Tobyís code needs Bootstrap. My code needs jQuery.

    he.js

    If you donít have it installed already via node or something, just take the he.js file to serve: https://github.com/mathiasbynens/he

    pm.2.0.js

    pm.2.0.cb.js

    Code to try to make the Chatterbox more dynamic. It has bugs, including an initial double display, that havenít bugged me enough to fix yet. If you use/edit it, please be careful not to put a bunch of load on the server with bad timers, etc.

    pm.2.0.css

    The only purpose here is to do a sort of anti-spinner. When you click I've checked all of these on the Recently Active Threads page, it blanks the page so you know something happened and shows it when the ajax has loaded it in the background. I probably should have just done it in JS but I thought Iíd be doing more CSS so started a fileÖ

    body { opacity: 0 !important; transition: opacity 0.5s; }

    If you donít have a webserver already, this is how I run mine on :8282; youíll need Plack::App::Directory. Donít ask me how to do your own certs. I do it less than annually and itís always a RTFM situation.

    plackup -p 8282 -MPlack::App::Directory -e \ 'Plack::App::Directory->new({root => q{/path/to/the/files}})->to_app +' \ --enable-ssl \ --ssl-key-file /path/to/certs/localhost.key \ --ssl-cert-file /path/to/certs/localhost.cert
filter-ports-commit-log.pl - Filter, highlight FreeBSD Ports one-line commit log messages
No replies — Read more | Post response
by parv
on Jul 10, 2021 at 06:42

    Description: Purpose is to remove inane (one-line) commit log messages of FreeBSD Ports Git repository, and highlights some others. It is not currently suitable to filter long form of commit messages.

Compile and possibly run cuda code on the GPU via Perl's Inline::C
1 direct reply — Read more / Contribute
by bliako
on Jul 02, 2021 at 04:48

    Here is my attempt to run Nvidia's cuda code on the GPU via Perl. The motivation is from question Perl GPGPU Modules by kcott (interesting problem, Ken!). The main tool is Inline::C which opens so many doors.

    Cuda is a programming language on top (or extending) C which deals with GPGPU. General-purpose computing on graphics processing units (GPGPU) tries to use graphics cards (GPU) and their highly parallel architecture to run tasks, like (large) matrix multiplication, which a CPU, because of its architecture, runs much slower and inefficiently. The GPU is designed for matrix multiplications and that's what it does frame after frame of what we see on our monitor without sweat. Matrix multiplication is the basis for a lot of numerical applications and can make social planning much easier.

    First the problems:

    • Nvidia provides its own compiler for cuda code: nvcc which compiles only cuda-specific code and the rest is delegated to the system compiler (e.g. gcc). So, as I understand it, both nvcc and gcc will be used to compile a cuda program which does have cuda extensions, i.e. it is not just "plain" C code.
    • Nvidia is very picky about the version of the system compiler. It usually only supports older compilers which must live in your system along with the system/current compiler. That's a bit of a kerfuffle. For example nvcc 11.4 supports up to gcc10, whereas my system compiler is at 11.1. My Linux system does not support installing other compilers via the package manager, or at least I did not find out how. Instead I resorted in building an older version from source with its own --prefix e.g. gcc84 and use that for each nvcc call using nvcc --compiler-bindir /usr/local/gcc84/bin/gcc84. Linking using nvcc requires the same treatment. See this for how to compile and install a second compiler in Linux with its own name-prefix-postfix.
    • nvcc does not take all the flags and parameters gcc takes. Instead, any flag to be passed on to the system compiler must be preceded by -Xcompiler
    • nvcc needs its input files to have the extension .cu

    Here is the general setup:

    Use Inline::C, which is a great and powerful module! thanks!, with specific compiler and linker by providing it (via use Inline C => Config => cc => '...', ld => '...') with two Perl scripts namely nvcc-compile.pl and nvcc-link.pl These will remove some incompatible compile/link flags which Inline::C and ExtUtils::MakeMaker use for compiling plain C code. They will also prefix others with -Xcompile ... to pass them on to the system compiler. The first script will also rename one of the temporary files produced in _Inline/build/ directory so that its extension is .cu and not .c. Then compiler and linker scripts proceed in running the actual nvcc command appropriate for compiling or linking. These scripts just worked for me but will probably need tweaking for other compilers and other flags. At least a general setup is in place.

    The two scripts to be provided to Inline::C as compiler and linker are given at the end. Edit: Save them at the same location as the demo script below without changing their names.

    Here is a basic Perl script running a cuda program on the GPU:

    #!/usr/bin/perl # by bliako @ PerlMonks.org # date: 01-Jul-2021 # see https://perlmonks.org/?node_id=11134582 # lame example for utilising GPGPU via Inline::C # TODO: extend to taking params and returning back results use strict; use warnings; use FindBin; use Inline C => Config => cc => $FindBin::Bin.'/nvcc-compile.pl', ld => $FindBin::Bin.'/nvcc-link.pl', ; use Inline C => <<'EOC'; // from https://developer.nvidia.com/blog/easy-introduction-cuda-c-and +-c/ #include <stdio.h> __global__ void saxpy(int n, float a, float *x, float *y) { int i = blockIdx.x*blockDim.x + threadIdx.x; if (i < n) y[i] = a*x[i] + y[i]; } int main() { int N = 1<<20; float *x, *y, *d_x, *d_y; x = (float*)malloc(N*sizeof(float)); y = (float*)malloc(N*sizeof(float)); cudaMalloc(&d_x, N*sizeof(float)); cudaMalloc(&d_y, N*sizeof(float)); for (int i = 0; i < N; i++) { x[i] = 1.0f; y[i] = 2.0f; } cudaMemcpy(d_x, x, N*sizeof(float), cudaMemcpyHostToDevice); cudaMemcpy(d_y, y, N*sizeof(float), cudaMemcpyHostToDevice); // Perform SAXPY on 1M elements saxpy<<<(N+255)/256, 256>>>(N, 2.0f, d_x, d_y); cudaMemcpy(y, d_y, N*sizeof(float), cudaMemcpyDeviceToHost); float maxError = 0.0f; for (int i = 0; i < N; i++) maxError = max(maxError, abs(y[i]-4.0f)); printf("Max error: %f\n", maxError); cudaFree(d_x); cudaFree(d_y); free(x); free(y); return 0; // << late edit! } EOC main;

    nvcc-compile.pl

    nvcc-link.pl

    At the moment, I have not implemented communicating parameters to and from the inlined cuda code. Feel free to extend.

    Suggestions: Inline::C can be modified in order to avoid my ugly hacks, or a new Inline::Cuda can be built.

    These are interesting times. This is a small step in making them fun-ner and lazy-er too. A big Thank You to the author of Inline::C and Nvidia.

    Tested on Linux with (older) gcc version 8.4, Nvidia's Cuda compilation tools version 11.4.48, Nvidia graphics driver 470.42.01, Perl version 5.32.1, Inline::C version 0.81

    Edits: main demo script added a return 0; at the end of main()

    bw, bliako

Extract/Print Firefox Bookmarks HTML File
2 direct replies — Read more / Contribute
by jmlynesjr
on Jun 25, 2021 at 19:06

    Here's a script to extract and print/save the URLs exported by the Firefox Export Bookmarks to HTML function.

    I know squat about HTML, but seem to have stumbled onto a good example.

    A flakey laptop is the mother of invention.

    #! /usr/bin/perl # bookmarks.pl - Script to extract and print the URLs created by the F +irefox # Export Bookmarks to HTML feature. # # James M. Lynes Jr. - KE4MIQ # Created: June 25, 2021 # Last Modified: 06/25/2021 - Initial version # Environment: Ubuntu 16.04 LTS # # Note: The raw HTML is very messy as it seems to include long strings # of encoded images. # Working code shamelessly stolen from the perldoc HTML::Element # example. use HTML::TreeBuilder; open(my $outfile, ">", 'bookmarks.txt') or die "Can't open bookmarks.t +xt: $!"; print $outfile "Firefox Bookmark URLs\n"; print $outfile "=====================\n"; my $tree = HTML::TreeBuilder->new(); $tree->parse_file('bookmarks.html'); for (@{ $tree->extract_links('a') }) { my($link, $element, $attr, $tag) = @$_; print "$link\n"; print $outfile "$link\n"; } $tree->delete;

    James

    There's never enough time to do it right, but always enough time to do it over...


Add your CUFP
Title:
CUFP:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":