 |
| User since: |
Jun 24, 2000 at 20:36 UTC
(25 years ago) |
| Last here: |
Dec 17, 2025 at 02:02 UTC
(2 days ago) |
| Experience: |
3346
|
| Level: | Curate (13) |
| Writeups: |
329
|
| CPAN ID: | SOMIAN |
| Location: | Buffalo CITY / New York STATE / U.S.A. NATION / North American CONTINENT / Western HEMISPHERE / Terra PLANET / Sol SYSTEM / MilkyWay GALAXY / "local" GROUP / Virgo SUPERCLUSTER |
| User's localtime: |
Dec 18, 2025 at 13:37 EST
|
| Scratchpad: |
View
|
| For this user: | Search nodes |
|
| about this image: |
| This is a visual fingerprint (a "visprint" as it's called)
— an image generated using fractal maths —
representing my GnuPG key fingerprint
(postprocessed in ImageMagick). |
Welcome to the home node of The Unreasonable Man! He goes by Soren, Sorentino, "somian", "amphibole", Soren Andersen)
“The reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore all progress depends on the unreasonable man.” — George Bernard Shaw
Other Favorite Quotes
"[André Malraux said] Do what you believe you must and leave the interpreting of it to others."
"[This] seemed to me to summarize his personal philosophy. How true this is. Don't be distracted by the
carping of bystanders, their irresponsible attitudes, their self-serving, cowardly words and actions."
— Daisaku Ikeda on a dialog with André Malraux
A little quote about religious tolerance, which I see as pertaining to
the tendency of some Christians to shout "Persecution!" rather often nowadays:
"We respect the right
of everyone to believe whatever they like. ...
But there are two important limits to religious tolerance. First, I have no
right to legal protection against your scepticism, criticism or ridicule.
Religion is too powerful a force, and is too often a cause of injustice or
evil, for it to be immune from discussion and debate."
—
David Pannick QC
“Perl is the portable distillation of
the UNIX philosophy."
—
Scott McMahan
"Write documentation as if whoever reads it is a violent psychopath who knows where you live."
—Steve English, as quoted by Peter Langston
but do not say later that you didn't have access to those views, carefully
explained ;-]>
I learned some Perl and became a CPAN Author:
[...]AUTHORS/ID/S/SO/SOMIAN/
"... people who condemn others simply on the basis that the target of condemnation is "angry" or "frustrated" are using a false premise as a basis for their condemnation. Anger is not, by itself, a transgression against society, or the Monastery."
The most reasonable of suggestions has been made
in Dealing with An(?:no|on)ytroll by tirwhan. It
deserves serious thought.
You will see formatting oddities on this node. These show as visible HTML formatting tags. The reason is not carelessness; instead, after this node was
created, the parser for Perlmonks nodes changed such that style=... in tags is no longer accepted.
A short rant
One thing that I've noticed in my time spent chatting in the cb here at Perlmonks is that the level of ethical sophistication amongst a few of my fellow cb'ers can be terribly low. I make this generalization because there's one prime point of all ethical systems that I can feel any respect for, and that is:
Might does Not make Right
But it is clear that among the cb'ers are those who don't understand this. They have an enormous blind spot when it comes to issues in the workplace or the Perl (or other kind of) hacker community. Maybe it's a generational thing; I'm in my 40s and many Monks are in their 20s. I think the times are shaping young people to have much lower sensitivity to this. Most are very quick to point out the shortcomings of political leaders but very few seem able to see that abuse of privilige and power plays a big role close around them in their everyday lives.
There are two kinds of social power generally at work in our world:
- Individual Despots
and
- The Despotic Mob
Both these exert their influence generally (not always) to the detraction of good in the lives of human beings, to the enhancement of evil. People seem to regard the exercize of power by individuals like irc ops as some form of divine right, which is fine as long as such people who think this way don't try to pass themselves off as freedom-loving people. Furthermore: there seems to be a general assumption that if a person has contrary views to an irc #channel-op or a Perlmonks God, they are automatically wrong. This is childish, immature, dangerous and pathetic.
Just as bad is the pattern wherein supposedly intelligent people automatically assume that the person saying a new thing that insults (in their view) or challenges a comfortable dogma, or other item of "social consensus," is automatically wrong.
The only positive change that has ever taken place in the world has come about because of alienated, despised malcontents who dared to speak truth to power. The only kind of human being truly worth honoring is one who can summon the personal courage to speak truth to power, on whatever level or in whatever form it takes (embodied as either the despot or the mob). No-one lives a worthwhile life without ever falling afoul of some embodiment of power, sometime during their lives. The rest of humanity live like
sheep, and no society that deserves to be remembered by history erects monuments of honor to sheep.
When a person gets banned in irc or otherwise "punished" somehow in any kind of hacker social context, they fairly often deserve it because their actions have been contrary to the general good of the group. But not always. This distinction between "always" and "not always" is the difference between the destruction of the world and its salvation. It is everything. Not understanding this is the distinction between an ignorant person and a real citizen, whether of the Happy Realm of Hacking Free Software or of the World.
From the Wikipedia entry for Internet Troll we see this quote:
[Likewise,]
accusers are often motivated by a desire to defend
a particular Internet project, and references to an Internet user as a
troll might not be based on the actual goals of the person so named. As
a result, identifying the goals of Internet trolls is most often
speculative.
The use of the term "Troll" on Perlmonks by a certain group of people is an
example of something like what's described above. It reflects not on the
accused person but on the accusers, who are
misusing a type of peer group -based power (being the Despotic Mob)
to exercize coercion against someone whose
aims are, as many others see, not those of a troll at all. The very best
that can be said of such misuse is that the accusers are engaging in
reckless and irresponsible speculation. The worst is that they themselves
are far more despicable than any "Internet Troll", that they are in fact
aiming to give themselves the twisted pleasure of seeing their group power
effectively deny another participant the option of
continuing to engage in a reasonable relationship with the site, community
or project in question.
One can only feel pity for people living with the kind of impoverished
inner lives and distorted emotional personalities that would derive pleasure
from such a thing,
but unfortunately the modern world at least, with its intense pressures
and demands, often gives rise to such it seems.
I don't see posts by Anonymous Monk beginning at 6:30pm on 7 Dec 2005,
by using CSS to override display settings. The texts of postings of any nature
by any non-existing (Anonymous) Monk are invisible for me. This is a measure
that I've taken until such time as the preferred solution comes to pass (the
preferred solution being: the Perlmonks site no longer allows Anonymous
posting at all).
A side note:
The application at cb60 is the
only cb history interface that is currently working (to my knowledge) at
the time of this writing, and is the only one that can be configured to
ignore users as the live chatterbox can.
There's a particularly annoying kind of conduct that very frequently
takes place and lands users who commit it on the following list. This
consists of coming into the chatterbox with a minimal but strange-sounding
question - one that rings "warning bells" for some of the experienced
Perl users. When it is suggested that more information is needed because
the approach seems dubious (perhaps based on a mistaken understanding
of how something in Perl works), such an individual committing this
type of annoyance then leaves in a huff, saying something like Thanks
for the kind help in a sarcastic and injured way that is intended
to cause guilt feelings.
This is playing the "Newbie Victim of Mean Monks"
card, and it is not only stupid, and not only pathetic,
but also wrong - because the chatterbox or Perlmonks in general
is a place where many give of their time to try to help less experienced
Perlers. These volunteers don't need to put up with that kind
of childishness, the attempted emotional manipulation and tantrums;
and in my opinion, should not put up with it.
Again, it is (in my opinion), really ok to insist on minimum standards of
mature behavior in order to qualify for help or attention at Perlmonks.
Perl Tips, Observations, and Experiments
I use both Free Software Operating Systems and the proprietary Microsoft Windows OSes.
Obviously I prefer to spend more time on the former (my favorites are Ubuntu and its
parent distribution, Debian). On MS Windows I use both ActivePerl and the new Win32
Perl that's being called
StrawberryPerl.
I often build my own Perl installations from source, as well.
The quality of the user experience one has with the MS Windwoes OSes is highly variable.
Some users find little lacking in it and some are driven crazy by it. One inclination
that is not well-served by Microsoft is the desire to use the CLI (Command-Line Interface,
but if you are here reading, you knew that ;-) …and so I rely on the long-lived
and community-supported
Cygwin
environment (this is important: Cygwin is supported by volunteers; do not act
like a petulant spoiled brat if you go asking for support {if you happen to try Cygwin
out}; if you do, you will just be ignored). Cygwin provides a port of Perl that tracks
the major release cycle of mainstream Perl and "acts like" Perl running on a unix OS
platform. Cygwin also provides the Bash shell and many other GNU userspace components
that are common to all GNU/Linux and other free unix OSes.
Because I have acquired years of experience using Perl on MS Windwoes, I do not have
the oblivious outlook about file name extentions that is customary from users who do
only work on unix platforms. My decision is to name Perl programs with a .plx
extention which disambiguates these files from those containing Perl library code. I
use the appropriate MS Windows commands (from the CMD.exe cli) to create the right
Registry settings so that the files named with .plx extentions are
associated with the perl executable.
A smattering of Useful Tips for PerlMonks, especially new ones
Ripped off from busunsl's node:
Link types at PM (because I tend to forget :-):
- [id://] a node's id (numerical value)
- [cpan://] searches CPAN
- [kobe://] is an alternate means of searching the CPAN (contrasted with the [cpan://] tag)
- [jargon://] searches the Jargon file hosted at the University of Amsterdam.
- [doc://] searches perldoc.perl.org: the
idea here is to provide a way of linking to more current Perl documentation
than what Perlmonks can maintain.
- [pad://] is a shortcut to a user's scratch pad
Monks Solemn Intonement:
righteousness ()
{
perl -e'
print "The troublesome entities, irksome to Monks:\n "
, ( join " and ",
map{
sprintf qq{$_ is safe as }.q{&#}.qq{%d;}, ord ;
} qw/[ ]/ )
, "\n";
'
}
n.y.p.m.blue
– my PerlMonks color theme for CSS-supporting browsers – is now listed and maintained on this node.
This list is of modules that I'm not currently using for anything but that I think I
might want to at some future time
A little parts bin of useful HTML entities for doing PM node markup
"[" left sq brkt [ [
"]" right sq brkt ] ]
"<" left angle brkt > < or <
">" right angle brkt < > or >
"mdash" em-dash — —
"ndash" en-dash – –
"lsquo" left single quotation ‘ ‘
"rsquo" right single quotation ’ ’
How I am creating ordinary paragraphs for Perlmonks node writeups these days:
perl -MText::Wrap='wrap,$columns' -MText::Textile=textile \
-lp000we \
'INIT{$Text::Wrap::unexpand=0; $columns=88; print qq/\n/. q[-]x88 .
+qq/\n/ };
s{\cM?\cJ} [\cJ]g;
$_=wrap(q[],q[],textile($_)).$/;
s{<br />} []g;' </dev/clipboard
This should work fine in a MS Windows CMD shell too, with the alterations that
(a) all single quotes around the -e script and perl flags are changed to double quotes,
and (b) the line-continuation backslash/newlines are removed.
·Assorted Perl Stuff, and platform-specific notes·
Which and where is
“Some::Perl::Module”
(finding VERSION and location of a Perl module):
Preface:
Depending on your OS and your work habits / preferences, you
might want to use a Unix sh means of wrapping the Perl code
implementing this technique (second thing below), or you might need a MS
Windows console helper (in the form of a DOSKEY macro,
shown immediately below). I've named this critter different things
in different manifestations on different machines at different
times ... but now I am aiming to settle on it being named
PMTEST.
PMTEST=perl -le "do{$modn=$_;s!::!/!g;$_.=q[.pm];do{print qq[$modn is
+not installed.];next} unless eval qq#require(\"$_\");1# && !$@;$modv=
+defined(${$modn.q[::VERSION]}) ? ${$modn.q[::VERSION]}:q{[version und
+efined]};$numtyp=2>$modv=~tr/.// ?'%s':'% 6d';printf qq[ %-*s $numty
+p in %s\n],(length>30 ? 5+length:15+length),$modn,$modv,$INC{$_}}for
+@ARGV;" $*
Sorry, those long (wrapped) ugly pieces of code
are what's required
for MS Windows CMD shell. The command interpreter does not offer any means (that I
have discovered) of using continuing statements on multiple lines when defining a
DOSKEY macro. Don't try a COPY-PASTE of the above, either, or you'll have to
figure out how to remove every introduced newline inside the macro definition before
the code will work. Trust me, you won't feel good about the wasted time.
To use the above code, you must place it in a *.bat or *.cmd file
and then "execute" it from the MS Windows console (the commandline interface,
CLI, CMD.exe).
Invoke the macro (not the .bat file it was saved in, which you
execute only once per each shell session or instance) with a
single arg, the Perl-style name of a module (for ex. “pmtest CGI” or
“pmtest File::Find”).
Here's the Unix shell (bash/ksh etc.) rendition of the
pmtest thing
# pmtest: bash reusable function authored by Soren Andersen
# license/terms of use/modification/redist: same as Perl
pmtest ()
{
perl -e'
my$modn = my$mod = "'$1'";
$mod =~s@::@/@g; $mod.=q[.pm];
die ("module $modn not installed.\n",$@) if
! eval {require qq[$mod];};
my $modv = defined ${$modn.q[::VERSION]} ?
${$modn.q[::VERSION]} : q{[version undefined]};
my$numtyp= (2 > $modv =~tr/.//) ? "%s" : "% 6d";
printf " %-*s $numtyp in %s\n",
length($modn) > 30 ? 5+length($modn) : 15+length($modn),
$modn, $modv, $INC{$mod};
';
return 0
}
This also needs to be "gotten into" the bash session somehow. Ths canonical
way of doing so is to include the above in a shell initialization file
like ~/.profile or ~/.bashrc.
For contemplation by people who want to write software installers,
Perl installation administrators, etc.:
In contrast with Unix-like platforms, MS Windows has it's own sense of Well-known Folders
(not absolute filesystem "folders" but instead pointers to locations which can reasonably
be expected to exist on most
Windows machines, with some divergence between the bog-ordinary Workstation and the more
complex Server kind of Windows installation).
These are abstractions, meta-directories if you like, which exist above the
level of the actual filesystem and happen to be represented in the typical, default Windows ENV
by variables like %APPDATA% and %ProgramFiles% and %ALLUSERSPROFILE%.
We can access the values assigned to these meta-directories using the API calls
wrapped in the Win32.pm module (not in the core namespace which is automatically
built in when Perl is created for a Windows system; the user has to explicitly
say use Win32; in order to make this work).
Here's a simple one-liner to demonstrate:
perl -MWin32 -le 'my @ds=grep {/CSIDL_/} @{ [keys %Win32::] }; ' \
-e 'do {printf qq/%31s => %s\n/, $_, Win32::GetFolderPath(&{$Win32::
+{$_}}) }'\
-e 'for map { $_->[0] } sort {$a->[1] <=> $b->[1]} map { [$_,&{$Win3
+2::{$_}}] } @ds'
Note that we did not even need to know the particular names of the metadirectories
available on the specific version of Windows on which this is run, which is Kinda Cool
imho.
Here's a way to get the location of the meta-directory of your choice, assuming that you
choose with some clue to begin with ;-/ ... :
perl -MWin32 -le "my @ds=grep {/^CSIDL_/ && /\U$ARGV[0]/} @{ [keys %Wi
+n32::] };
do {printf qq/%31s => %s\n/, substr($_,6), Win32::GetFolderPath(&{$
+Win32::{$_}}) }
for @ds" profile
This should display the Special Folders that are named *PROFILE* (in globbing terms) and
display the actual location(s) of such folders.
Note also that the above commandlines aren't broken up in actual use, and will have to be mended
by any who wish to try it out. MS Windows CMD shell doesn't allow multi-line commands
even inside quotes UPDATE:
You can create multi-line
Perl one-liner (console input) scripts in the interactive Windows CMD shell. You will escape the newline with
the ^ character (caret) but this does not work to span lines inside quotes.
Instead, you will use -e repeatedly, just as you may do in a *nix sh-type shell. Here's the
oneline demo above, thanks to pKai who educated me on this!:
perl -MWin32 -e "my @ds=grep {/CSIDL_/} @{ [keys %Win32::] };" ^
-e "do {printf qq/%31s => %s\n/, substr($_=>6), Win32::GetFolderPath(&
+{$Win32::{$_}}) }" ^
-e "for map { $_->[0] } sort {$a->[1] <=> $b->[1]} map { [$_,&{$Win32:
+:{$_}}] } @ds"
Here's a DOSKEY macro-ized version of the code above. Handy for interactive CMD shell
use where you need to quickly check the list of Special Folders (or a particular group of them).
:: MS Windows BAT/CMD syntax. Wraps a Perl one-liner program.
DOSKEY SPECIALFOLDERS=perl -MWin32 -e "my @ds=grep {/CSIDL_/} @{ [key
+s %%Win32::] };
do {printf qq/%%24s=>%%s\n/, substr($_=>6), Win32::GetFolderPath( &
+{$Win32::{$_}} )}
for map { $_->[0] } grep {(0+@ARGV ? $_->[0]=~m<$ARGV[0]>i : 1)
+}
sort {$a->[1] <=> ${b}->[1]} map { [$_,&{$Win32::{$_}}]
+ } @ds" $*
Remember to reformat the code above so that no linebreaks are present. The line that begins
with DOSKEY needs to be one continuous line.
·For MSWin
-using Monks·
- You can emulate the Unix sh-shell user-defined function examples
shown on this node to some extent by using DOSKEY macros.
DOSKEY still exists on Windows XP, Vista, and 7. In a CMD shell you
can query what macros you've defined by doing
D:\ > DOSKEY /macros
and can define new macros by saying something like this:
D:\ > DOSKEY perlversion=perl -le "printf qq[%vd$/]=> $^V"
This is a somewhat trivial and quite contrived example of course. ;-)
Here's a less contrived example. This will make cli work easier if you
find yourself working in a directory named like C:\Documents and Settings\You There...
DOSKEY compactcwd=FOR /F "delims=*" %%N IN ("%CD%") DO CD %%~sN
There are some DOSKEY/Perl gotchas to look out for. Note that this is not an exhaustive list.
- The special tokens $* and $B, $G, $L and $T (case does not matter) will be interpreted by DOSKEY
instead of DWYM with Perl This means that scalar variables must not
be named $[Bb].* or $[Tt].*, using regexp
meta-syntax to explain. You could say ${Beginning} or
${tangent}, though.
- The % sigil in a hash variable name (or a printf format, or anywhere else) must be doubled if you
are trying to set up DOSKEY macro definitions in a batch
file script. The first one is "eaten". (Note: I've some reason
to think that escaping a % with a caret ^ might work, but I
haven't had time to test this. I think that in general, quoting with
the ^ in CMD doesn't work inside double quotes.)
- Batchfile as DOSKEY macro-file (thanks, Ben Burnett):
- The macros discussed above can be cleverly included in a CMD
session using this as a file (say, save it as PMACROS1.bat)
and starting CMD from a shortcut like this:
%SYSTEMROOT%\System32\CMD.exe /E:on /F:on /V:on /K CD %USERPROFILE% & PMACROS1.bat
;= @echo off
;= rem Call DOSKEY and use this file as the macrofile
;= %SystemRoot%\system32\DOSKEY /listsize=1024 /macrofile=%0%
;= rem In batch mode, jump to the end of the file
;= goto end
;= rem ***************************************************************
+***
;= rem * Filename: DOSKEY-M1.cmd
;= rem * Version: 2.0
;= rem * Author: Soren Andersen <somian08@gmail.com>
;= rem * Purpose: Some useful perl 1-liners
;= rem * license/terms of use/modification/redist: same as Perl
;= rem * Last modified: Wed 28 Dec 2011
;= rem * History:
;= rem ***************************************************************
+***
;= rem PMTEST: Test for use of a Perl module
PMTEST=perl -le "do{$modn=$_;s!::!/!g;$_.=q[.pm];do{print qq[$modn is
+not installed.];next} unless eval qq#require(\"$_\");1# && !$@;$modv=
+defined(${$modn.q[::VERSION]}) ? ${$modn.q[::VERSION]}:q{[version und
+efined]};$numtyp=2>$modv=~tr/.// ?'%s':'% 6d';printf qq[ %-*s $numty
+p in %s\n],(length>30 ? 5+length:15+length),$modn,$modv,$INC{$_}}for
+@ARGV;" $*
;= rem SPECIALFOLDERS: Display Well-Known Folder pathnames
SPECIALFOLDERS=perl -MWin32 -e "my @ds=grep {/CSIDL_/} @{ [keys %Win32
+::] }; do {printf qq/%24s=>%s\n/, substr($_=>6),Win32::GetFolderPath(
+&{$Win32::{$_}})} for map {$_->[0]} grep {(0+@ARGV ? $_->[0]=~m#$ARGV
+[0]#i : 1)} sort {$a->[1] <=> ${b}->[1]} map {[$_,&{$Win32::{$_}}]} @
+ds" $*
;= :end
Documentation for the current version of PPM (3),
the crufty thingy that many MSwin users rely on to install new packaged Perl modules:
| ppm3 Documentation
|
- You can easily break your PPM v3 unknowingly merely by
updating Text::Autoformat – see
Bug Listing
|
- PPD file format – appears
to have not been updated since the 5.6 series releases at
ActiveState. Please note that it makes
no mention whatsoever of a parameter or field named
ARCHITECTURE NAME then go and in contrast
look at some example .PPD files from the various repositories.
Note Added:
This seems to be explained by
this brief excerpt
from the ppm Mailing List, authored by Jan Dubois:
"Since Perl 5.6 and Perl 5.8 are not binary compatible, we started appending
the Perl version number to the architecture string in ActivePerl 5.8. Try this:
<ARCHITECTURE NAME="MSWin32-x86-multi-thread-5.8" />
Both ppm2 and ppm3 in ActivePerl 8xx have been patched to use these architecture names."
|
- A (perhaps) little-known, rich PPM repository to add to your list that ppm searches.
|
- For Perl5.8 you may check status
of ActiveState's builds of packages (modules).
|
The dmake utility:
|
The recommended tool for building Perl from the source kit using a Free C/C++ compiler
(MinGW), is dmake. This variant of the classic make tool is now
maintained by OpenOffice.org folks ("tools" Project) and the dmake manpage is online.
dmake on CPAN: is now maintained by
Steve Hay and is no longer the extremely old code offered years ago by Gurusamy
Sarathy. Steve is building it using MSVC++ from the OO.org source mentioned above.
|
·For EveryMonk· (any platform)
Investigate the modules and libraries your Perl installation
has access to:
Tom Phoenix' script "Inside" on CPAN.
Need Help Using CPAN Effectively?
Preflight-check for CPAN.pm mirrors (using system `ping(1)'):
perl -MCPAN -l \
-e 'CPAN::Config->load;' \
-e '@pcnt= $^O eq "cygwin"? qw(-n 2):qw(-c 2);' \
-e ' do{ $fn=$_;
if (s#^\w+p://([^/]+).*#$1#) {
print $fn; system("ping",@pcnt,$_); print "\n","-"x52
} }
for @{ $CPAN::Config->{urllist} }'
# code tested on cygwin and GNU/Linux
Find your system's master list of CPAN mirror sites, maybe freshen it up:
perl -MFile::stat -MCPAN -MLWP::Simple=mirror -le 'CPAN::Config->load;
+ my $fhost;' \
-e 'my $Mdat = $CPAN::Config->{keep_source_where}.q[/MIRRORED.BY];'
+\
-e 'if (-e $Mdat and -M _ < 14) { print qq[$Mdat: freshness OK, last
+ modified: ]' \
-e ' .gmtime stat($Mdat)->mtime()' \
-e '} else { ($fhost)=grep(/^http/,@{$CPAN::Config->{urllist}});' \
-e 'die "no suitable cpan http mirror host" if !$fhost;' \
-e 'printf q[%s],qq[File $Mdat not found or stale, will d/l fresh fr
+om $fhost ...];' \
-e 'mirror($fhost .q[MIRRORED.BY] , $Mdat) and print q[ ].gmtime(sta
+t($Mdat)->mtime)}'
Wrap the code above in a function in your shell initfile if you are a bash
user and you like to have such conveniences at your "fingertips", as I do:
function mirrorsrefresh
{
< above perl code here >
}
More tips on coping with CPAN.pm can be found
here at "dumpcpanurls" Snippet.
Easy way to see that script output gets a terminating newline automatically:
In scripts:
#! /usr/bin/perl -l
# *or*
$\ = "\n"; # do it once and won't have to again.
In one-liners (script is "-e"):
$ perl [other flags] -le "[some code]"
Filter newlines out of systems call results
%hash = ( key => grep [ chomp ], `which ps` );
which does the same things as:
%hash = ( key => grep {chomp || 1} `which ps` );
Attribution: seen on comp.lang.perl.misc
in msgid <3F447BDB.9928761A@acm.org>.
Slurp an entire file in
# Previous declaration of "$filename" is assumed.
my $data = do{local(@ARGV,$/) = $filename;<>}
Attribution: here
Another way to do this, faster and better:
my $data = do{ open local(*FH),$filename or die "can't open: $!" ;
sysread( FH, my $buf, -s FH ) ; $buf ;
};
Something that may be called "The Bartian Transposition" someday:
(@a[0 .. ($#a = $#b)], @b) = @{[ @b, @a]} # swap two arrays
Where's my HOME???
my $home = $ENV{'HOME'} || $ENV{'LOGDIR'} ||
(getpwuid($<))[7] || die "WAAAAA! I'm HOMEless!\n";
# from `perldoc perlop'.
Something really special:
Opcode scanning for Safe.pm
Dump a string of opcode names that can be fed to Safe::new->permit. Based on knowledge / shell
elan shared by ysth.
$ perl -MO=Concise,-exec <FILENAME.pl> \
| perl -lnaF -e '$_=$F[2]; s/\W.*//; $h{$_}=0; END{ print join " "=>k
+eys %h}'
Created 30 Jul 2003 EDT (GMT+4):
Updated Thu Jul 31 2003
Updated Sun Jul 04 2004
Regarding the Meditation on List Cleanup
[After getting helpful advice on the node above I rewrote the snippet (as a complete scriptlet) ... several times (mostly recently on July 4 2004)]
The goal is to eliminate duplicates without disturbing existing
ordered-ness. Thus the property of mundane hash assignment such
that duplicates disappear is not sufficient by itself, but in a
combination demonstrated in this code below, the truth-ness of
a hash value can be used to prevent duplicate array entries.
#! /usr/bin/env perl
# "uniqnord" - remove dups from a list of identifiers.
use strict; use warnings;
$, = ! -t STDOUT ? "\n" : " " ;
my %seen = (); $\ = "\n";
print STDOUT join($, =>
grep {!$seen{$_}++} map {
if (/ +/) { $/=" " ; @_=split }
else { chomp ; $_ }} <>)
__END__
|
The real code:
#! /usr/bin/env perl
# "uniqnord" - remove dups from a list of identifiers.
use strict; use warnings;
$, = ! -t STDOUT ? "\n" : " " ;
my %seen = (); $\ = "\n";
print STDOUT join($, =>
grep {!$seen{$_}++} map {
if (/ +/) { $/=" " ; @_=split }
else { chomp ; $_ }} <>)
__END__
|
|
Posts by Intrepid
|
acsite.m4 compilation from Autoconf Archive D/L's
in Cool Uses for Perl
No replies — Read more | Post response
|
by Intrepid
on Jul 17, 2003 at 03:42
|
|
|
My last PerlMonks posting was a CUFP that related very specifically to Microsoft Windows (but had the saving grace that it related to Free/Open-Source software insofar as I had written it in order to use Cygwin, that is, GNU-on-Windows, more effectively). So to be balanced and all, this submission for the perusal of the monkly Sis/Breth-ren relates to the very GNU-oriented developer's tool Autoconf and specifically to the use of macros in the authorship of those darned complex-icated configure files that are used to prepare the directed compilation of so many Open Source packages.
My CUFP this time is another very, very simple tool (because that's what I like most: the simple tools) that just does one thing. Before I explain what it does I'll just show the code:
#! /usr/bin/env perl
=for gpg
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
=cut
# update_acsite -- Place all m4 autoconf macros found in DIR into the
+file named
# "acsite.m4" under ${PREFIX}/share/autoconf.
use warnings;
use strict;
use File::Glob qw{:glob};
use File::Spec::Functions qw{rel2abs splitpath file_name_is_absolute
catfile canonpath};
use vars qw{@MacrDa};
my $MyDir = $ARGV[0] || q|/usr/local/share/repository_ac_macros|;
my $OutFN = $ARGV[1] || q|/usr/local/share/autoconf/acsite.m4|;
my $OutDN = (splitpath($OutFN))[1];
# my $MyGlb = catfile($MyDir , "*.m4");
$MyDir = rel2abs( canonpath($MyDir) => '' ) if
not file_name_is_absolute($MyDir);
die "This process cannot write to the dest directory: $!" if
not ( -w $OutFN || (-d $OutDN && -w _) );
die "This indicated directory does not exist!: $!" if
not chdir( $MyDir );
my @repos_macs = bsd_glob( '*.m4' ,
GLOB_ERROR | GLOB_MARK | GLOB_NOCASE | GLOB_TILDE | GLOB_NOSORT
);
if (@repos_macs) {
foreach my $macfile_data (@repos_macs) {
my $fsz = -s $macfile_data;
(my $fln = <<"!ROBUSTO!" ) =~s/^\s*//mg;
dnl ------------------------------------------------------------
+-
dnl The next file added $fsz bytes to this collection.
dnl file: $macfile_data
dnl ------------------------------------------------------------
+-
!ROBUSTO!
open IFH,$macfile_data or
die "Failed to open() \"$macfile_data\" ";
read(IFH, my $data, $fsz);
$data or die "Could not read any data from \"$macfile_data\"";
close IFH;
push @MacrDa , qq{\n\n}, $fln , $data;
}
open OFH,">$OutFN" or die "Cannot open() the outfile \"$OutFN\" -- $
+!";
print OFH @MacrDa;
} else {
my $me = (splitpath($0))[3];
print STDERR <<"!CLEMENTINE!";
$me terminated because there were no macro *.m4 files found in the ind
+icated
or default directory location. Please check your arguments and try aga
+in.
!CLEMENTINE!
}
__END__
=begin gpg
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: For info see http://www.gnupg.org
iD8DBQE/FWU8BXOj2U4kTqYRArKyAJwKJ/9gmyof0MZJ+Ao2TQ+rcPEwYQCdEmdC
5/oKZKbs5XfVaHlvV1r3h+0=
=TX52
-----END PGP SIGNATURE-----
=end gpg
This Program is Free Software,
(C)2003 Soren Andersen <somian -AT- pobox -DOT- com>
it may be used under the same terms as Perl itself.
Now what's going on there is this. Being the kind of laid-back mellow dude that I am, I recently surfed over into the two AC Autoconf Macro archive sites (who are:
...) and I did what comes most naturally to me, just started downloading whatever looked useful. So I ended up with a newly-created directory populated with files ending in .m4 and wondered how to use them.
Autoconf (versions going back how far?) will add any macros found in a file named acsite.m4 located in the top Autoconf "lib" (conceptually) directory. In the case of my own recent site-local (manually installed) Autoconf that is in /usr/local/share/autoconf , macros in such a file will be known to Autoconf (when it is looking for definitions while building the configure file from configure.ac).
Autoconf m4 macros are conceptually very much like Perl modules. They extend the functionality of Autoconf in an analogous fashion and embody the primary Virtue of code reuse. My simple Perl tool just slurps in all the .m4 files it finds in the given dir and writes them all out to the single properly named file (the user is responsible for telling the program where the file should be be properly placed). There's not much Perl there but there was a gap in the convenience of the AC Archive concept that I thought Perl should be the one to fill. And yes, the Archive(s) offer all the macros bundled into downloadable archive files, and that would be perhaps another shortcut. I felt that I didn't want ALL the macros but just the ones that seemed useful or interesting to me, and I can always go back and add more later. Perl will take care of adding them to my working Autoconf system: I can re-run update_acsite anytime I want and it will just Do The Right Thing. IMHO, this comprises a CUFP.
| PS: |
Q: OK, what's up with the signed code?
A: See perlsign. Another CUFP, IMHO ;-)
|
|---|
|
Create MSWindows Registry REG_EXPAND_SZ entry
in Cool Uses for Perl
2 direct replies — Read more / Contribute
|
by Intrepid
on Jul 02, 2003 at 05:47
|
|
|
Hi, Monks. I've been trying to add a MS Windows shell context entry to
enable me to alternate-mouse click on a file or folder in
Windows Explorer GUI, and have the file name as Cygwin sees it
placed on the Clipboard. Because the Perl tool I wrote
to help me accomplish this was used it for enhancing
my enjoyment of Cygwin, this qualifies in my book as a CUFP.
This (context-menu access to the Cygwin-mode filename) has been invented before, but TTBOMK nobody has shown
how to make it portable across different people's systems
without editing the .reg file manually.
BTW, to get this to work I used what's already defined in my master Windows ENV, a
variable %CYGROOT% which points to the MSWin32 mode path spec of
the top of my Cygwin installation tree.
Substitute your own
different software installation needs and you may agree that this could be pretty useful once in a while.
Update:
Except that you cannot get Win95, 98, prob. ME to import
such a key value-data type into the Registry. I have just
found out that the inferior REGEDIT tool supplied with these inferior versions of Windows is incapable of doing this. The later NT4/5-derived Windows can do so.
There's really some Perl coming soon, I promise. I just dislike very incomplete and puzzling explanations that
people sometimes give about software I am unfamiliar with, that leaves me totally in the dark about why they bothered.
So here's the rest of the set-up...
There are several "DATA TYPES" (Microsoft
terminology) possible for
MS Win Registry entries. The type most of us would call a "C string" is called a REG_SZ and is formatted as a
simple string (but with some complex quoting and escaping rules). There's a logically and semantically (since "SZ" is
is Microsoft-speak for "null-terminated string") related Registry data type called a REG_EXPAND_SZ that can contain a level of "indirection" in the form of a
system variable that can be resolved at the time of use of
the entry. For example:
"SoMeThIng"="%WINDIR%\\system32"
could in our naive imagination be a Registry
.REG -file line indicating a directive to insert a value-data pair into a key, except that REG_EXPAND_SZ
data must be presented as
what MS calls a *binary* data type (subtype "2"), so
the value must be formatted in a kind of hexidecimal format, comma-delimited, two tokens per byte (padded with zeros),
with a terminating null byte of course
(and further explanation is obviously far beyond the scope of this article, and the author won't be held responsible for anyone's misuse of the incomplete information given thus far).
So the line above will not work but indicates the end result I wanted to achieve.
As a real working .REG -file entry the example above must be rendered as:
"SoMeThIng"=hex(2):22,25,57,49,4e,44,49,52,25,5c,5c,73,79,73,74,65,6d,33,32,22,00
Finally we get to the Perl. Perl does what's needed here with such elegance and efficiency, <sigh>. Given a
"Registry psuedo-code" string that *describes* what we want
the "decoded" string to look like, like that shown earlier, Perl can generate the kind of hex format needed for inclusion of the line in a REGEDIT .REG file:
UPDATE:
Ooops. I forget to chomp() the newline before encoding it
when taking data from <STDIN>. Fixed now. Well, classic CRLF vs. LF gotcha. NOW is fixed.
UPDATE:
Ooops, again. Not showing sterling recall of my sprintf() style ;-). Need to pad to two tokens per byte, format: "%02x". Debugging continues.
UPDATE (July 06, 2003):
Apparently, REGEDIT5 (e.g., on Win XP) exports such REG_EXPAND_SZ data with a null byte 00 after every real byte. These tools here will clearly fail to create or decode such a stream and therefore are limited to handling REGEDIT4 -style .REG files.
#!/usr/bin/perl -w
# "REGexpandSZgen" - generate the formatted hex string from a normal
# ascii input string- for a REGEDIT file; to enter a REG_EXPAND_SZ
# data-type entry into the MS Windows Registry.
use strict;
my $encme = pop(@ARGV) || <STDIN>;
$encme =~s% (\x{0d}|\x{0a}{1,2})\Z
%%x;
if($encme =~m{^("[^"]+"|\@)\=(.*)$}) {
# " does not appear where "entry"= @
$encme = [$1, $2];
}
my $cvtd = [ map { sprintf "%02x",ord } split('',
ref $encme ? $encme->[1]:$encme) ];
if(not $ARGV[0]) {
print '', (ref $encme ? "$encme->[0]=":""),
"hex(2):", join(',',@$cvtd,'00'), "\n";
} else {
# any prepended arg causes us to
# debug / test / verify the string.
print "\n IN: ",(ref $encme ? $encme->[1]:$encme),"\nOUT: "
, pack("c*", map(hex, @$cvtd[0..(@$cvtd - 0x1)]))
, "\n";
}
__END__
This Program is Free Software,
(C)2003 Soren Andersen <somian -AT- pobox -DOT- com>
it may be used under the same terms as Perl itself.
I needed a debugging tool, so I whipped up a decoder too...
#! /usr/bin/perl -wl
# "REGdecodeSZ" - decode Microsoft .REG -style null-terminated
# strings encoded as comma-delimited sequences of hex bytes.
use strict;
my ($instr, @barr);
chomp($instr = <STDIN>)
unless( $instr = $ARGV[0x0] );
my $to = 0x1 * (@barr=split q/,/ , $instr);
print join '',
(
map { chr hex } @barr[
0x0 .. ($to ? $to - 0x2
: $to) ]
);
__END__
This Program is Free Software,
(C)2003 Soren Andersen <somian -AT- pobox -DOT- com>
and it may be used under the same terms as Perl itself.
I haven't shown all the pieces -- particularly the .REG
file which actually modifies the Registry, because that
isn't Perl and doesn't really pertain to the broader concept. The reader who is left wanting a look at the rest of the pieces of this, my excuse-for-the-evening to crank out some Perl hacks, is encouraged to check the Cygwin mailing List archives (from
the Cygwin site)
for the recent and many past discussions relating to this specific idea.
|
Generate randomized .sig compiled file for Pegasus E-Mail (Win32)
in Cool Uses for Perl
No replies — Read more | Post response
|
by Intrepid
on Mar 03, 2001 at 07:44
|
|
|
This special-purpose script has been updated on Thurs Sep 13, 2001 to reflect improvements needed to make it more compatible with the ugly realities of MS Windoze OS's: the code using a shell file descriptor redirect 2>&1 has been conditional'd-out for users of non-NT systems (which are far more seriously broken). The code has now been used and tested on Win98.
Soren Andersen
Original description:
I think this is a pretty good CUFP, if somewhat esoteric
Pegasus Email for Win32 is a widely used and fine zero-cost email client. It has the feature that it can load a file at run time which contains an arbitrarily large collection of email .sigs, and include these into outgoing messages randomly. In order to set it up for Pegasus to do this, one must manually create the binary "RQUOTES.PMS" file and place it one's Pegasus user directory. This file is a compiled resource file produced from a human-readable text file using the resource compiler <CITE>rescom.exe</CITE>, included in Pegasus Email.
Further steps are also required on the Pegasus menu level and although not difficult to accomplish, rigorously detailing them here is beyond the scope of this posting and OT for this Monastery. That info is available in the Pegasus documentation.
The program requires the endlessly enjoyable and useful Perl module Text::Autoformat (CPAN). Naturally as it is only relevant to the Win32 Perl user group, it also uses Win32:: modules. File::Compare is also used. The code is rough and user convenience hasn't been dealt with; lots of manual setup will be needed.
Intrepid (Soren)
#!perl -w
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# "MakePSigs.p" is a Perl-on-Win32 program for managing the auto-
# generation of a random .sig compiled resource file that is used by
# Pegasus Email for Win32.
# Copyright (c) 2001 Soren Andersen. All Rights Reserved.
# This program is Free Software and may be used, copied or modified
# subject to the same terms as Perl itself.
# L/M: Thu Sep 13 18:28:00 2001
#
# sample invocation:
# $> MakePSigs.p "soren" "E:/data/var/MBOXEN/RQUOTES.PMS"
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
use Text::Autoformat;
use Win32;
use Win32::FileOp;
use Win32::Process;
use File::Compare qw{cmp};
use strict;
use vars qw{ $QuoSrc $QuoteFile $Backup $WrkDir
$RPG_rsc $Whatever $ShortQFname @Msgs
@Quotes $TodayNow };
use subs qw{ &EntryFormat &ErrorReport &UnDOS &ReDOS};
# DO USER CONFIGURATION OF PATHS HERE
$QuoSrc = 'E:/data/textfile/email_sigs/Philosophic_random_src.txt';
$WrkDir = 'E:/Pegasus/Resource';
# "Rquotes.pms" goes where your Pegasus user files live:
$RPG_rsc = ($ARGV[1])? $ARGV[1] : 'G:/Pegasus_user/Rquotes.pms';
# DONE WITH USER CONFIGURATION
$Whatever = '';
my $pegasus_user = ($ARGV[0])? lc $ARGV[0] : 'default';
($QuoteFile,$Backup) = ( ReDOS($WrkDir).'\Rquotes.'.$pegasus_user,
ReDOS($WrkDir).'\Rquotes.'.$pegasus_user .q[BU]);
open(QRAW, qq[<$QuoSrc]) or
die autoformat(<<OUTPUT
There is something wrong, I could not open() the quotations
text source file "$QuoSrc", are you sure it is really there? -
"$!"
OUTPUT
, {all =>1});
sub UnDOS { my $pathspec_expression = shift;
$pathspec_expression =~s@\\@/@g;
return $pathspec_expression; };
sub ReDOS { my $pathspec_expression = shift;
$pathspec_expression =~s@/@\\@g;
return $pathspec_expression; };
$ShortQFname = UnDOS( Win32::GetShortPathName(
UnDOS($QuoteFile) ) );
print STDERR qq[\n DIAGN: "$ShortQFname" is file name\n];
my $block = 0; my $current = [];
while (<QRAW>) {
if (/^\<\<$/ ) {
$Quotes[$block++] = $current;
undef $current;
(eof)? last:next;
}
push @$current, $_;
}
close ( QRAW );
foreach my $rand_sig (@Quotes) {
print STDERR qq[\n], &EntryFormat($rand_sig);
}
print STDOUT qq{\n}, '-' x 58, qq{\nWould you like to add these},
qq{ quotes to the Random Philosopical Quote (RPQ) file?\n};
if (<STDIN> =~/Y(?:es)?/i) {
CopyEx($QuoteFile => $Backup,
FOF_ALLOWUNDO | FOF_FILESONLY) if -e $QuoteFile;
open RPQ, qq[> $QuoteFile] or die $!;
$TodayNow = localtime(time);
print RPQ<<FINI;
# file automatically generated, last revision on $TodayNow
headers off # Ignore this command
symbols off # Ignore this command.
FINI
foreach my $rand_sig (@Quotes) {
print RPQ qq[\n], &EntryFormat($rand_sig);
}
close( RPQ ) or die $!;
chdir "$WrkDir" or die
qq[\nCould not cd into wrkng Peg dir "$WrkDir":\n$!];
if (Win32::IsWinNT()) {
(my $piD = open RPQCC, ReDOS($WrkDir).q[\Rescom.exe].
qq[ $ShortQFname 2>&1 |]) or
die qq[We had pipe-open() trouble. ],
qq[Could not open "rescom.exe":],
qq[\n$!];
push @Msgs, qq[\n\nMessages from the resource compiler:\n\n];
if (defined $piD) {
while (<RPQCC>) {
push @Msgs, ' '. $_;
$Whatever = $1 if (m@Created\s resource\s file\s
([A-Z]:/.+/Resource/RQUOTE.+\.rsc) \:@xi);
}
}
close( RPQCC ) or warn qq[Cannot close the pipe-handle?!:\n $?];
} elsif (Win32::GetOSVersion()) # return values: Win9x 1, WinNT 2
{
select STDERR; $|++;
select STDOUT; $|++;
my ($spawnd, $pid, $exitcode);
Win32::Process::Create($spawnd, q[RESCOM.exe],
"RESCOM $ShortQFname -w -a", 0, CREATE_NEW_CONSOLE, ".")
|| die ErrorReport();
if ( $pid = sprintf(q[%#8X],$spawnd -> GetProcessID()) ) {
print STDERR qq[\nThe RESCOM.EXE process was successfully ],
qq[started and is running as PID $pid\n];
$spawnd -> Wait(3000);
$Whatever = q[RQUOTE~1.RSC];
$spawnd -> GetExitCode( $exitcode );
my $rverb = substr (Win32::FormatMessage($exitcode << 256),
0, -2);
$rverb = ($rverb)? $rverb : q[OK];
print STDERR qq[\n Exit status for the RESCOM process: ],
( $exitcode << 256 ), qq[ ("${rverb}")\n];
} else {
warn autoformat( qq[\nThe RESCOM.EXE process was ].
qq[ not started right, no pid returned ...] );
}
}
print STDERR @Msgs,qq[Done compiling, did it go satisfactorily?\n];
if (<STDIN> =~/Y(?:es)?/i and $Whatever) {
$Win32::FileOp::ProgressTitle =
qq[Copying Pegasus resource file $Whatever to user dir];
CopyConfirm("$Whatever" => "$RPG_rsc") or
die qq[Copy .RSC to Pmail user dir failed:\n$^E \n($!)];
if ( cmp( $Whatever,$RPG_rsc ) ) {
warn qq[Copy .RSC to Pmail user dir .PMS failed:\n],
qq[the files are not the same];
} else {
print STDERR qq[\nDone! -- $RPG_rsc is ],
int(-M $RPG_rsc), qq[ days old.\n];
}
} else {
print STDERR qq[\nYou've elected to abort the procedure? OK.\n];
exit 2;
}
} # END IF STDIN =~"yes"
exit 0;
# ================ SUBS ===================
sub EntryFormat {
my $sigquote = shift;
my @sigquote = do {
split qq[\n],autoformat(join(q[ ],'',@$sigquote),
{ all =>1, left =>5, right =>68} );
};
@sigquote = map{
s@\"@'\"'@ge if length >= 0;
$_ .= '\n' if length >= 0;
if ($_ !~/^$/) {$_;} else {'';}
} @sigquote;
@sigquote = map{$_ = qq["$_",\n];} @sigquote;
my $final = join '', @sigquote;
my $entry=<<DONEDEAL;
text x
{
$final
};
DONEDEAL
return $entry;
}
sub ErrorReport{
print Win32::FormatMessage( Win32::GetLastError() );
}
=pod
=head1 Name
MakePSigs
=head1 Synopsis
C<perl MakePSigs.p [Pegasus login name] [pathspec for outputfile]>
=over 3
The Pegasus Email login name is optional; if not used, the script
will paste the suffix ".default" onto the end of generated
filenames. You'd want to name the source textfile (see below)
appropriately, then, B<before> running the script.
=back
=head1 Description
B<Pegasus Email for Win32> is a widely used and fine zero-cost email
client. It has the feature that it can load a file at run time which
contains an arbitrarily large collection of email .sigs, and include
these into outgoing messages randomly. In order to set it up for
Pegasus to do this, one must manually create the binary "RQUOTES.PMS"
file and place it one's Pegasus user directory. This file is a
compiled resource file produced from a human-readable text file
using the resource compiler F<rescom.exe>, included in
"Pegasus Email for Windows."
Further steps are also required on the Pegasus menu, namely setting
a signature choice with the characters `B<~!>' (B<tilde-bang>) at
the place where you want the randomely-chosen quote to be inserted.
See the Pegasus Email for Windows documentation.
The program requires the endlessly enjoyable and useful Perl module
F<Text::Autoformat> (CPAN). Naturally as it is only relevant to the
Win32 Perl user group, it also uses F<Win32::> modules.
F<File::Compare> is also used. The code is rough and user
convenience hasn't been dealt with much; some attention to manual
setup will be needed.
=head2 The Source file Format
The script reads in from a source file, a text file with a format
along these lines:
"The reasonable man adapts himself to the world ...
the unreasonable man persists in trying to adapt the world to himself
+."
"Therefore, all progress depends on the unreasonable man."
-- George Bernard Shaw
<<
"Kindness is the flower of strength."
-- Jose Marti, Hero of Cuban Independence
<<
The example file above has been indented in this POD documentation
to preserve formatting; in actual use there would be no left margin.
The E<lt>E<lt> characters on a line alone is the delimiter between
quotes. Make sure the last quote in the file is followed by the
delimiter I<or the script will break>.
=head2 from Pegasus header:
## Compile this source using ResCom.exe, by issuing the
## command "ResCom RQUOTES.R", then copy the resulting
## RQUOTES.RSC file into your home mailbox as RQUOTES.PMS.
##
## So, the sequence of commands looks like this:
##
## C:\PMAIL> rescom rquotes.r
## C:\PMAIL> copy rquotes.rsc f:\mail\9000001\rquotes.pms
=head1 AUTHOR
Soren Andersen E<lt>libertador@flashmail.comE<gt>
=for html
<A HREF="mailto:libertador@flashmail.com">libertador@flashmail.com</A>
=head1 COPYRIGHT
Copyright (c) 2001 Soren Andersen. All Rights Reserved.
This program is Free Software and may be used, copied or modified
subject to the same terms as Perl itself.
=cut
|
gcc_spec_check
in Cool Uses for Perl
No replies — Read more | Post response
|
by Intrepid
on Dec 19, 2000 at 05:21
|
|
|
A little tool for developers.
Updated: 22 Jan 2004 — Major re-write. Now named gcc-spcdmp
No longer relies on the deprecated (now) File::PathConvert module, only on core Perl libraries. This is considerably better code than I wrote in 2000 when first posted to PM.
Links provided for reader convenience:
- This script's documentation as POD:
gcc-spcdmp.pod
|
- This script as syntax-hilighted stand-alone code, no POD:
gcc-spcdmp.html
|
- This script's "production copy" with inline POD and cryptographically signed:
gcc-spcdmp
|
| links last checked: 22-Jan-2004 |
#!/usr/bin/env perl
eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
if 0; # not running under some shell
package main;
###
# gcc-spcdmp - cleans up output from spec check on GNU C compiler suit
+e.
###
## Last modified: 22 Jan 2004 16:00:52
# (c)2000,2004 Soren Andersen
# Kode Kudos to Shigio Yamaguchi & Barrie Slaymaker.
#======================= cvs/rcs internal data =======================
+======#
## $Source: /usr/src/repositories/cvs/perl-proj/devtools/gcc-spcdmp,v
+$
## $Date: 2004/01/22 20:51:48 $
## $Revision: 1.4 $ ##
#=====================================================================
+======#
require 5.005; # qr// operator.
use strict;
import File::Cleanspec 'concise'; # use File::Cleanspec;
use Env ('SHELL','COMSPEC');
use Text::Wrap ('wrap','$columns');
use Pod::Usage 'pod2usage';
BEGIN {
my( $argC,$argN ) = ( +@ARGV , $ARGV[$#ARGV] );
if( grep { $_ eq lc($argN) or $_ eq substr lc($argN)=>1 }
qw/ -h -u -man -help -usage / ) { pod2usage(-verbose => 2) }
elsif ($argC > 1 ) { pod2usage(1) }
}
###
# included module code, see File::Cleanspec which may be released
# on CPAN someday (by the author of this program).
###
package File::Cleanspec;
require 5.002;
use strict;
BEGIN {
use Exporter ();
use vars qw (@ISA @EXPORT);
@ISA = 'Exporter';
@EXPORT = 'concise';
}
# set up global lexicals & their default values
my $fstype = 'Unix' ;
my $sep = '/' ;
my $sepRE = '/' ;
my $notsepRE = '[^/]' ;
my $volumeRE = '' ;
my $directoryRE = '(?:(?:.*/(?:\.\.?$)?)?)' ;
my $isrootRE = '(?:^/)' ;
my $thisDirRE = '\.' ;
my $parentDir = '..' ;
my $parentDirRE = '(?:\.\.)' ;
my $casesensitive = 1 ;
my $idempotent = 1 ;
# global regexen used in the indicated routines. These
# are initialized by setfstype, so they don't need to be rebuilt each
+time
# the routine that uses them is called.
# Used in realpath() to split filenames.
my $bnsRE ;
# This RE matches (and saves) the portion of the string that is just b
+efore the beginning of a name
my $begonRE ;
# This whopper of an RE looks for the pattern "name/.." if it occurs
# after the beginning of the string or after the root RE, or after a s
+eparator.
# We don't assume that the value of $isrootRE has a trailing separator
+.
# It also makes sure that we aren't eliminating '../..' and './..' pat
+terns
# by using the negative lookahead assertion '(?!' ... ')' construct.
+It also
# ignores 'name/..name'.
#
my $nspRE ;
#
# Matches '..$', '../' after a root
my $leading_parentRE ;
#
# Matches things like '/(./)+' and '^(./)+'
#
my $dot_sep_etcRE ;
#
# Matches trailing '/' or '/.'
#
my $trailing_sepRE ;
# based on "setfstype" in File::PathConvert by
# Shigio Yamaguchi & Barrie Slaymaker
#******************************************************************
sub _setfstype #********************************
#******************************************************************
{
my $osname = shift ;
# Find the best match for OS and set up our atomic globals accordin
+gly
if ( $osname =~ /^(?:(ms)?(dos|win(32|nt)?))/i )
{
$fstype = 'Win32' ;
$sep = '/' ;
$sepRE = '[\\\\/]' ;
$notsepRE = '[^\\\\/]' ;
$volumeRE = '(?:^(?:[a-zA-Z]:|(?:\\\\\\\\|//)[^\\\\/]+[\
+\\\/][^\\\\/]+)?)' ;
$directoryRE = '(?:(?:.*[\\\\/](?:\.\.?$)?)?)' ;
$isrootRE = '(?:^[\\\\/])' ;
$thisDirRE = '\.' ;
$parentDir = '..' ;
$parentDirRE = '(?:\.\.)' ;
$casesensitive = 0 ;
$idempotent = 1 ;
}
elsif ( $osname =~ /^MacOS$/i )
{
$fstype = 'MacOS' ;
$sep = ':' ;
$sepRE = '\:' ;
$notsepRE = '[^:]' ;
$volumeRE = '(?:^(?:[^:]+:)?)' ;
$directoryRE = '(?:(?:.*:)?)' ;
$isrootRE = '(?:^(?=[^:].*:)?)' ;
$thisDirRE = 'cantpossiblymatchthis' ;
$parentDir = '' ;
$parentDirRE = '(?=(?<=:):)' ;
$casesensitive = 0 ;
$idempotent = 0 ;
}
elsif ( $osname =~ /^VMS$/i )
{
$fstype = 'VMS' ;
$sep = '.' ;
$sepRE = '[\.\]]' ;
$notsepRE = '[^\.\]]' ;
# volume is node::volume:, where node:: and volume: are optional
+
# and node:: cannot be present without volume. node can include
# an access control string in double quotes.
# Not supported:
# quoted full node names
# embedding a double quote in a string ("" to put " in)
# support ':' in node names
# foreign file specifications
# task specifications
# UIC Directory format (use the 6 digit name for it, instead
+)
$volumeRE = '(?:^(?:(?:[\w\$-]+(?:"[^"]*")?::)?[\w\$-]+:
+)?)' ;
$directoryRE = '(?:(?:\[.*\])?)' ;
# Root is the lack of a leading '.', unless string is empty, whi
+ch
# means 'cwd', which is relative.
$isrootRE = '(?:^[^\.])' ;
$thisDirRE = '\[\]' ;
$parentDir = '-' ;
$parentDirRE = '-' ;
$casesensitive = 0 ;
$idempotent = 0 ;
}
elsif ( $osname =~ /^URL$/i )
{
# URL spec based on RFC2396 (ftp://ftp.isi.edu/in-notes/rfc2396.
+txt)
$fstype = 'URL' ;
$sep = '/' ;
$sepRE = '/' ;
$notsepRE = '[^/]' ;
# Volume= scheme + authority, both optional
$volumeRE = '(?:^(?:[a-zA-Z][a-zA-Z0-9+-.]*:)?(?://[^/?]
+*)?)' ;
# Directories do _not_ include the query component: we pretend t
+hat
# anything after a "?" is the filename or part of it. So a '/'
# terminates and is part of the directory spec, while a '?' or '
+#'
# terminate and are not part of the directory spec.
#
# We pretend that ";param" syntax does not exist
#
$directoryRE = '(?:(?:[^?#]*/(?:\.\.?(?:$|(?=[?#])))?)?)' ;
$isrootRE = '(?:^/)' ;
$thisDirRE = '\.' ;
$parentDir = '..' ;
$parentDirRE = '(?:\.\.)' ;
# Assume case sensitive, since many (most?) are. The user can o
+verride
# this if they so desire.
$casesensitive = 1 ;
$idempotent = 1 ;
}
# Now assemble our composite regexps
$bnsRE = '^(.*)'. $sepRE . '('. $notsepRE .'*)$' ;
$leading_parentRE = '('. $isrootRE .'?)(?:'. $parentDirRE . $sepRE
+ .')*'
.'(?:'. $parentDirRE
+.'$)?' ;
$trailing_sepRE = '(.)' . $sepRE . $thisDirRE . '?$' ;
$begonRE = '(?:^|'. $isrootRE .'|'. $sepRE .')' ;
$dot_sep_etcRE =
'(' . $begonRE . ')(?:' . $thisDirRE . $sepRE . ')+';
#---------------------------------------------------------------------
+-
# in english:
# nothing (start of string) or root or sep (captured)
# IF FOLLOWED BY something that is NOT . or .. FOLLOWED BY / (zero
+-width lookahead),
# FOLLOWED BY something that isn't / , FOLLOWED BY / , FOLLOWED BY
+ .. , FOLLOWED BY
# either / or nought (end of string).
$nspRE = '('. $begonRE .')'
. '(?!(?:'. $thisDirRE .'|'. $parentDirRE .')' . $sepRE .')'
. $notsepRE .'+' . $sepRE . $parentDirRE
. '(?:'. $sepRE .'|$)' ;
#---------------------------------------------------------------------
+-
return $fstype ;
}
# based on "regularize" from File::PathConvert
# by Shigio Yamaguchi & Barrie Slaymaker
# (but note reordered substitutions).
#******************************************************************
sub concise #********************************
#******************************************************************
{
local $^W = 1;
my $in = shift @_ ;
# Combine idempotent separators. Do this first so all other REs o
+nly
# need to match one separator. Use the first sep found to preserve
# backward slashes on Win32.
$in =~ s/($sepRE)$sepRE+/$1/g if $idempotent ;
# We do this after deleting redundant separators in order to be co
+nsistent.
# If a Win32 path ended in \, we want to be sure that \ is returne
+d, not /.
my $trailing_sep = ($in =~ /($sepRE)$sepRE*$/) ? $1 : '';
# Get rid of ./ in '^./' and '/./'
$in =~ s/$dot_sep_etcRE/$1/g ;
# Get rid of trailing '/' and '/.' unless it would leave an empty
+string
$in =~ s/$trailing_sepRE/$1/ ;
# Delete all occurences of 'name/..(/|$)'. This is done with a while
# loop to get rid of things like 'name1/name2/../..' ... we choose th
+e pattern
# name/../ as the target instead of /name/.. so as to preserve 'rootn
+ess'.
# see explanation of this regexp "$nspRE" above.
do {} while $in =~ s/$nspRE/$1/g ;
# Get rid of '../' constructs from absolute paths
$in =~ s/$leading_parentRE/$1/ if ( $in =~ /$isrootRE/ ) ;
# Restore trailing separator if it was lost. We do this to preserv
+e
# the 'dir-ness' of the path: paths that ended in a separator on e
+ntry
# should leave with one in case the caller is using trailing slash
+es to
# indicate paths to directories.
$in .= $trailing_sep
if ( $trailing_sep ne '' && $in !~ /$sepRE$/ ) ;
return $in ;
}
# Executed once when module is loaded. No "1;" at last line because we
+ *DON'T* WANT
# perl to succeed in loading the module if this sub fails. IOW, this s
+hould always
# return true anyway.
my $detected = _setfstype($^O);
###
# end of included module (package space) "File::Cleanspec"
###
package main;
my $setfstype = \&File::Cleanspec::_setfstype;
$columns = 76;
my( $specHd , $fndelim , $fh , $bg2en , @bconfig
, $bctarget , $rootish , $realvol , @goods , %compo );
my $divdr = qq(\n ) . '-' x $columns . qq(\n);
my $cntdefs = 0;
my $sanify = {};
my $cppdefchr = qr{ [-_=0-9a-zA-Z]+ \s* }x;
my $flegalchr = q{[-.\w]};
my @intro = (qq{\n GCC component tools:});
my $gcc_cmd_path = 'gcc';
do { eval "select $_ ; $| = 1 ;" } foreach qw{STDERR STDOUT};
$specHd = $fndelim = '/';
if ($ARGV[0] and $ARGV[0] eq '-demo')
{ # demo
print STDERR " *** D E M O ***\n";
$fh = \*DATA;
$specHd = '[A-Z]:';
$fndelim = quotemeta '\\';
$setfstype->( 'mswin32' ) eq 'Win32' or die "Cannot set fstype";
}
elsif # we supply an alternate name for gcc invocation:
($ARGV[0])
{
$gcc_cmd_path = shift @ARGV;
$gcc_cmd_path =~ s@\\@/@g;
}
if ( (not $SHELL) or
(not $ARGV[0]
and
($COMSPEC &&
$COMSPEC=~m@(?:CMD(?:\.EXE)?|COMMAND(?:\.COM)?)@i
and
eval{
my $prb=`gcc -dumpmachine`;
1 if $prb =~/\-mingw/m;
}
))
)
{
$setfstype->( 'mswin32' );
$specHd = '[A-Z]:';
$fndelim = quotemeta '\\';
}
elsif ($^O =~ /cygwin/ and
$SHELL and $SHELL =~ m% [[:alpha:]]{0,2}sh %x)
{
$specHd = $fndelim = '/';
if ($ENV{'CYGROOT'})
{
$rootish = $ENV{'CYGROOT'};
}
else
{
chomp( $rootish = `cygpath -wa /` );# print qq(\n My CygROOT: $roo
+tish\n);
}
$realvol = substr( $rootish, 0, 2 );
$rootish = quotemeta( substr( $rootish, 3 ));
$setfstype->( 'unix' );
}
if (! defined $fh)
{
die "drat, no touch!" if system qq(touch foo.c);
open SHPIPE, qq(2>&1 $gcc_cmd_path --verbose -c foo.c | )
or die qq(We haven't got a good open() here?!\n$!);
$fh = \*SHPIPE;
}
my $re_FNstart = qq%$specHd$fndelim?$flegalchr+$fndelim\\S+%;
# print STDERR "RE for paths is \"$re_FNstart\"\n";
while (<$fh>)
{
last if /\A\s*\Z/ and eof;
my( $path , $processed , $reduced , $prepath
, $whol , $pstpath , $predef , $pstdef )
= map ('',(1 .. 8));
$bg2en = 0;
# s#/#\\#g; # for mswin-dos
if ( /\sas(?=\s-(V|o))/ or /$re_FNstart(?=\s)/o )
# May need some work?
# the above won't tolerate spaces in path specifications
# (Windoze users take note!). /^(?<=\s)$specHd $flegalchr+ $fndelim
+ \S(?=\s) /x
{
chomp($path = $&);
next if /as -o/ or q'"' eq substr($path, -1);
chomp($whol = $_);
$prepath = $` if $`;
$pstpath = $' if $' and not m@\-(?:D|A)$cppdefchr@;
$bg2en = 1 if $whol =~/\Q$path\E/;
unless ($specHd eq '/')
{
$reduced = concise( $path );
# debugging stuff
print STDERR qq(\n * Oops, "concise()" failed: ),
$reduced, qq(\n from path: $path\n)
if $reduced =~m@\Q$fndelim\E\.\.\Q$fndelim@;
}
elsif ($rootish)
{
my $cpath = concise( $path );
chomp( $reduced = `cygpath -wa $cpath` );
my $winpath = $reduced;
$reduced =~s@\\@$fndelim@g;
$reduced =~s@ $realvol (?:$fndelim$rootish)? @@x;
$sanify->{$reduced} = $winpath;
print STDERR qq(\n * Oops, failed: ),
$reduced, qq(\n win path: $winpath\n) if $reduced =~m@$fndeli
+m\.\.$fndelim@;
}
else # other uni*-like platforms .. sorry MacPerl-ites ;-(
{
$reduced = concise( $path )
or warn qq(\nTrouble from path spec "$path"\n);
}
if ( $pstpath =~ m@ -lang-c -v @
or /-(?:D|A)$cppdefchr/ )
{
my @defin = qq(\n);
my @other = ();
push @defin, grep /\-(?:D|A)$cppdefchr/, split /\s+/, $_;
push @other, grep !/\-(?:D|A)$cppdefchr/, split /\s+/,
substr($_, index ($_ => '-v'));
$predef = $` if $`;
$pstdef = $' if $';
push @goods , qq(\n), qq(\n)
, 'Default/automatic preprocessor-defined symbols:'
, (map { (sprintf( "\n [% 2u] ",
++$cntdefs). $_) if $_;
} grep {s@\s+\Z@@ || 1}@defin)
, qq(\n\n);
if (@other)
{
my $bopeep = 0;
push @goods, "Other CPP default conditions: ";
push @goods, map { s%[/\\]+%$fndelim%go;
/-iprefix/ .. $bopeep++ ?
($bopeep ? concise($_) : $_) : "" }@other;
push @goods, qq{\n};
}
}
my $comp;
if ($reduced =~ m@cpp (?:\.exe|0)? \Z@x) { $comp = 'CPP' }
elsif ($reduced =~ m@cc1 (?:\.exe)? \Z@x) { $comp = 'CC' }
elsif ($reduced =~ m@as (?:\.exe)? \Z@x) { $comp = 'AS' }
# -------------------------------------------------------------------
+-
if ($comp) { $compo{$comp} = qq|$divdr $reduced| ; next }
# -------------------------------------------------------------------
+-
unless ($rootish) { $_ = $prepath . $reduced . $pstpath }
else
{
$_ = $prepath . $reduced;
$_ .= qq|\n ** aka |. $sanify->{$reduced} .qq| **|
if exists $sanify->{$reduced};
$_ .= $pstpath;
}
$processed = $_;
$_ = $whol .qq(\n);
}
# -------------------------------------------------------------------
+-
my $comv;
if (/^GNU CPP version/) { $comv = 'CPP' }
elsif (/^GNU C version/) { $comv = 'CC' }
elsif (/^GNU assembler version/) { $comv = 'AS' }
elsif (/^\s*compiled by .+\.\d\.\Z/) { $comv = 'CC' }
# -------------------------------------------------------------------
+-
if ($comv)
{
my $parent = /\Q(cpplib)\E/ ? 'CC' : $comv;
chomp;
$compo{$parent} .= ($compo{$parent} ? qq[\n] : q[]);
if (substr( $compo{$parent}, -5, 3 ) ne '---') {
$compo{$parent} .= wrap(q| |,q| |,$_);
}else{
substr($compo{$parent},(-1 * (3 + $columns))
) = wrap(q| |,q| |,$_);
}
$compo{$parent} .= $divdr;
next;
}
# -------------------------------------------------------------------
+-
if ($processed =~ /Reading specs from/) {
unshift @intro => $processed ; next ;
} elsif (/\Agcc version/) {
unshift @intro => q( ).$_ ; next ;
}
if (/with:/)
{
$bctarget = substr($_, rindex ($_=>' '));
substr($_, rindex ($_=>' ')) = '' if $bctarget !~ /--\S+/;
push @bconfig => $_ ; next ;
}
elsif (/Thread model:/) { next }
push @goods => ($processed ? $processed : $_);
}
close ($fh); # Done reading in output.
# Post-process gcc & slaves output dumps.
unshift @goods => ( @intro
, grep { $_ } map($compo{$_} , qw(CPP CC AS)) );
# We're ready to tell all:
printin (@goods, 2);
printin ($divdr
, map( (/^(?:Configured|Thread)/? '':' --').$_.qq{\n},
map { split /\s+--/, $_ }@bconfig )
, ($bctarget ? "target $bctarget" : "")
, substr($divdr=>3), 2) if @bconfig;
exit 0;
sub printin
{
my $indent_by = pop;
$indent_by = ' ' x $indent_by;
foreach my $line (@_)
{
my $in = $line !~ m%\A\s*\Z% ? $indent_by : "";
printf STDOUT "$in%s" => $line;
}
}
sub END
{ # Clean up after ourselves.
unlink 'foo.c', 'foo.o';
}
__DATA__
Reading specs from D:\MinGW32\gcc-2.95.2\bin\..\lib\gcc-lib\i386-mingw
+32msvc\2.95.2\specs
gcc version 2.95.2 19991024 (release)
D:\MinGW32\gcc-2.95.2\bin\..\lib\gcc-lib\i386-mingw32msvc\2.95.2\cpp.
+exe -lang-c -v -iprefix D:\MinGW32\gcc-2.95.2\bin\..\lib/gcc-lib/i386
+-mingw32msvc\2.95.2\ -D__GNUC__=2 -D__GNUC_MINOR__=95 -Di386 -D_WIN32
+ -DWIN32 -D__WIN32__ -D__MINGW32__=0.2 -D__MSVCRT__ -DWINNT -D_X86_=1
+ -D__STDC__=1 -D__stdcall=__attribute__((__stdcall__)) -D_stdcall=__a
+ttribute__((__stdcall__)) -D__cdecl=__attribute__((__cdecl__)) -D__de
+clspec(x)=__attribute__((x)) -D__i386__ -D_WIN32 -D__WIN32__ -D__WIN3
+2__ -D__MINGW32__=0.2 -D__MSVCRT__ -D__WINNT__ -D_X86_=1 -D__STDC__=1
+ -D__stdcall=__attribute__((__stdcall__)) -D___stdcall__=__attribute_
+_((__stdcall__)) -D__cdecl=__attribute__((__cdecl__)) -D__declspec(x)
+=__attribute__((x)) -D__i386 -D__WIN32 -D__WINNT -D___stdcall=__attri
+bute__((__stdcall__)) -Asystem(winnt) -Acpu(i386) -Amachine(i386) -re
+map -Acpu(i386) -Amachine(i386) -Di386 -D__i386 -D__i386__ foo.c G:\T
+MP\ccZhaaaa.i
GNU CPP version 2.95.2 19991024 (release) (80386, BSD syntax)
#include "..." search starts here:
#include <...> search starts here:
D:\MinGW32\gcc-2.95.2\bin\..\lib\gcc-lib\i386-mingw32msvc\2.95.2\..\.
+.\..\..\include
D:\MinGW32\gcc-2.95.2\bin\..\lib\gcc-lib\i386-mingw32msvc\2.95.2\..\.
+.\..\..\i386-mingw32msvc\include
D:\MinGW32\gcc-2.95.2\bin\..\lib\gcc-lib\i386-mingw32msvc\2.95.2\incl
+ude
End of search list.
The following default directories have been omitted from the search pa
+th:
/gcc-2.95.2/lib/gcc-lib/i386-mingw32msvc/2.95.2/../../../../include/g
+++-3
/usr/local/i386-mingw32/include
End of omitted list.
D:\MinGW32\gcc-2.95.2\bin\..\lib\gcc-lib\i386-mingw32msvc\2.95.2\cc1.
+exe G:\TMP\ccZhaaaa.i -quiet -dumpbase foo.c -version -o G:\TMP\ccOpa
+aaa.s
GNU C version 2.95.2 19991024 (release) (i386-mingw32msvc) compiled by
+ GNU C version 2.95.2 19991024 (release).
as -o foo.o G:\TMP\ccOpaaaa.s
|
A little project - Web storage
in Meditations
1 direct reply — Read more / Contribute
|
by Intrepid
on Aug 09, 2000 at 16:01
|
|
|
Hello Monks,
A handful of free services on the Net are offering free "online hard drives" (I will leave it as an exercise to the reader to check out the specifics of the offers each entity makes). To make a short list, there is:
As a user I find a lot to be annoyed about concerning all these sites -- but they are free, after all, so complaining about their buggy systems is pretty pointless. However as a coder I am not satisfied to leave it alone; I cannot help but wonder if there isn't a challenge to be met there. If their coders cannot get their sites to work, maybe I can overcome the obstainancy of their systems with some judiciously applied Perl?
Just for reference, because some readers may wonder what I mean by "buggy", I'll observe that file uploads often fail. It may be that some of these services (I have accounts with them all <sigh> ..) have file size limits that I forget in between each time I need to upload (and I'd like to arrange for someone reliable, like Perl, to remember that kind of thing for me ... wouldn't this be true laziness ?) Also the desktop client software for Win32 that can be downloaded for most of the services is not working on WinNT (even though it is supposed to -- a situation that many NT users must find quite tiresomely familiar; it is an industry-wide problem with mass-marketed commercial software).
My meditation concerns this: an invitation to
- Let us know if anyone knows of existing Perl hacks into these systems, so that uploading or downloading of files from the remote storage server can be programmatically controlled;
- Let us know if anyone has been thinking about this, but hasn't written any working code yet;
- Let us (me specifically) know if the idea interests any fellow monks and they would like to collaborate on a project.
For my part I have little detailed knowledge of how these systems work, and don't want to assume without knowing more than I do, and I think that hacking this all by myself is a bit beyond my abilities at present. However I recently came across a clue that suggested to me that xdrive, for instance, is simply using a variety of FTP transaction (as might well all of them be) to upload to the remote server.
My guess is that this would be true "hacking" as the clueless mass media knows it, involving the running of a packet sniffer on one's system to monitor and suss out what is taking place between one's desktop / laptop box and the remote server, and then seeking to construct a workable emulation of that in Perl, adding all sorts of error-checking, redundancy and try-again-until-it-uploads obstinancy of course. I have never used a packet sniffer. A sockets guru might find this a worthy game?
I would welcome any replies, insights, or expressions of interest.
soren
|
Perl4Win32: prettify code syntax
in Cool Uses for Perl
No replies — Read more | Post response
|
by Intrepid
on Jul 20, 2000 at 07:01
|
|
|
Use code2html
to syntax-highlight and HTML-ify your code before posting to
'Monks, etc. This is a perl one-liner to work with code2html
utilizing Win32::Clipboard to transmogrify the code without writing
files which then would have to be opened, copied, etc.
perl -"MWin32::Clipboard" -e "$tmp=$ENV{'TEMP'};
$tmp.='\tmpcode2html'; $tmp=~s#\\#\\\\#g;
$clp=Win32::Clipboard(); $it=$clp->Get(); open(CH,\"^|perl -S
code2html -v -lperl -ohtml-dark ^>$tmp\") or die $!;
print CH $it; close CH; $tmp=~s#\\\\#/#g; open(TF,$tmp);
read(TF,$it,(-s $tmp));$clp->Set($it); unlink $tmp;"
Please note that this looks all wrong to UNI* gurus who see the
quoting through typical shell rules that apply there; Win is
different and there's a couple of not-well-known Windoze shell
escaping tricks demonstrated in this code, as well.
Also shows how to open a pipe to a process to be written to by
Perl, has the ugly kludge of writing a tmp file -- if anyone knows
a *Windoze*-workable way to avoid this please comment.
|
Perl-Win32 "filter" shortcuts
in Cool Uses for Perl
1 direct reply — Read more / Contribute
|
by Intrepid
on Jul 03, 2000 at 06:41
|
|
|
This special adaption or hybridization of the Perl one-liner and
the Windoze desktop environment allows users to set up a collection
of shortcuts that run operations in Perl. It is not drag-and-drop
in this instance, however. The text to be formatted (be it code or
simple comments) is first copied to the Windows clipboard, then
the shortcut is double-clicked. The processed text (which is now
HTML) is then pasted into the entry field in the browser window.
For users of Win32 Perl I want to share what I have cooked up to make posting remarks and code to PerlMonks a lot more automated, alluring ... Perl-ish. These could be termed "utility one-liners" but with a twist which makes them Win32-specific.
Snippet 1: format code
perl "-MHTML::FromText" "-MWin32::Clipboard" -e "$clp=Win32::Clipboard();$ct=$clp->Get(); $ct=text2html($ct,paras=>1,blockcode=>1,metachars=>1);$clp->Set($ct);"
Snippet 2: format ordinary comment or quoted text - step 1 -
perl "-MWin32::Clipboard" "-MText::Wrap=$columns,fill" -e "$clp=Win32::Clipboard();$ct=$clp->Get(); $columns=68;$ct=fill('','',$ct); $clp->Set($ct);"
Snippet 3: format ordinary comment text - step 2 -
perl "-MHTML::FromText" "-MWin32::Clipboard" -e "$clp=Win32::Clipboard();$ct=$clp->Get(); $ct=text2html($ct,paras=>1,blockquotes=>1,bold=>1,underline=>1,metachars=>1,urls=>1); $clp->Set($ct);"
Snippet 4: format quoted text - step 2 -
perl "-MHTML::FromText" "-MWin32::Clipboard" -e "$clp=Win32::Clipboard();$ct.=$clp->Get(); $ct=text2html($ct,lines=>1,spaces=>1,bold=>1,underline=>1,metachars=>1); $ct='<I><BLOCKQUOTE>'.$ct .'</I></BLOCKQUOTE>'; $clp->Set($ct);"
Snippet 5: deal with the square brackets - Perlmonks requires this extra step -
perl "-MWin32::Clipboard" -e "$clp=Win32::Clipboard();$s=$clp->Get();1 while( $s =~ s/ ([\[\]]) / sprintf \"&#%03u;\",ord $1 /exg);$clp->Set($s);"
To explain more clearly what I mean, I have created a little screenshot:
Each of these shortcuts has as its "Properties|Shortcut|Target" one of the perl one-liners shown here.
<IMG SRC="http://www.wonderstorm.com/cgi-bin/PNGem.pl?filtershortcuts" WIDTH=213 HEIGHT=153 HSPACE=16 VSPACE=10>
Message effectiveness can be said to eq substance + style. Poorly
formatted messages that require a lot of extra effort to read are
not as likely to be read as ones that are carefully presented.
Have to remark that there are those of us who love the command line
but don't plan on completely giving up our mouse and our GUI just
yet. The reason I make that statement has nothing to do with OSs or
inflamatory OT debates except to observe that more Windoze users
are (duh) more acclimated to doing things with the gui than at a
prompt. As I just said I am not interested in engaging in
judgemental debates about THAT, but i think there's a segment of
the monks out there (present or future) who would appreciate the
comfortable-ness of what I propose here, find it congenial, and
adjusted to their way of doing things. OTOH, Maybe i am wrong about
that but what does it matter.
So this snippet is about using a point-and-click means of rapidly
formatting text for entry into the kind of PerlMonks-site browser
entry field that I am using right now. It is Win32-specific. The
Windoze Explorer guishell allows one to right-click and create a
new shortcut. Normally a shortcut points to an existing file
somewhere on the filesystem, of course. The shortcut created in
order to use this Perl I am presenting isn't pointing to anything,
however (except the Perl interpreter). It is a one-liner IOW.
It is a form of the ordinary kind of copy-paste operation most
Monks perform (I assume) many times a day, but with the extra step
of double-clicking a (hopefully very easily accessible, keeping a
special Explorer window view open all the time on the Desktop is
one the points that make this a time-saver) "active" shortcut that
unleashes the power of Perl on the contents of the clipboard,
replacing what the user placed on it with same, but now in
HTML-ized form.
The code in the snippets goes in the field "shortcut" in the
Properties box of the "shortcut-filters" as I am calling these
little pieces of Perl code. In order to work the user must have the
module Win32::Clipboard (ppm to get it if you don't have it) and
uses HTML::FromText to do the magic.
Caution: Needless to say, these one-liners must be pasted into the
appropriate field as one-liners regardless of how they got
wrapped when displayed in the reader's browser rendering of this Perl Monks node.
|
|