
Getopt::Popt - Perl interface to the popt(3) library

use Getopt::Popt qw(:all);
# setup the options array
push @options,new Getopt::Popt::Option(
longName => "long",
shortName => "l",
argInfo => POPT_ARG_STRING,
arg => \$qux,
val => $val);
# or, if you're lazy, have Getopt::Popt automagically do the new()
push @options, { shortName => 's',
argInfo => POPT_ARG_NONE,
arg => \$quux,
val => 's'
};
# "val"s can be a single character or an integer:
push @options, { longName => 'xor',
argInfo => POPT_ARG_VAL | POPT_ARGFLAG_XOR,
arg => \$quuux,
val => 0xbadf00d # integer
},
Enable automatic help/usage messages (--help or --usage):
push @options, POPT_AUTOHELP;
Create a new popt context:
$popt = new Getopt::Popt(name => $alias_name,
argv => \@ARGV,
options => \@options,
flags => $flags);
Setup option aliases:
# load some aliases
$popt->readDefaultConfig();
$popt->readConfigFile("/path/to/aliases");
# add your own alias
$alias = new Getopt::Popt::Alias(longName => "taco",
argv => [qw(--flavored --kisses)]);
$popt->addAlias($alias, $alias_flags);
Load options as you would in C:
# loop through the options, using the popt C way:
while(($rc = $popt->getNextOpt()) > 0) {
...
# one way to get the arg val
$bork = $popt->getOptArg();
...
# stuff some args
$popt->stuffArgs(qw(-q -u -x));
...
# start over
$popt->resetContext();
...
}
And handle errors as you would in C:
$errstr = $popt->strerror($rc);
$badopt = $popt->badOption($rc,$badopt_flags);
Or try the new perly way:
eval {
while(defined($val = $popt->getNextOptChar())) {
^^^^-- note!
# $val is a Scalar::Util::dualvar:
if($val eq "c") { # <- character
...
} elsif($val == 0xbeef) { # <- integer
...
} elsif(ord($val) == 2922) { # <- utf8, ok!
...
}
...
# you can still stuff args or reset the context as before
...
}
};
# check for errors:
if($@) {
# prints something like "bad argument: --shoes: unknown option"
print "bad argument: $@\n";
}
Get leftover args:
$arg = $popt->peekArg();
$arg = $popt->getArg();
@args = $popt->getArgs();

This module provides an interface to (most of) the functions available in the popt library. See the popt(3) manpage for more details about what the popt library can do.

Getopt::Popt should look like a fairly natural object oriented mapping to all of the popt functions.
Getopt::Popt->new( %params )Create a new Getopt::Popt context. Parameters map to the arguments to popt's poptGetContext(), plus one additional argument:
%params = (
alias_name => $name,
argv => \@argv,
options => \@options,
flags => $flags,
# new and special:
dont_prepend_progname => $bool,
);
Dies on an error.
$alias_name Name for lookup in alias definitions (see the popt(3) manpage). Can be empty.
\@argvCommand line arguments, e.g. \@ARGV. NOTE: \@argv will be passed to popt as the array ($0, @argv) (a copy is made so that your \@argv won't be modified) unless given the dont_prepend_progname option (see below).
$flagsContext flags (see CONSTANTS). Defaults to 0.
\@optionsOptions array. All elements must be either a Getopt::Popt::Option or a hashref; hashrefs will be automagically converted into Getopt::Popt::Options.
$dont_prepend_prognameDon't stick $0 before @argv. Perl's @ARGV just has arguments and does not include the current process name, but popt expects something in argv[0]. So $0 is prepended unless this flag has been set. It's an error if dont_prepend_progname is true but @argv is empty.
Defaults to 0.
Getopt::Popt::getNextOptChar()This is a wrapper around Getopt::Popt::getNextOpt(). Returns a dualvar (see Scalar::Util) rather than just an integer. In a numeric context ("0+$ch" or "$ch == $number") the return value is the integer value that Getopt::Popt::getNextOpt() would've returned, and in a string context the return value is a character. Really all it saves you is having to use chr() all the time.
Returns undef when it's done reading args, dies with a Getopt::Popt::strerror()'d message on an error.
See the popt(3) manpage for details on these methods:
Getopt::Popt::resetContext()
Getopt::Popt::getNextOpt()
Getopt::Popt::getOptArg()
Getopt::Popt::getArg()
Getopt::Popt::peekArg()
Getopt::Popt::getArgs()
Getopt::Popt::strerror($error)
Getopt::Popt::badOption($flags)
Getopt::Popt::readDefaultConfig()
Getopt::Popt::readConfigFile()
Getopt::Popt::addAlias($alias, $flags)
Getopt::Popt::setOtherOptionHelp($str)
Getopt::Popt::stuffArgs(@args)Represents a struct poptOption
Getopt::Popt::Option->new( %params )Create a new option. %params maps to popt's struct poptOption:
%params = (
longName => $longName,
shortName => $shortName, # single char
argInfo => $argInfo, # see CONSTANTS below
arg => \$arg, # depends on $argInfo
val => $val, # integer OR single character
descrip => $descrip,
argDescrip => $argDescrip,
);
Dies on an error.
$longNameLong name of the argument, e.g. "--foo"'s long name is "foo".
$shortNameShort name of the argument, e.g. "-f"'s short name is "f". Must be a single character.
$argInfoAn integer, bitwise-ORed with different flags (see CONSTANTS below).
\$argA scalar reference, with the scalar being set to the option argument value.
$valThe value to be returned by getNextOpt() (or getNextOptChar()). Can be a single character or an integer.
Note that if you want $val to be a real single-digit integer (and not the character representation of it), pass it in as "+1" or "1.0", or as "\1". If you use any of the bit operations (POPT_ARGFLAG_[AND|OR|XOR]) that popt has, it's important that "1" be a 1 and not ord("1") = 49. Otherwise you probably don't care.
$descripLong description of the option, used in generating autohelp.
$argDescripShort description of the argument to the option, used in generating autohelp.
Value getters (no setters):
Getopt::Popt::Option::getLongName()
Getopt::Popt::Option::getShortName()
Getopt::Popt::Option::getArgInfo()
Getopt::Popt::Option::getArg()
Getopt::Popt::Option::getVal()
Getopt::Popt::Option::getDescrip()
Getopt::Popt::Option::getArgDescrip()Represents a struct poptAlias
Getopt::Popt::Alias->new( %params )Create a new alias to pass to Getopt::Popt::addAlias(). %params maps to popt's struct poptAlias:
%params = (
longName => $longName,
shortName => $shortName, # single char
argv => \@args, # non-empty array of args
);
Dies on an error.

Most of the constant integers defined in popt.h (except for a few relating to callbacks and table inclusion, see TODO below) are available for import via the :all tag. Other tags are: :argflag for argument flags, :arg for argument types, :autohelp for POPT_AUTOHELP, :badoption for POPT_BADOPTION_NOALIAS, :context for context flags, and :error for error values.
You can use the the POPT_AUTOHELP constant just as you would in C. Just put it on your \@options and autohelp will be enabled.

The following is a perl implementation of the example given in the popt(3) manpage.
#!/usr/bin/perl
use Getopt::Popt qw(:all);
use strict;
main();
sub usage {
my $popt = shift;
my $exitcode = shift;
my $error = shift;
my $addl = shift;
# not implemented:
# $popt->printUsage(\*STDERR, 0);
print STDERR "do --help to show options\n";
print STDERR "$error $addl\n" if $error;
exit($exitcode);
}
sub main {
my $c; # used for argument parsing
my $portname;
my $speed; # used in argument parsing to set speed
my $raw; # raw mode?
my @buf;
my $popt;
my @optionsTable = (
{
longName => "bps",
shortName => 'b',
argInfo => POPT_ARG_INT,
arg => \$speed,
val => 0,
descrip => "signaling rate in bits-per-second",
argDescrip => "BPS"
},
{
longName => "crnl",
shortName => 'c',
argInfo => 0,
val => 'c',
descrip => "expand cr characters to cr/lf sequences"
},
{
longName => "hwflow",
shortName => 'h',
argInfo => 0,
val => 'h',
descrip => "use hardware (RTS/CTS) flow control"
},
{
longName => "noflow",
shortName => 'n',
argInfo => 0,
val => 'n',
descrip => "use no flow control"
},
{
longName => "raw",
shortName => 'r',
argInfo => 0,
arg => \$raw,
descrip => "don't perform any character conversions"
},
{
longName => "swflow",
shortName => 's',
argInfo => 0,
val => 's',
descrip => "use software (XON/XOF) flow control"
} ,
POPT_AUTOHELP,
);
$popt = new Getopt::Popt(argv => \@ARGV,options => \@optionsTable);
$popt->setOtherOptionHelp("[OPTIONS]* <port>");
if (@ARGV < 1) {
# not implemented
#$popt->printUsage(optCon, stderr, 0);
print STDERR "not enough arguments: do --help to show options\n";
exit(1);
}
# Now do options processing, get portname
eval {
while (defined($c = $popt->getNextOptChar())) {
push(@buf,'c') if $c eq 'c';
push(@buf,'h') if $c eq 'h';
push(@buf,'s') if $c eq 's';
push(@buf,'n') if $c eq 'n';
}
};
if ($@) {
# an error occurred during option processing
my($msg) = ($@ =~ m/(.*) at [\S]+ line \d+\s*$/);
printf(STDERR "bad argument: $msg\n");
exit 1;
}
$portname = $popt->getArg();
if(($portname eq "") || !($popt->peekArg() eq "")) {
usage($popt, 1, "Specify a single port", ".e.g., /dev/cua0");
}
# Print out options, portname chosen
print("Options chosen: ");
print("-$_ ") foreach @buf;
print("-r ") if(defined($raw));
print("-b $speed") if(defined($speed));
print("\nPortname chosen: $portname\n");
exit(0);
}

This module should be considered beta quality. Don't use it where a possible buffer overflow or double-free or something would be a bad thing. Comments and bug fixes are greatly appreciated!
POPT_ARG_VAL is converted internally to POPT_ARG_NONE (but don't worry, it still sets \$arg to $val). As a consequence, the behavior may be slightly different.
If you're using POPT_AUTOHELP and the user gives --help or --usage, popt exits and any exit handlers, destructors, etc. won't be called. This is expected to be fixed once printHelp() and printUsage() get implemented (see TODO below).
Tested with popt-1.6 and popt-1.7 on Debian woody i386, and on slack 9 with popt-1.7, YMMV.

Finish writing this documentation.
Need to implement: printHelp(), printUsage(), callbacks, parseArgvString(), and dupArgv()
Probably won't implement: table inclusion (because it's easier to just pass around perl arrays of options);

popt(3), Getopt::Std, Getopt::Long, and everything in http://search.cpan.org/modlist/Option_Parameter_Config_Processing
The latest version of the popt library is distributed with rpm and is always available from: ftp://ftp.rpm.org/pub/rpm/dist.

This module is by James Baker <jamesb-at-cpan-dot-org>.
The popt library is by Erik W. Troan <ewt-at-redhat-dot-com>.

This program is Copyright 2003 by James Baker. This program is free software; you can redistribute it and/or modify it under the terms of the Perl Artistic License or the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
If you do not have a copy of the GNU General Public License write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.