Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: Perl: porters

Getopt::Long, + options, installperl, +v

 

 

Perl porters RSS feed   Index | Next | Previous | View Threaded


nick at ccl4

May 18, 2008, 11:40 AM

Post #1 of 22 (340 views)
Permalink
Getopt::Long, + options, installperl, +v

So I was taking a look at the TODO

=head2 merge common code in installperl and installman

There are some common subroutines and a common C<BEGIN> block in F<installperl>
and F<installman>. These should probably be merged. It would also be good to
check for duplication in all the utility scripts supplied in the source
tarball. It might be good to move them all to a subdirectory, but this would
require careful checking to find all places that call them, and change those
correctly.

=cut

and I noticed that one of the differences between the two is that installperl
has variables $nonono and $verbose, whereas installman has $opts{notify} and
$opts{verbose}. This is because installman uses Getopt::Long, whereas
installperl has hand-rolled argument parsing.

So, I wondered whether installperl should be dragged into the century of
the fruitbat and converted to Getopt::Long.

However, I spot this potentially troubling bit of code:

$versiononly = 1 if $ARGV[0] eq '-v';
$versiononly = 0 if $ARGV[0] eq '+v';

which dates from 2001:

http://public.activestate.com/cgi-bin/perlbrowse/p/8747

Change 8747 by jhi[at]alpha on 2001/02/09 18:12:04

Subject: versiononly and installperl
From: abigail[at]foad.org
Date: Wed, 7 Feb 2001 22:43:12 +0100
Message-ID: <20010207214312.7045.qmail[at]foad.org>

Add +v flag to force a normal install of the perl binary
and the utilities.

Subject: [PATCH] installperl
From: Nicholas Clark <nick[at]ccl4.org>
Date: Fri, 9 Feb 2001 16:28:57 +0000
Message-ID: <20010209162857.B10931[at]plum.flirble.org>

Add -A flag which also hardlinks the binary with
the full architecture name.


so I wondered how Getopt::Long copes with options starting with +
From skimming the man page and the code it seems that it can, if you set
getopt_compat. However, it seems that there is no way of it reporting back
whether one used a + or a - option.

So

1: is this correct?

2: if this is correct, should we find a new name for +v, and deprecate the
old name? (and after the deprecation cycle completes, refactor to use
Getopt::Long?)

(or is this makework, and life would be simpler if we replaced $nonono,
$verbose and friends with %opt, but kept the hand-rolled argument parsing
code?)

Nicholas Clark


jvromans at squirrel

May 18, 2008, 12:13 PM

Post #2 of 22 (334 views)
Permalink
Re: Getopt::Long, + options, installperl, +v [In reply to]

[Quoting Nicholas Clark, on May 18 2008, 19:40, in "Getopt::Long, + opti"]
> However, I spot this potentially troubling bit of code:
>
> $versiononly = 1 if $ARGV[0] eq '-v';
> $versiononly = 0 if $ARGV[0] eq '+v';
>
> ...
>
> so I wondered how Getopt::Long copes with options starting with +
> From skimming the man page and the code it seems that it can, if you
> set getopt_compat. However, it seems that there is no way of it
> reporting back whether one used a + or a - option.

Yes, that is right (although support for this is planned).

Currently, you can do it with a bit of extra work:

#!/usr/bin/perl

use strict;

# Disable '+' as a prefix.
use Getopt::Long qw(:config prefix_pattern=--|-);

@ARGV = qw(-v foo +v bar) unless @ARGV;

my $versiononly;

# To save possible arguments.
my @saved_options;

GetOptions
( '<>' => sub { # catch-all handler
my $a = shift;
if ( $a eq '+v' ) {
warn("Option +v is obsolete, please use --forcenormal instead\n");
$versiononly = 0;
}
else {
push(@saved_options, $a);
}
},
v => \$versiononly,
forcenormal => sub { $versiononly = 0 },
);

# Prepend saved options to @ARGV.
if ( @ARGV ) {
@ARGV = (@saved_options, '--', @ARGV);
}
else {
@ARGV = @saved_options;
}

# Demo.
if ( $versiononly ) {
warn("Version only install (ARGV = @ARGV)\n");
}
elsif ( defined $versiononly ) {
warn("Force normal install (ARGV = @ARGV)\n");
}

-- Johan


nick at ccl4

May 18, 2008, 12:19 PM

Post #3 of 22 (332 views)
Permalink
Re: Getopt::Long, + options, installperl, +v [In reply to]

On Sun, May 18, 2008 at 09:13:12PM +0200, Johan Vromans wrote:
> [Quoting Nicholas Clark, on May 18 2008, 19:40, in "Getopt::Long, + opti"]
> > However, I spot this potentially troubling bit of code:
> >
> > $versiononly = 1 if $ARGV[0] eq '-v';
> > $versiononly = 0 if $ARGV[0] eq '+v';
> >
> > ...
> >
> > so I wondered how Getopt::Long copes with options starting with +
> > From skimming the man page and the code it seems that it can, if you
> > set getopt_compat. However, it seems that there is no way of it
> > reporting back whether one used a + or a - option.
>
> Yes, that is right (although support for this is planned).
>
> Currently, you can do it with a bit of extra work:

Ah right. I don't think that there's any pressing need to refactor installperl

(it was more a means to an end - to get some of the ancillary code in
installperl and installman identical before merging it and reverting some
decade-old cut&paste)

So I wonder if the best bet for now is to rejig installperl to keep its hand
rolled argument parsing code, but make it write to %opts, so that in future
once Getopt::Long gets the planned support, we can re-write directly without
needing the "extra work" code, and hence do the job properly and do the job
once. (and avoid makework and churn)

Nicholas Clark


tchrist at perl

May 18, 2008, 9:41 PM

Post #4 of 22 (321 views)
Permalink
Re: Getopt::Long, + options, installperl, +v [In reply to]

On "Sun, 18 May 2008 19:40:12 BST."
Nicholas Clark <nick[at]ccl4.org> wrote
in <20080518184012.GJ6780[at]plum.flirble.org>:

> So I was taking a look at the TODO

> =head2 merge common code in installperl and installman

> There are some common subroutines and a common C<BEGIN> block
> in F<installperl> and F<installman>. These should probably be
> merged. It would also be good to check for duplication in all
> the utility scripts supplied in the source tarball. It might be
> good to move them all to a subdirectory, but this would require
> careful checking to find all places that call them, and change
> those correctly.

> =cut

> and I noticed that one of the differences between the two is
> that installperl has variables $nonono and $verbose, whereas
> installman has $opts{notify} and $opts{verbose}. This is
> because installman uses Getopt::Long, whereas installperl has
> hand-rolled argument parsing.

When I read that, I was suddenly stricken with some vague but completely
unjustifiable suspicion of distant personal responsibility. Happily, I
confirmed that it was phantom déjà vu. I figure it's because I just now
looked inside two programs I use daily, once I was just looking over today,
too. The one uses the old-style, home-rolled parser, including with the
very variables you mention, $nonono and $verbose. That's what scared me.

The hand-rolled parser with the same variable names occurs in that old
rename/relink program of Larry's that I rewrote to process options and be
in general more robust and faster.

The other culprit, tcgrep, being the more "modern" program, uses a %opts
hash and Getopt::Std. But it really should have used Getopt::Long instead,
because it became quite complicated, and so I ended up once again redoing a
bunch of stuff which Johan had long ago done so much better. If you have
tcgrep, look at its gross parse_args() function. It's no simple matter of

# core of tcgrep's opt parser
$optstring = "incCwsxvhe:f:l1HurtpP:aqTF";
getopts($optstring, \%opt) || usage();

but rather, has more auxiliary logic in it. A *lot* more. Should
have used Getopt::Long, no question about it. Oh well.

> So, I wondered whether installperl should be dragged into the
> century of the fruitbat and converted to Getopt::Long.

How about thinking of it as being dragged into the new millennium some 7
years late, or now into the 3rd decade of Perl's existence? I think you'll
be happy you did. I *really* like Getopt::Long, and the work that Johan's
done with it in so brilliant I cannot say enough good things about it to do
it the justice it deserves.

The only problem is that I just don't use it enough. I bet I'm not alone.
What seems to happen is that at first we just want to add--oh say for
example JUST ONE, SINGLE LITTLE -v flag. Well, that's so easy enough to
hand-hack, that of course we do so; maybe like this:

if (@ARGV && $ARGV[0] eq '-v') {
$verbose = 1;
shift @ARGV;
}

or maybe we do something a tad fancier.

But even so, it's still a slip, slip, slippery slope. I remember how
Larry'd always roll his own quick, simple ones. I'd ask him why not use
the library, and he said it didn't seem worth the bother to load it in for
just an opt or two. IIRC, he's written a lot of hand-rolled opt parsers
like I'm about to demo below, and in that peculiar style, too.

But just like any other piece of software, these things all seem to have a
way of overgrowing their original expectations. It's like writing "just a
simple" shell script: you don't foresee that it's going to grow beyond the
tools ability to get the job done, or beyond your own patience for working
around the beast you've begotten, kicking yourself you didn't do it the
"right way" all the way from the get-go. At least, that's what happens to
me all the time with option handling.

A quick inspection of two different semi-substantial corpora of perl code
shows that (1) I'm not alone in this kick-myself underestimation of what it
would need, (2) more often resorting to hand-rolling than to Getopt:Std,
and (3) more apt to use Getopt:Std than to use Getopt::Long.

But Getopt::Long is just *wonderful*, up--I believe--to any job you can
come up with for it. Too often its absence means that I've in the long run
made more work for myself--or others--by not having used it originally.
Even in the rare case that what you want *isn't* there, I'd bet you a
finely Belgian Trappist Ale of arbitrary size that Johan'd put your
functionality in there for you right away in a jiffy.

Observe two metrics, first on my own scripts:

% ls -l ~/scripts | wc -l
769

% tcgrep -lq '(while.*ARGV.*=~|ARGV.*eq)' ~/scripts | wc -l
59
% tcgrep -lq 'Getopt::Std' ~/scripts | wc -l
17
% tcgrep -lq 'Getopt::Long' ~/scripts | wc -l
12

and then on the Perl Power Tools programs, some by me but most
by other people:

% ls ppt-0.14/bin | wc -l
116

% tcgrep -lq '(while.*ARGV.*=~|ARGV.*eq)' ppt-0.14/bin | wc -l
39
% tcgrep -lq 'Getopt::Std' ppt-0.14/bin | wc -l
38
% tcgrep -lq 'Getopt::Long' ppt-0.14/bin | wc -l
5

See the trend? Alas, it's more of the same, and perhaps even more
egregious than in my own stuff, which is really atrocious (we won't
ask Larry to check his though :-).

But Nick, just because you have yourself a hand-rolled parser, and may even
want to keep it, by no means demands that it must be ugly, that it can't
look elegant and (gasp) legible! :-)

Contrast installperl's version: (BTW, fails on destdirs w/newlines in them,
but those are so evil, they deserve to suffer--I think.)

while (@ARGV) {
$nonono = 1 if $ARGV[0] eq '-n';
$dostrip = 1 if $ARGV[0] eq '-s';
$versiononly = 1 if $ARGV[0] eq '-v';
$versiononly = 0 if $ARGV[0] eq '+v';
$silent = 1 if $ARGV[0] eq '-S';
$otherperls = 0 if $ARGV[0] eq '-o';
$force = 1 if $ARGV[0] eq '-f';
$verbose = 1 if $ARGV[0] eq '-V' || $ARGV [0] eq '-n';
$archname = 1 if $ARGV[0] eq '-A';
$nwinstall = 1 if $ARGV[0] eq '-netware';
$nopods = 1 if $ARGV[0] eq '-p';
$destdir = $1 if $ARGV[0] =~ /^-?-destdir=(.*)$/;
if ($ARGV[0] eq '-?' or $ARGV[0] =~ /^-?-h/) {
print <<"EOT";
Usage $0: [switches]
-n Don't actually run any commands; just print them.
-s Run strip on installed binaries.
-v Only install perl as a binary with the version number in the name.
(Override whatever config.sh says)
[ETC]

with my own hand-rolled but highly stylized (=funny-looking) critter
out of the the dark ages for the rename/relink program (where you
can see the similar things line up in the same column from one line to
the next so you can quickly see what's different):

sub opter {

ARG: while (@ARGV && $ARGV[0] =~ s/^-(?=.)//) {
OPT: for (shift @ARGV) {

m/^$/ && do { next ARG; };
m/^-$/ && do { last ARG; };

s/^0// && do { $nullpaths++; redo OPT; };
s/^f// && do { $force++; redo OPT; };
s/^l// && do { $reslinking++; redo OPT; };
s/^I// && do { $inspect++; redo OPT; };
s/^i// && do { $careful++; redo OPT; };
s/^v// && do { $verbose++; redo OPT; };
s/^V// && do { $verbose += 2; redo OPT; }; # like two -v's
s/^m// && do { $renaming++; redo OPT; };
s/^n// && do { $nonono++; redo OPT; };
s/^N// && do { $nonono += 2; redo OPT; }; # like two -n's
s/^q// && do { $quiet++; redo OPT; };

s/^F(.*)//s && do { push @flist, $1 || shift @ARGV; redo OPT; };

usage("Unknown option: $_");
}
}
unless ($renaming || $reslinking) {
$renaming = $0 =~ /name/;
$reslinking = $0 =~ /link/;
}
if ($renaming && $reslinking) {
usage "Can't both rename (-r) and relink (-h)";
}
unless ($renaming || $reslinking) {
warn "$0: assuming renaming behavior requested\n";
$renaming++;
}
$verbose += $nonono if $nonono;

if ($inspect) {
accesstty() || usage "can't inspect without /dev/tty: $!";
}

# pretend this was stubbed earlier as sub usage;
sub usage {
warn "@_\n" if @_;
die <<EOF;
usage: $0 [-ifqI0vnml] [-F file] perlexpr [files]
-i ask about clobbering existent files
-f force clobbers without inquiring
-q quietly skip clobbers without inquiring
-I ask about all changes
-0 read null-terminated filenames
-v verbosely says what it's doing
-V verbosely says what it's doing but with newlines between old and new filenames
-n don't really do it
-m to always rename
-l to always symlink
-F path read filelist to change from magic path(s)
EOF
}

Come on, you at least gotta admit it's a wee bit cute there at the
beginning with the hanging-regexp looking switch() emulation, even if I
am bit of a vertical-alignment freak^Waficionado. :-) I even compressed
this for your screen compared with the real program.

But then I in turn gotta admit *I* should've used Getopt::Long all along. :-(

I wouldn't do what I did, Nick, if I'd the whole thing thing to do over.
I'd just thank Johan and use his code. I don't think you'll be sorry
if you do.

--tom

PS: Full program enclosed, as I think far fewer people have this really
rather cool (if I do say so myself) version of rename than who have
my tcgrep. You'll see what I mean by cool stuff quite readily
if you look it over. And anyway, it's only 4 lines of code :-)

opter();
compiler();
fixer();
exit($errcnt != 0);

Have the appropriate amount of fun!

BTW, I think you fixed the XXX problem it mentions. Thanks!!!

#!/usr/bin/perl
# pathedit/rename/relink -- rename or relink files
# original rename and relink were by Larry Wall
# this version by Tom Christiansen

use strict;
use warnings;

our(
$errcnt, # how many didn't work
$verbose, # trace actions
$nonono, # but don't do them (implies verbose)
$careful, # ask if target *appears* to exist
$inspect, # ask about everything
$quiet, # don't carp if target skipped
$force, # overwrite existing target without prompting
$nullpaths, # stdin paths are null terminated, not \n
@flist, # list of magic filenames containing paths to edit
$renaming, # rename paths (disimplies reslinker)
$reslinking,# reslink paths (disimplies renamer)
);

$errcnt = 0;

opter();
compiler();
fixer();
exit($errcnt != 0);

sub usage {
warn "@_\n" if @_;
die <<EOF;
usage: $0 [-ifqI0vnml] [-F file] perlexpr [files]
-i ask about clobbering existent files
-f force clobbers without inquiring
-q quietly skip clobbers without inquiring
-I ask about all changes
-0 read null-terminated filenames
-v verbosely say what it's doing
-V verbosely say what it's doing but with newlines between old and new filenames
-n don't really do it
-m to always rename
-l to always symlink
-F path read filelist to change from magic path(s)
EOF
}

sub accesstty {
return 1 if defined fileno(TTYIN) &&
defined fileno(TTYOUT);

unless (open(TTYIN, "</dev/tty") && open(TTYOUT,">/dev/tty")) {
return 0;
}

select((select(TTYOUT),$|=1)[0]);
return 1;
}

sub compiler {
my $op = shift @ARGV || usage();
*pathedit = eval qq{
sub () {
use warnings qw/FATAL all/; # XXX: does not work
local \$SIG{__WARN__} = sub {
local \$_ = "\@_";
s/at \\(eval.*//;
die "FATAL WARNING: \$_";
};
$op;
}
} || do {
local $_ = $@;
s/at \(eval.*//s;
die "$0: can't compile perlexpr $op: $_\n";
}
}

sub get_targets {
if (@ARGV) {
usage "-F list exclusive of command line paths" if @flist;
return @ARGV;
}
@ARGV = @flist ? @flist : "-";
local $/ = "\0" if $nullpaths;
my @paths = <>;
chomp @paths;
return @paths;
}

sub fixer {
my $oldslink;

PATHNAME:
for my $oldname (get_targets()) {

if ($oldname =~ /\0/) {
warn "$0: null found in $oldname; did you forget -0?\n";
$errcnt++;
next PATHNAME;
}
if ($renaming && !-e $oldname) {
warn "$0: $oldname doesn't exist\n";
$errcnt++;
next PATHNAME;
}

if ($reslinking) {
unless (-l $oldname) {
warn "$0: $oldname ", (-e _)
? "not a symbolic link\n"
: "doesn't exist\n"
unless $quiet;
$errcnt++;
next PATHNAME;
}
$oldname = readlink($oldslink = $oldname);
}
my $newname = do {
local $_ = $oldname;
pathedit();
$_;
};
next if $newname eq $oldname;

local *confirm = sub () {
next PATHNAME unless accesstty();
print TTYOUT $renaming
? "rename $oldname to $newname? "
: "symlink $oldslink to point to $newname? ";
my $answer = <TTYIN>;
no warnings "exiting";
last PATHNAME unless defined $answer; # exit?
chomp $answer;
last PATHNAME if "QUIT" =~ /^\Q$answer/i;
next PATHNAME unless "YES" =~ /^\Q$answer/i;
};

confirm() if $inspect;

# "I'd like to teach
# The world to race
# In perfect hackery!"
my $was_there = do {
no warnings "newline";
-e $newname;
};

if ($renaming) {

if ($was_there && !$inspect && $careful) {
confirm() unless $force || $quiet;
next PATHNAME if $quiet;
}

unless (vrename($oldname, $newname)) {
warn "$0: can't rename $oldname to $newname: $!\n";
$errcnt++;
next PATHNAME;
}

}
elsif ($reslinking) {
unless ($was_there) {
warn "$0: symlinking $oldslink to nonexistent $newname\n"
unless $quiet;
}
unless (vunlink($oldslink)) {
warn "$0: can't unlink $oldslink: $!\n";
$errcnt++;
next PATHNAME;
}
if (!vsymlink($newname, $oldslink)) {
warn "$0: can't symlink $newname to $oldslink: $!\n";
$errcnt++;
next PATHNAME;
}
}
else {
die "Not reached";
}

}

}

sub vunlink {
my $goner = shift;
if ($verbose) {
print "unlink $goner\n";
return 1 if $nonono;
}
unlink $goner;
}

sub vrename {
my ($old,$new) = @_;
if ($verbose) {
if ($verbose > 1) {
print "renaming $old\n to $new\n";
} else {
print "rename $old $new\n";
}
return 1 if $nonono;
}
rename($old,$new);
}

sub vsymlink {
my ($new,$old) = @_;
if ($verbose) {
if ($verbose > 1) {
print "symlinking $old\n to $new\n";
} else {
print "symlink $old $new\n";
}
return 1 if $nonono;
}
symlink($new,$old);
}

sub opter {

ARG: while (@ARGV && $ARGV[0] =~ s/^-(?=.)//) {
OPT: for (shift @ARGV) {

m/^$/ && do { next ARG; };
m/^-$/ && do { last ARG; };

s/^0// && do { $nullpaths++; redo OPT; };
s/^f// && do { $force++; redo OPT; };
s/^l// && do { $reslinking++; redo OPT; };
s/^I// && do { $inspect++; redo OPT; };
s/^i// && do { $careful++; redo OPT; };
s/^v// && do { $verbose++; redo OPT; };
s/^V// && do { $verbose += 2; redo OPT; }; # like two -v's
s/^m// && do { $renaming++; redo OPT; };
s/^n// && do { $nonono++; redo OPT; };
s/^N// && do { $nonono += 2; redo OPT; }; # like two -n's
s/^q// && do { $quiet++; redo OPT; };

s/^F(.*)//s && do { push @flist, $1 || shift @ARGV; redo OPT; };

usage("Unknown option: $_");
}
}
unless ($renaming || $reslinking) {
$renaming = $0 =~ /name/;
$reslinking = $0 =~ /link/;
}
if ($renaming && $reslinking) {
usage "Can't both rename (-r) and relink (-h)";
}
unless ($renaming || $reslinking) {
warn "$0: assuming renaming behavior requested\n";
$renaming++;
}
$verbose += $nonono if $nonono;

if ($inspect) {
accesstty() || usage "can't inspect without /dev/tty: $!";
}

}


demerphq at gmail

May 19, 2008, 1:18 AM

Post #5 of 22 (318 views)
Permalink
Re: Getopt::Long, + options, installperl, +v [In reply to]

2008/5/18 Nicholas Clark <nick[at]ccl4.org>:
> so I wondered how Getopt::Long copes with options starting with +
> From skimming the man page and the code it seems that it can, if you set
> getopt_compat. However, it seems that there is no way of it reporting back
> whether one used a + or a - option.
>
> So
>
> 1: is this correct?
>
> 2: if this is correct, should we find a new name for +v, and deprecate the
> old name? (and after the deprecation cycle completes, refactor to use
> Getopt::Long?)

Maybe add a new flag using long argument style and just do a map on
@ARGV before you call into Getopt::Long.

@ARGV= map { $_ eq "+v" ? "--no-version-only" : "" } @ARGV;

Judging by the original code you dont have to worry about bundled
switches so this should suffice.

Cheers,
yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"


demerphq at gmail

May 19, 2008, 1:18 AM

Post #6 of 22 (316 views)
Permalink
Re: Getopt::Long, + options, installperl, +v [In reply to]

2008/5/19 demerphq <demerphq[at]gmail.com>:
> 2008/5/18 Nicholas Clark <nick[at]ccl4.org>:
>> so I wondered how Getopt::Long copes with options starting with +
>> From skimming the man page and the code it seems that it can, if you set
>> getopt_compat. However, it seems that there is no way of it reporting back
>> whether one used a + or a - option.
>>
>> So
>>
>> 1: is this correct?
>>
>> 2: if this is correct, should we find a new name for +v, and deprecate the
>> old name? (and after the deprecation cycle completes, refactor to use
>> Getopt::Long?)
>
> Maybe add a new flag using long argument style and just do a map on
> @ARGV before you call into Getopt::Long.
>
> @ARGV= map { $_ eq "+v" ? "--no-version-only" : "" } @ARGV;

Urk.

@ARGV= map { $_ eq "+v" ? "--no-version-only" : $_ } @ARGV;



--
perl -Mre=debug -e "/just|another|perl|hacker/"


sthoenna at efn

May 19, 2008, 1:50 AM

Post #7 of 22 (316 views)
Permalink
Re: Getopt::Long, + options, installperl, +v [In reply to]

On Mon, May 19, 2008 1:18 am, demerphq wrote:
> @ARGV= map { $_ eq "+v" ? "--no-version-only" : $_ } @ARGV;

s/^\+v\z/--no-version-only/for[at]ARGV;


demerphq at gmail

May 19, 2008, 1:54 AM

Post #8 of 22 (316 views)
Permalink
Re: Getopt::Long, + options, installperl, +v [In reply to]

2008/5/19 Yitzchak Scott-Thoennes <sthoenna[at]efn.org>:
> On Mon, May 19, 2008 1:18 am, demerphq wrote:
>> @ARGV= map { $_ eq "+v" ? "--no-version-only" : $_ } @ARGV;
>
> s/^\+v\z/--no-version-only/for[at]ARGV;
>

Swish! :-)



--
perl -Mre=debug -e "/just|another|perl|hacker/"


nick at ccl4

May 19, 2008, 2:03 AM

Post #9 of 22 (318 views)
Permalink
Re: Getopt::Long, + options, installperl, +v [In reply to]

On Sun, May 18, 2008 at 10:41:03PM -0600, Tom Christiansen wrote:

> Even in the rare case that what you want *isn't* there, I'd bet you a
> finely Belgian Trappist Ale of arbitrary size that Johan'd put your
> functionality in there for you right away in a jiffy.

"arbitrary sized Belgian Trappist Ale" - that's s *scary* concept. :-)
At least with small, finite sized ales I can count them, and when I lose
count I know I should have stopped (probably some time ago)

> But then I in turn gotta admit *I* should've used Getopt::Long all along. :-(
>
> I wouldn't do what I did, Nick, if I'd the whole thing thing to do over.
> I'd just thank Johan and use his code. I don't think you'll be sorry
> if you do.

I guess that there is one problem you may have had with using Getopt::Long all
along - I'd guess that some of your code predates it.

Nicholas Clark


pagaltzis at gmx

May 19, 2008, 2:53 AM

Post #10 of 22 (316 views)
Permalink
Re: Getopt::Long, + options, installperl, +v [In reply to]

* demerphq <demerphq[at]gmail.com> [2008-05-19 10:20]:
> Maybe add a new flag using long argument style and just do a
> map on @ARGV before you call into Getopt::Long.
>
> @ARGV= map { $_ eq "+v" ? "--no-version-only" : "" } @ARGV;
>
> Judging by the original code you dont have to worry about
> bundled switches so this should suffice.

Bundling is not the only problem: switches with mandatory
arguments will also trip you up as they change the interpretation
of whatever follows the switch.

Regards,
--
Aristotle Pagaltzis // <http://plasmasturm.org/>


jvromans at squirrel

May 19, 2008, 3:01 AM

Post #11 of 22 (316 views)
Permalink
Re: Getopt::Long, + options, installperl, +v [In reply to]

[Quoting Aristotle Pagaltzis, on May 19 2008, 11:53, in "Re: Getopt::Long, + "]
> Bundling is not the only problem: switches with mandatory
> arguments will also trip you up as they change the interpretation
> of whatever follows the switch.

That's why I suggested the slightly more elaborate solution where
Getopt::Long handles all parsing.

-- Johan


demerphq at gmail

May 19, 2008, 3:07 AM

Post #12 of 22 (318 views)
Permalink
Re: Getopt::Long, + options, installperl, +v [In reply to]

2008/5/19 Aristotle Pagaltzis <pagaltzis[at]gmx.de>:
> * demerphq <demerphq[at]gmail.com> [2008-05-19 10:20]:
>> Maybe add a new flag using long argument style and just do a
>> map on @ARGV before you call into Getopt::Long.
>>
>> @ARGV= map { $_ eq "+v" ? "--no-version-only" : "" } @ARGV;
>>
>> Judging by the original code you dont have to worry about
>> bundled switches so this should suffice.
>
> Bundling is not the only problem: switches with mandatory
> arguments will also trip you up as they change the interpretation
> of whatever follows the switch.

could this be a place where perfect is the enemy of good enough?


--
perl -Mre=debug -e "/just|another|perl|hacker/"


pagaltzis at gmx

May 19, 2008, 3:08 AM

Post #13 of 22 (318 views)
Permalink
Re: Getopt::Long, + options, installperl, +v [In reply to]

* Nicholas Clark <nick[at]ccl4.org> [2008-05-18 21:25]:
> So I wonder if the best bet for now is to rejig installperl to
> keep its hand rolled argument parsing code, but make it write
> to %opts, so that in future once Getopt::Long gets the planned
> support, we can re-write directly without needing the "extra
> work" code, and hence do the job properly and do the job once.
> (and avoid makework and churn)

If Johan already knows the API syntax that is going to be used
when this feature is available, you can already do the work now.
Just make a compat wrapper that translates back to the current
syntax; something like this:

sub GetOptions { # forward-compat wrapper for plus-prefixed options
my %plus_opt;
my @opt_spec;
while ( my ( $k, $v ) = splice @_, 0, 2 ) {
if ( $k eq '+v' ) { $plus_opt{$k} = $v }
else { push @opt_spec, $k, $v }
}

my @saved_arg;
my $ret = Getopt::Long::GetOptions(
'<>' => sub {
my ( $arg ) = @_;
$plus_opt{$arg}
? $plus_opt{$arg}->()
: push @saved_arg, $arg;
},
@opt_spec,
);

push @saved_arg, '--' if @saved_arg and @ARGV;

splice @ARGV, 0, 0, @saved_arg;

return $ret;
}

Then, assuming '+v' is the syntax that Johan plans to implement,
you just write the code using the new-style API, and whenever the
feature is implemented in Getopt::Long you merely kick out the
wrapper and everything continues to work.

Regards,
--
Aristotle Pagaltzis // <http://plasmasturm.org/>


nick at ccl4

May 19, 2008, 3:09 AM

Post #14 of 22 (316 views)
Permalink
Re: Getopt::Long, + options, installperl, +v [In reply to]

On Mon, May 19, 2008 at 12:07:43PM +0200, demerphq wrote:

> could this be a place where perfect is the enemy of good enough?

Yes. That's why I already decided to avoid any change to the argument parsing
until Getopt::Long supports a way of telling if one used -v or +v :-)

(oh, and committed that bit, and moved on)

Nicholas Clark


pagaltzis at gmx

May 19, 2008, 3:12 AM

Post #15 of 22 (316 views)
Permalink
Re: Getopt::Long, + options, installperl, +v [In reply to]

* demerphq <demerphq[at]gmail.com> [2008-05-19 12:10]:
> 2008/5/19 Aristotle Pagaltzis <pagaltzis[at]gmx.de>:
> > Bundling is not the only problem: switches with mandatory
> > arguments will also trip you up as they change the
> > interpretation of whatever follows the switch.
>
> could this be a place where perfect is the enemy of good
> enough?

It depends on what the code does. If there are no switches with
mandatory arguments then the point is moot. I am just pointing
that out.

Regards,
--
Aristotle Pagaltzis // <http://plasmasturm.org/>


jvromans at squirrel

May 19, 2008, 3:46 AM

Post #16 of 22 (318 views)
Permalink
Re: Getopt::Long, + options, installperl, +v [In reply to]

[Quoting Aristotle Pagaltzis, on May 19 2008, 12:08, in "Re: Getopt::Long, + "]
> If Johan already knows the API syntax that is going to be used
> when this feature is available, you can already do the work now.

As of 2.37, the GetOptions callback handlers are called with an object
as first arg, instead of a string (the name of the option). The object
stringifies to the name of the option for compatibility.

It is my idea to provide methods for this callback object to query
(and modify) some G::L internals in a well defined and well-behaving
manner.

Currently, the callback object has one method, 'name'. Everything else
is undocumented and experimental.

Given the +v / -v problem, I'd add an method 'prefix' that provides the
actual prefix used. Normally, that would be one of '-', '--' or '+'
depending on the config options.


> while ( my ( $k, $v ) = splice @_, 0, 2 ) {
> if ( $k eq '+v' ) { $plus_opt{$k} = $v }

E.g., $plus_opt{'+v'} = \$versiononly .

> '<>' => sub {
> my ( $arg ) = @_;
> $plus_opt{$arg}
> ? $plus_opt{$arg}->()

Deref a scalar ref with ->() ?

-- Johan


pagaltzis at gmx

May 19, 2008, 4:29 AM

Post #17 of 22 (318 views)
Permalink
Re: Getopt::Long, + options, installperl, +v [In reply to]

* Johan Vromans <jvromans[at]squirrel.nl> [2008-05-19 12:50]:
> [Quoting Aristotle Pagaltzis, on May 19 2008, 12:08, in "Re: Getopt::Long, + "]
> > while ( my ( $k, $v ) = splice @_, 0, 2 ) {
> > if ( $k eq '+v' ) { $plus_opt{$k} = $v }
>
> E.g., $plus_opt{'+v'} = \$versiononly .
>
> > '<>' => sub {
> > my ( $arg ) = @_;
> > $plus_opt{$arg}
> > ? $plus_opt{$arg}->()
>
> Deref a scalar ref with ->() ?

No, the intent of that code was merely to accept coderefs for
plus-prefixed options. The compat wrapper wouldn’t have to
provide the full new API syntax, after all, just the bits that
are used in the script, and I assumed that `+v` would be parsed
by invoking a coderef for the purposes of this script, so that’s
all I support in the example wrapper.

The point is that the code should be written against the future
API, and then made to work using a wrapper that translates to
current API. For that purpose it’s a waste of effort to make the
compat wrapper support more of the future API than locally used.

But the point is moot, since you are not just adding syntax –
the future API will provide this capability through a completely
aspect which cannot be emulated so easily. So writing a compat
wrapper would be too hard in this case, and Nick’s going ahead
with a more minimal solution turned out to be just as well.

Nothing to see here, move along.

Regards,
--
Aristotle Pagaltzis // <http://plasmasturm.org/>


tchrist at perl

May 19, 2008, 4:11 PM

Post #18 of 22 (311 views)
Permalink
Re: Getopt::Long, + options, installperl, +v [In reply to]

In his epistle <20080519090347.GO6780[at]plum.flirble.org>, Nicholas Clark
wrote on Primidi, Prairial 1°, day 241 of the year CCXVI at 4:19:29:

>On Sun, May 18, 2008 at 10:41:03PM -0600, Tom Christiansen wrote:

>> Even in the rare case that what you want *isn't* there, I'd bet you a
>> finely Belgian Trappist Ale of arbitrary size that Johan'd put your
>> functionality in there for you right away in a jiffy.

> "arbitrary sized Belgian Trappist Ale" - that's s *scary* concept. :-)
> At least with small, finite sized ales I can count them, and when I lose
> count I know I should have stopped (probably some time ago)

Hey, just blame it on the grande and glorieuse Révolution française with
their système métrique! :-) Voilà how well it all worked out for the
second line of the current message!

Or ask Lavoisier. :-(

But I do *so* love metric time, too; don't you? It would give the world
economy a *huge* boost if we were to all convert now. Plus I'd no longer
be obliged to boringly preface my missives with the likes of

At 10:03:47 2008-05-19, Nick Clark wrote:

Or, dying of boredom, seek to go embellishing the Dickens (:-) out of it
until it's as bello (NOT bellic!) as anyone could imagine (and few'd dare):

On Monday at 10:03:47am BST [+0100], the 19th of May in anno
domini 2008, one Mister Nicholas Clarke, Esq. has done us all
the fine honour of having seen fit to graciously write:

Well, ok, fine; maybe not quite *that* much. :-)

But gosh, it's the prémier day of Prairial, and that's so cool. That's
just a saying, you know, the cool part. We're expecting 92° tomorrow!
and I grant you that if it felt much more like Germinal 'round these parts
a few days ago, not even yet Floréal.

But we just don't *have* spring here in Colorado.

Instead, we have these radical oscillations between winter and summer of
semi-random but ever-lengthening periodicity, ever back and forth again
between them, and across both halves of the year. Starting only
gradually with sudden fits and starts, and even more sudden setbacks,
summer *eventually* wins this climatic tug of war, though at times
not till nigh unto Midsummers Day itself.

But only for a time, and with no guarantee of its continued abeyance.
Which means I'm not quite foolhearty enough to put my tomatoes out yet.
:-) But in return, summer sometimes pays winter surprise visits here,
too. You just never know. The Old Norse were right: there really are
but two seasons, at these given appropriate latitudes and/or altitudes.

Let's get back to talking ale. Tell me, who can *really* know what all
those silly Belgian measures add up when you can no longer nor count?

Easier just to deal with halves and doubles.

For example, if your alestein is half-full, or even half-empty on a
ones-complement system, why, now you've just gone and pinted your quart!
And if the barmaid of the establishment doesn't immediately upon seeing
your sad and halvsied condition quickly top you off entirely unsupplicated
and irremunerated, you're just not gettin' your quids' worth, and thus
should frequent another public house; or perhaps even a private one :-)

Plus who wants to use a vigesimal counting system, and why? "Et alor,
that'll be only quatre-vingts dix-neuf today, M'sieur!" At least
you'd be in Belgium where they have their nonantes. That way you
wouldn't have to take your shoes off to count. :-)

But *you* still have vigesimal pints, don't you now? At least now I'm
told that "THEY"'re at long last relenting on pushing *their* cultural
imperialism enough to let you folks keep your/our units.

Well, not quite ours. Our liquid measures always nicely halve or
double, being completely binary, making an *American* gallon of ale not
one grain shy of the rather enticing- looking kilodram (2**10 drams),
you know--or, if the non-hackers get their way again, I suppose a
kibidram, but that sounds too much like a Kibo-gram to me.

I still think base-10 just plain sucks for some kind of things.
Gimme a duodecimal system any [12-hour] day. :-) Better yet, gimme
a sexy sexagesimal system any [60-minute] hour or [60-second] minute,
and cry Fie! on metric time.

That way the shopkeeps can C<use integer> when making change: "That'll
be two to the pound, ma'am." Or three. Or four. Or six. Or an even
dozen. Why, just *look* at all those nice factors in 12 and 60! Makes
your head go in circles, doesn't it now? And I'm not talking radians:
Babylon shall be with us always.

And look, I didn't even have to tell you whether the tomatoes weighed
in at 3 to a pound, or whether that was the price the greengrocer was
asking for them. Or both. How very perlish!

>> But then I in turn gotta admit *I* should've used Getopt::Long
>> all along. :-( I wouldn't do what I did, Nick, if I'd the
>> whole thing thing to do over. I'd just thank Johan and use his
>> code. I don't think you'll be sorry if you do.

> I guess that there is one problem you may have had with using
> Getopt::Long all along - I'd guess that some of your code
> predates it.

Most of my code is prey, not predator. :-(

Heck, I've got scripts that antedate Perl itself. And this isn't even most
of them from university, which are stuck on 9-track tapes nobody any longer
has hardware readers for.

% ls -lrt ~/scripts/
total 4592
-rwxr-x--- 1 tchrist 100 431 Jun 2 1987 getwin
-rwxr-xr-x 1 tchrist users 214 Jan 20 1989 systail
-rwxr-x--- 1 tchrist 100 483 Jul 24 1989 mergef
-rwxr-x--- 1 tchrist 100 491 Aug 6 1989 redist
-rwxr-xr-x 1 tchrist users 5499 Jul 28 1991 h2ph
-rwxr----- 1 tchrist users 20610 Feb 23 1993 user
-rw-r--r-- 1 tchrist 100 321 Apr 29 1993 tip
-rw-r--r-- 1 tchrist users 337 Jan 11 1994 vi
-rwxr-xr-x 1 tchrist 100 604 May 4 1994 ah
-rwxr-xr-x 1 tchrist 500 1384 Feb 1 1996 Who
-rw-r--r-- 1 tchrist 500 818 Feb 1 1996 W.oneill
[...]

The eldest of those, getwin, reads:

#!/bin/csh -f
if( "$1" =~ *:* ) setenv DISPLAY "$1"

foreach x ( `xwininfo -root -children | sed -ne '/Child/s/^.*: //p'` )
xwininfo -id $x | awk \
'BEGIN { ismapped = 0 } \
/Window name/ { temp = "" ; for(i = 5; i <= NF; i++) \
temp = temp $i ; \
winname = substr(temp, 2, length(temp)-2) } \
/IsMapped/ { ismapped++; } \
/Upper.*=.*x/ { outgeo = $4 ; } \
END { if(ismapped > 0) print winname " " outgeo }'
end

See what I mean about most of my code falling more into the prey set
than the predator one? :-) And aren't you all glad Perl showed up?
Otherwise, who *knows* what dark monsters I'd've brought to light by
now but for that one, happy event?

Even in Perl, memory is long. Think back to those pre-pod days when things
started with:

#!/usr/local/bin/perl
'di';
'ig00';

Or when we'd blithely write code like:

$cols = ($ENV{"TERMCAP"} =~ /:co#(\d+):/) ? $1 : 80;
$PIPE= "who |";
open(PIPE) || die "$0: can't open $PIPE: $!\n";

That still works, you know, so kindly don't break it. :-) While some of
those scripts there at the start of the list are "truly" ancient, almost
all still run just fine. Well, or (often?) appear to.

See any wee problem here?

$now = time;
$DELTA = 2*60*60;
@mo = (Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec);
open(UTMP,'/etc/utmp') || die "can't open utmp: $!";
chdir '/dev' || die "can't cd to /dev: $!";
open(TTYS, "/etc/ttys") || die "can't open /etc/ttys: $!";

Then again, if you miss that you can't cd to "/dev," I imagine you'll land
in hotter water later. :-) Reminds me of the great 1984 paper entitled

Can't Happen
or
/* NOTREACHED */
or
Real Programs Dump Core

in which the authors present the initially (ahem) intriguing question:

In what program do we find the following code sequence:

open("/", 0);
dup(0);
dup(0);


--[tchrist here] Where you wait a minute, thinking and guessing,
before you're gabberflasted to learn that--


V7 init, alas. There are two other occurrences, in which the
opens are "open(tty, 2);" and "open(ctty, 2);". The author
*knew*, by god, that those system calls could *never* fail.
As a result, when the kernel file or inode tables fill, init
fails to re-populate some terminals with init children and
thus getty's. Thus those terminals will never inherit init's
until the next crash or reboot. We know: the file and inode
tables aren't supposed to fill, thus it **can't happen**.
A common counter-argument is that in such a case there is
nothing sensible to be done. Yet a moment's thought often
reveals a better alternative than failing to check. In this
case, since the code in question is running in a child of
init, init can sleep briefly and try again if a system call
such as dup() fails or if an open() fails due to resource
exhaustion.

See http://www.darwinsys.com/history/canthappen.html for details.

Before Perl, I used anything--and EVERYTHING--to get the job done.
Sometimes that meant using m4(1) as a system programming language;
sometimes it meant using sh(1). For examples of using troff(1) as a
systems programming language, though you'll have to hit up Larry,
as that one's his bailiwick.

I had lovely little shell scripts with pretty code like:

device=/dev/rmt8
dd_noise='^[0-9]+\+[0-9]+ records (in|out)$'
exec 3>&1
status=`((dd if=$device ibs=64k 2>&1 1>&3 3>&- 4>&-; echo $? >&4) | egrep -v "$dd_noise" 1>&2 3>&- 4>&-) 4>&1`
exit $status

Catch that one? All it wants to know whether the dd(1) failed. Is that
too much to ask? Apparently. Being the first stage of the pipeline, it
wouldn't have been propagated:

chthon(tchrist)% sh
$ true | false
$ echo $?
1
$ false | true
$ echo $?
0

I used to rdist out syslog.conf files to bunches of machines, with
extremely elaborate install-actions (ie, special "..." clauses) that
remotely executed scripts on the target client that I'd WRITTEN IN m4!
And not just the trivial "m4 distfile | rdist -f -", therefore.
The good news was that m4's external-command-execution abilities,
you can thus do anything. That, of course, was also the bad news,
for I did so . :-)

And of course, I used C. I calculate I cranked out over 100,000 of C
code even before I hit grad school. I don't use C becaues I don't know
it; rather, I don't use C because I *do*. :-)

POP QUIZ! Without consulting any other document and relying only upon
memory or deduction for your answer, write out in full the correct
type-signature declaration, complete with ANSI prototypes, for the standard
signal(3) function. You have just 30 seconds; start! I dare ya!!

See what I mean? :-(

Now sure, *you* can probably do it, Nick, and I know Larry could, too. But
who else? Very few, very few. I'd even be willing to bet that this
mailing list contains a statistically misrepresentative number of folks who
could, since most previous pumpkings probably can, and the *REALLY* good
Unix-C hackers, and just how many of *those* are there in the world?

But come on, it is *not* a trivial problem--and so too is the very fact
that it's not a trivial problem also a non-trivial problem, if you take
my meaning.

We all used C, but not out of love.

I remember an email exchange with Larry over an rn(1) patch I sent
him in this during this time at university in the mid 80s; again,
PREPERLESCENTLY, but I can't read the 9-track. :-(

Remember: the real code for Perl's "original" open2() function was
written by me more than TWO YEARS BEFORE perl's public debut. I
think I posted it on comp.unix.wizards or the comp.unix.programming
as an undergrad. It began like this:

/* process.c
*
* written by tom christiansen on Wed May 22 15:02:19 CDT 1985
* to open a socket pair and let the user read and write from
* both sides. return -1 on error, otherwise put the correct
* file pointers into *input and *output.
*
* CAVEAT UTILITOR:
* you will block forever if one of the sides of the
* pipes blocks because of too much in the buffer.
*/

See

<URL: http://groups.google.com/group/comp.lang.perl/browse_frm/thread/3dc0c9132e81ebbc/f63de423e278454b?hl=en&lnk=st>

for the rest of it, posted almost a decade later. It's probably *the* most
didactically-commented C code I've ever written--though not the most
dydact__ally-commented C code: I've never been a two-finger typist. :)

Gosh, now I feel *really* old.

BTW, for those few and intrepid souls who actually read all this from top
to bottom without standing on their heads, you guys have done an ABSOLUTELY
SMASHING-GOOD JOB with the 5.10 release. I'm stunned by how much very fine
and very hard work you've all done, an honest compliment and accolade that
I *never* give out in flattery, and am perhaps even too chary of awarding
when credit is justly due. And credit is here most certainly due: THANK YOU!

Sure, I've had some small troubles, but those were mostly with CPAN. For
one thing, lynx fetching the gz stuff into tmp$$ files fails constantly, so
I kept having to

% cd .cpan/sources/modules
% rename 's/\.tmp\d+$//' *

And in fact, even that's not enough: you must omit the $ to get them
all. And you have to *keep* doing this, over and over for those files
one by one, until you manage to get yourself boostrapped enough to use
something better.

The other major problem was that my default process limits were too
conservative for CPAN to be able to load up its datafiles without
running out of memory. What I had...

% limit
cputime unlimited
filesize unlimited
datasize 76800 kbytes
stacksize 4096 kbytes
coredumpsize 0 kbytes
memoryuse 111576 kbytes
descriptors 64
memorylocked 37621 kbytes
maxproc 128

...just didn't cut it. I kept getting out-of-memory errors from CPAN.pm
as it tried to load its huge dataset, and on more than one platform.

FINALLY, I realized it was a resource limit, not a real bug, and thus

% unlimit datasize
% unlimit stacksize
% unlimit memoryuse

sufficed to get me back into action.

Whew.

But that now reminds me of an old faux-errno (ferrno?) of mine...

--tom
--

"EMACS belongs in <sys/errno.h>: Editor too big!"
--tchrist


sthoenna at efn

May 19, 2008, 4:41 PM

Post #19 of 22 (310 views)
Permalink
Re: Getopt::Long, + options, installperl, +v [In reply to]

On Mon, May 19, 2008 4:11 pm, Tom Christiansen wrote:
> my default process limits were too
> conservative for CPAN to be able to load up its datafiles without running
> out of memory.

Insert mandatory CPAN::SQLite plug here.


rgarciasuarez at gmail

May 20, 2008, 12:40 AM

Post #20 of 22 (278 views)
Permalink
Re: Getopt::Long, + options, installperl, +v [In reply to]

2008/5/20 Tom Christiansen <tchrist[at]perl.com>:
> In his epistle <20080519090347.GO6780[at]plum.flirble.org>, Nicholas Clark
> wrote on Primidi, Prairial 1°, day 241 of the year CCXVI at 4:19:29:
[...]
> But gosh, it's the prémier day of Prairial, and that's so cool. That's
> just a saying, you know, the cool part. We're expecting 92° tomorrow!
> and I grant you that if it felt much more like Germinal 'round these parts
> a few days ago, not even yet Floréal.

(Sorry, but since you're lyric about the metric system, I felt compelled
to nitpick.)

92° ? That's a really hot temperature, in the centigrade temperature scale!


h.m.brand at xs4all

May 20, 2008, 12:45 AM

Post #21 of 22 (278 views)
Permalink
Re: Getopt::Long, + options, installperl, +v [In reply to]

On Mon, 19 May 2008 17:11:18 -0600, Tom Christiansen <tchrist[at]perl.com>
wrote:

> BTW, for those few and intrepid souls who actually read all this from top
> to bottom without standing on their heads, you guys have done an ABSOLUTELY
> SMASHING-GOOD JOB with the 5.10 release. I'm stunned by how much very fine
> and very hard work you've all done, an honest compliment and accolade that
> I *never* give out in flattery, and am perhaps even too chary of awarding
> when credit is justly due. And credit is here most certainly due: THANK YOU!

:)

That might be the next quote for the summarizer

Thank you too, you've done your part in the past. The work we now build
upon.

BTW, even if you got the signature for signal () correct, then *using*
it correct is far more than 30 seconds of reading through the system
manpages and include files, as when what is included and how might
depend on weather your compiler (thinks it) is in XPG4 and/or STDC
mode. Then there are old(er) compilers that won't accept argument
prototypes or ANSI signatures, but *do* enforce these through weird
macro definitions.

extern void (*signal (int, void (*)(int)))(int);

then becomes

extern void (*signal (int, void (*)()))();

Ahhhhrg!

--
H.Merijn Brand Amsterdam Perl Mongers (http://amsterdam.pm.org/)
using & porting perl 5.6.2, 5.8.x, 5.10.x on HP-UX 10.20, 11.00, 11.11,
& 11.23, SuSE 10.1 & 10.2, AIX 5.2, and Cygwin. http://qa.perl.org
http://mirrors.develooper.com/hpux/ http://www.test-smoke.org
http://www.goldmark.org/jeff/stupid-disclaimers/


tchrist at perl

May 20, 2008, 10:14 AM

Post #22 of 22 (271 views)
Permalink
Re: Getopt::Long, + options, installperl, +v [In reply to]

There's no Perl content here. Move right along now.
These are not the droids you are looking for.

In his epistle of "Tue, 20 May 2008 09:40:09 +0200."
<b77c1dce0805200040t2d8c8792q802bd010a45f56bd[at]mail.gmail.com>
d. Rafaël García-Suárez <rgarciasuarez[at]gmail.com>,
innocently plucking the coyly proffered fruit from where
it dangled so temptingly low, wrote:

> 2008/5/20 Tom Christiansen <tchrist[at]perl.com>:

>> In his epistle <20080519090347.GO6780[at]plum.flirble.org>, Nicholas
>> Clark wrote on Primidi, Prairial 1°, day 241 of the year CCXVI at
>> 4:19:29:

>>[...]

>> But gosh, it's the prémier day of Prairial, and that's so cool.
>> That's just a saying, you know, the cool part. We're expecting 92°
>> tomorrow! and I grant you that if it felt much more like Germinal
>> 'round these parts a few days ago, not even yet Floréal.

> (Sorry, but since you're lyric about the metric system, I felt
> compelled to nitpick.)

> 92° ? That's a really hot temperature, in the centigrade
> temperature scale!

Trust me, I did that one *totally* on purpose. I was teasing out the
nit-pickers with full awareness and intent, but not with malice.

There's a funny rule-of-thumb formula around here, and I believe it to
be sufficiently accurate for thumb-work. It's this: there's a loose
formula that says that water boils at 100° minus an extra degree per
every thousand feet above sea-level. I'm at about 5500', so my water
boils at close 94°.

> 2008/5/20 Tom Christiansen <tchrist[at]perl.com>:

>> In his epistle <20080519090347.GO6780[at]plum.flirble.org>, Nicholas
>> Clark wrote on Primidi, Prairial 1°, day 241 of the year CCXVI at
>> 4:19:29:

>>[...]

>> But gosh, it's the prémier day of Prairial, and that's so cool.
>> That's just a saying, you know, the cool part. We're expecting 92°
>> tomorrow! and I grant you that if it felt much more like Germinal
>> 'round these parts a few days ago, not even yet Floréal.

> (Sorry, but since you're lyric about the metric system, I felt
> compelled to nitpick.)

> 92° ? That's a really hot temperature, in the centigrade
> temperature scale!

Trust me, I did that one *totally* on purpose. I was teasing out the
nit-pickers with full awareness and intent, but not with malice.

There's a funny rule-of-thumb formula around here, and I believe it to
be sufficiently accurate for thumb-work. It's this: there's a loose
formula that says that water boils at 100° minus an extra degree per
every thousand feet above sea-level. I'm at about 5500', so my water
boils at close 94°.

Centigrade, that is.

Quite odd, really, if you think about it, the measurement mashup.

Another rule to remember is that to sterilize water, you boil it for a
minute, *plus* an extra minute for each 1,000 feet of elevation above
sea-level. In Leadville or Southpark, that means you better be
boiling for 11 long minutes. It's really hard to get hot coffee or
tea there. And all that "just add boiling water" "no-mess" backpacking
food? Hah! You have to boil the food itself, and for a good long
spell, too. It just doesn't boil hot enough 2 or 3 miles up for those
directions to do you any good at all.

I'm more comfortable thinking in centigrade than I probably am with
anything else in the metric system, but that's probably more because
I've lived in London and Madrid than for any other reason. Oh sure,
each and every one of my science classes I ever took though what, 19
years of public education (only one of which was spent abroad) never
used *anything* but SI units, but since we never really work with them
here outside the realm of science (where they're pretty obligatory),
one just doesn't think in them. Too many brushes with the other every
day. "Would you like an 8-oz coffee sir, or a 12-oz one?" "How many
pounds of tomatoes would you like, maam?" "Gosh, it's gonna hit triple
digits before June you know." It's everywhere, so you think in the
local lingo.

I just tell people that meter is metric for yard and to leave it at
that-- even though the ratio is much closer to 12:13 than to 1:1, but
that's well within the normal tolerance of human guestimation. AND
THAT IS ALMOST ALWAYS PERFECTLY GOOD ENOUGH.

Getting too accurate isn't natural--or correct. That's why Americans
think the average human body temperature is exactly 98.6°F.

It's not.

It's 37°C ± something like ½°C. So they've taken a figure accurate
in two decimal places and falsly magnified its apparent accuracy by
an order of magnitude by trying to give it 3 digits when it deserve
no more than two.

That's just not right.

Another suspect rule is that you lose 3-5°F per 1,000 feet of elevation you
go up. I bet that's not the real rule. I bet it's really 2°C per 300
meters, and somebody was just trying to be helpful. But I don't know that
for sure, nor the tolerances involved. Too many fuzzy factors easily enter
into it, and I'm not entirely certain it's altogether linear.

Now, some folks are *finally* starting to catch on to this sort
of thing, like the Economist. But most people figure that golly,
if a meter's 39.37", dog gone it, then if you go and tell them
something's oh only about some 3 meters away from them, they figure
that it's 10.11" past 9' away, from them, which is almost always
very silly.

The only worse one was when I read some stupid magazine (ok, it was
Newsweek, but I was trapped at my dentist's office; I'm happy to report
that I've since converted him to the Economist) that said how the room
temperature had risen 10°F warmer than it had been previously, like from 60
to 70 or something -- a figure which they in naïve helpfulness more like a
blindly obedient computer than a thinking human being proceeded to
parenthesize as "(-12.2°C)".

Laughed my you-know-what off.

But I really have no trouble using different measurements for
different things. Oh, I don't mean measuring horses in hands and cows
in feet (although they do, now that I think of it). I just mean that
it's no problem for me that I measure flower-blooms in millimeters but
altitudes (Z-axis) in in feet, land distances (XY pseudoplane [oblate
spheroid]) in miles, light wavelengths in nanometers, and stellar
distances in parsecs.

Same with all the others: Pints of beer, gallons of milk, and 30mg of
cough syrup--and yes, I'm aware that one of those things is not like
the other in a far more profound way then just switching systems:
volume vs mass.

And speaking of altitude, ahem, we do measure it oddly, now don't we?
It's that whole "sea"-level and "oblate spheroid" bit. Mt Everest in
the Himalayas isn't the "tallest" peak; Mt Chimborazo in the Andes
(probably) is. Then try figuring out whether Death Valley is lower
or higher than Fairbanks. Go ahead. It's fun.

And how come when I stand at 12 or 15 kilofeet, I don't need an oxygen
mask, but a pilot in an open craft does? Because of the contour
effect of the atmosphere hugging the surface. Well, that, plus if
*he* passed out, he's got a *lot* farther to fall than I'd have.

But really, there's a lot less air if you're hovering 12k' above the
ocean than there is here up at Cottonwood Pass, which is also at 12k'.
You can breathe there fine (well, I can), because you still have
something like 60% of sea-level air pressure there. It only affects
me half as much as flatlanders, since you're used to 25% more air than
I am in the first place. Flatlanders usually have about 30" Hg, but
I never seem to even hit 25" of quicksilver. Cottonwood Pass, or the
top of Trail Ridge Road, has about 17" of mercury in the tube. You do
the arithmetic.

Somewhere I have pictures of Damian at these places and more. At
the start of the week he was almost staggering once we got beyond
the timberline. To be fair, he did recovery quickly and improved
notably as the week progressed. But racing up the stairs at the
top of Trail Ridge Road on his first day here was incredibly
funny. I don't think he'd ever been high before then, but he
sure was that day!

Now don't get me started on whether pounds are measuring mass, or
really just measuring force. If on Luna you "weigh" only about a
sixth what you do on Earth, say 30 pounds instead of 180, then don't
you DARE go converting pounds into kilograms and report that you now
weigh something like about 65 kg. Nobody weighs anything in
kilograms; they *weigh* something in Newtons, which most certainly
does change depending on where one's is standing--or falling.

But just try convincing a metric maven of that one. You're
right, they're wrong, and you won't win. And on the other side
of the water, down that road lie waiting these really nasty
slugs you surely wish to avoid dealing with. And don't get me
started on whether pounds are measuring mass, or really just
measuring force.

The only other one that kinda annoys me is how pounds of feathers
weigh more than pounds of gold.

And I try not to think about my regular oven's BTUs.

I just REALLY wish that nukable food would tell you how long it took
to cook in watt-seconds instead of the useless and often misleading
handwaving they usually publish. Anything else than watt-seconds is
foolish, as microwave oven can very in more than an order of magnitude
(well, in binary :-), so all directions are stupid. If you go from a
600-watt oven that cooks something in 3 minutes to a 1300-watt often,
you jolly well had better adjust those 180 seconds by a corresponding
factor of 6/13. And people never do, and suffer.

And no, I don't mean you should be cooking it for 83.076923076923076
seconds or only 1 minute, dang it.:-) Just call it 80 or 85 seconds.

Now, it would seem to me that if you really wanted Americans (or anybody
else) to convert, that the easiest, most devious--and, I believe, the most
effective--route leading to Americans to adopt SI units is simply to recast
the discourse as "Standard vs Imperial". That's *not* it's talked about
here. Rather, here it's "Metric vs English".

This *is* a problem. It may even be *the* problem.

An American contemplating forced away from "English" (wrongly)
perceives himself as the victim of some form of subtle European
imperialism. Decouple it from the same word that's their mother
tongue and they just might start to think logically about it.
Don't do that, and they never will. Or won't for a very long time.

I say this because I strongly believe that it's as much an
unrecognized cultural, socio-linguistic thing that's blocking adoption
as it is anything else; maybe moreso. That's why I called my plan
devious. They won't see it coming.

The sooner we change the emotionally-charged discourse-framework into
one that furthers our standardization goals, the sooner we can begin
the easier battle: that is, winning the minds. For if ever we manage
to change the discourse framework, the harder battle will already have
been won: that of their hearts.

Don't believe me? Fine: consider how much harder it would be to
get Americans to use Unicode if it happened to have been called
Eurocode instead. You *know* it would have been, and so there
I rest my case.

For names matter, often a lot, and they do so in ways for most of us that
operate considerably below the level of conscious awareness. But that
hardly renders them inoperative.

Just ask Larry why Python is a terrible name for a language, but Pearl
a lovely one. It's pretty obvious, really.

- python <= serpent = devil = original sin => evil.

- perl <= pearl = precious => small and beautiful => desirable.

The only question I'm somewhat unresolved on here is whether we should hold
as ethical the manipulation of someone else entirely for their own good,
not for your own. Is it still ethical if they're *not* made aware of said
manipulation? The best and worst cases of those would seem to gravitate
toward an answer of no and yes, respectively. Plus also, I guess it
depends on the consequences--both ways. But *that* sounds far, *far* too
much like one of those ends-justifying-means things for me ever to be
totally cool with it. Too many brutal things, things of unspeakable evil,
have been done by those who *thought* themselves gifted (to them) with the
vision and will to do great good in this world.

Look at last century.

Look even at today.

But now that I've told *you* of my secret plan to drag Americans kicking
and screaming (back) into full(er) SI compliance, my ever-niggling
conscience is once again clear as a just-cast churchbell. That means
the stealth-campaigning may begin at will. :-)

If you're up to it, then spread the good word: it's not "English vs Metric",
but "Standard vs Imperial." You don't need to tell them where it came from.
You don't even have to say why you are doing it; that's up to each of you.

But that won't stop it from getting done. In fact, a semi-surreptitious,
low-key approach with slow viral spread of this meme told mouth to
mouth may well, if even so slightly, improve the odds of its success.

Or so I reckon.

But remember: There *is* *no* Cabal. :)

Yet.

--tom
--

"We make a living by what we get,
but we make a life by what we give."
--Winston Churchill

Perl porters RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact lists@gossamer-threads.com
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.