2002-03-09 23:29:33 +00:00
|
|
|
#
|
|
|
|
# Copyright 1999, 2000, 2001 Patrik Stridvall
|
|
|
|
#
|
|
|
|
# This library is free software; you can redistribute it and/or
|
|
|
|
# modify it under the terms of the GNU Lesser General Public
|
|
|
|
# License as published by the Free Software Foundation; either
|
|
|
|
# version 2.1 of the License, or (at your option) any later version.
|
|
|
|
#
|
|
|
|
# This library 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
|
|
|
|
# Lesser General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU Lesser General Public
|
|
|
|
# License along with this library; if not, write to the Free Software
|
2006-05-18 12:49:52 +00:00
|
|
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
2002-03-09 23:29:33 +00:00
|
|
|
#
|
|
|
|
|
2001-06-13 19:38:29 +00:00
|
|
|
package options;
|
|
|
|
|
|
|
|
use strict;
|
2020-07-21 22:10:10 +00:00
|
|
|
use warnings 'all';
|
2001-06-13 19:38:29 +00:00
|
|
|
|
|
|
|
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
|
|
|
|
require Exporter;
|
|
|
|
|
|
|
|
@ISA = qw(Exporter);
|
2001-07-23 23:20:56 +00:00
|
|
|
@EXPORT = qw();
|
2004-10-26 00:12:21 +00:00
|
|
|
@EXPORT_OK = qw($options parse_comma_list parse_value);
|
2001-06-13 19:38:29 +00:00
|
|
|
|
2001-07-23 23:20:56 +00:00
|
|
|
use vars qw($options);
|
2001-07-11 17:27:45 +00:00
|
|
|
|
2001-07-29 20:19:14 +00:00
|
|
|
use output qw($output);
|
|
|
|
|
2004-10-26 00:12:21 +00:00
|
|
|
sub parse_comma_list($$) {
|
2001-06-13 19:38:29 +00:00
|
|
|
my $prefix = shift;
|
|
|
|
my $value = shift;
|
2001-07-29 20:19:14 +00:00
|
|
|
|
2001-06-13 19:38:29 +00:00
|
|
|
if(defined($prefix) && $prefix eq "no") {
|
|
|
|
return { active => 0, filter => 0, hash => {} };
|
|
|
|
} elsif(defined($value)) {
|
|
|
|
my %names;
|
|
|
|
for my $name (split /,/, $value) {
|
|
|
|
$names{$name} = 1;
|
|
|
|
}
|
|
|
|
return { active => 1, filter => 1, hash => \%names };
|
|
|
|
} else {
|
|
|
|
return { active => 1, filter => 0, hash => {} };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-10-26 00:12:21 +00:00
|
|
|
sub parse_value($$) {
|
2001-07-29 20:19:14 +00:00
|
|
|
my $prefix = shift;
|
|
|
|
my $value = shift;
|
|
|
|
|
|
|
|
return $value;
|
|
|
|
}
|
|
|
|
|
2001-06-13 19:38:29 +00:00
|
|
|
package _options;
|
|
|
|
|
|
|
|
use strict;
|
2020-07-21 22:10:10 +00:00
|
|
|
use warnings 'all';
|
2001-06-13 19:38:29 +00:00
|
|
|
|
2001-07-23 23:20:56 +00:00
|
|
|
use output qw($output);
|
|
|
|
|
2004-10-26 00:12:21 +00:00
|
|
|
sub options_set($$);
|
|
|
|
|
|
|
|
sub new($$$$) {
|
2001-06-13 19:38:29 +00:00
|
|
|
my $proto = shift;
|
|
|
|
my $class = ref($proto) || $proto;
|
|
|
|
my $self = {};
|
|
|
|
bless ($self, $class);
|
|
|
|
|
2001-07-26 21:42:12 +00:00
|
|
|
my $options_long = \%{$self->{_OPTIONS_LONG}};
|
|
|
|
my $options_short = \%{$self->{_OPTIONS_SHORT}};
|
|
|
|
my $options_usage = \${$self->{_OPTIONS_USAGE}};
|
2001-06-13 19:38:29 +00:00
|
|
|
|
|
|
|
my $refoptions_long = shift;
|
|
|
|
my $refoptions_short = shift;
|
|
|
|
$$options_usage = shift;
|
|
|
|
|
|
|
|
%$options_long = %{$refoptions_long};
|
|
|
|
%$options_short = %{$refoptions_short};
|
|
|
|
|
|
|
|
$self->options_set("default");
|
|
|
|
|
2001-07-26 21:42:12 +00:00
|
|
|
my $arguments = \@{$self->{_ARGUMENTS}};
|
2001-09-10 23:16:05 +00:00
|
|
|
@$arguments = ();
|
2001-06-13 19:38:29 +00:00
|
|
|
|
2001-07-26 21:42:12 +00:00
|
|
|
my $end_of_options = 0;
|
2001-06-13 19:38:29 +00:00
|
|
|
while(defined($_ = shift @ARGV)) {
|
2001-07-26 21:42:12 +00:00
|
|
|
if(/^--$/) {
|
|
|
|
$end_of_options = 1;
|
|
|
|
next;
|
|
|
|
} elsif($end_of_options) {
|
|
|
|
# Nothing
|
|
|
|
} elsif(/^--(all|none)$/) {
|
2001-06-13 19:38:29 +00:00
|
|
|
$self->options_set("$1");
|
|
|
|
next;
|
|
|
|
} elsif(/^-([^=]*)(=(.*))?$/) {
|
|
|
|
my $name;
|
|
|
|
my $value;
|
|
|
|
if(defined($2)) {
|
|
|
|
$name = $1;
|
|
|
|
$value = $3;
|
|
|
|
} else {
|
|
|
|
$name = $1;
|
|
|
|
}
|
2002-06-01 02:55:48 +00:00
|
|
|
|
2001-06-13 19:38:29 +00:00
|
|
|
if($name =~ /^([^-].*)$/) {
|
|
|
|
$name = $$options_short{$1};
|
|
|
|
} else {
|
|
|
|
$name =~ s/^-(.*)$/$1/;
|
|
|
|
}
|
2002-06-01 02:55:48 +00:00
|
|
|
|
2001-06-13 19:38:29 +00:00
|
|
|
my $prefix;
|
|
|
|
if(defined($name) && $name =~ /^no-(.*)$/) {
|
|
|
|
$name = $1;
|
|
|
|
$prefix = "no";
|
|
|
|
if(defined($value)) {
|
2001-07-11 17:27:45 +00:00
|
|
|
$output->write("options with prefix 'no' can't take parameters\n");
|
2001-06-13 19:38:29 +00:00
|
|
|
|
|
|
|
return undef;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
my $option;
|
|
|
|
if(defined($name)) {
|
|
|
|
$option = $$options_long{$name};
|
|
|
|
}
|
|
|
|
|
|
|
|
if(defined($option)) {
|
|
|
|
my $key = $$option{key};
|
|
|
|
my $parser = $$option{parser};
|
|
|
|
my $refvalue = \${$self->{$key}};
|
|
|
|
my @parents = ();
|
2002-06-01 02:55:48 +00:00
|
|
|
|
2001-06-13 19:38:29 +00:00
|
|
|
if(defined($$option{parent})) {
|
|
|
|
if(ref($$option{parent}) eq "ARRAY") {
|
|
|
|
@parents = @{$$option{parent}};
|
|
|
|
} else {
|
|
|
|
@parents = $$option{parent};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-06-01 02:55:48 +00:00
|
|
|
if(defined($parser)) {
|
2001-09-10 23:16:05 +00:00
|
|
|
if(!defined($value)) {
|
|
|
|
$value = shift @ARGV;
|
|
|
|
}
|
2001-06-13 19:38:29 +00:00
|
|
|
$$refvalue = &$parser($prefix,$value);
|
|
|
|
} else {
|
|
|
|
if(defined($value)) {
|
|
|
|
$$refvalue = $value;
|
|
|
|
} elsif(!defined($prefix)) {
|
|
|
|
$$refvalue = 1;
|
|
|
|
} else {
|
|
|
|
$$refvalue = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if((ref($$refvalue) eq "HASH" && $$refvalue->{active}) || $$refvalue) {
|
|
|
|
while($#parents >= 0) {
|
|
|
|
my @old_parents = @parents;
|
|
|
|
@parents = ();
|
|
|
|
foreach my $parent (@old_parents) {
|
|
|
|
my $parentkey = $$options_long{$parent}{key};
|
|
|
|
my $refparentvalue = \${$self->{$parentkey}};
|
2002-06-01 02:55:48 +00:00
|
|
|
|
2001-06-13 19:38:29 +00:00
|
|
|
$$refparentvalue = 1;
|
|
|
|
|
|
|
|
if(defined($$options_long{$parent}{parent})) {
|
|
|
|
if(ref($$options_long{$parent}{parent}) eq "ARRAY") {
|
|
|
|
push @parents, @{$$options_long{$parent}{parent}};
|
|
|
|
} else {
|
|
|
|
push @parents, $$options_long{$parent}{parent};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
}
|
2002-06-01 02:55:48 +00:00
|
|
|
|
2001-07-26 21:42:12 +00:00
|
|
|
if(!$end_of_options && /^-(.*)$/) {
|
2002-06-01 02:55:48 +00:00
|
|
|
$output->write("unknown option: $_\n");
|
2001-07-11 17:27:45 +00:00
|
|
|
$output->write($$options_usage);
|
2001-06-13 19:38:29 +00:00
|
|
|
exit 1;
|
|
|
|
} else {
|
2001-07-26 21:42:12 +00:00
|
|
|
push @$arguments, $_;
|
2001-06-13 19:38:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if($self->help) {
|
2001-07-11 17:27:45 +00:00
|
|
|
$output->write($$options_usage);
|
2001-06-13 19:38:29 +00:00
|
|
|
$self->show_help;
|
|
|
|
exit 0;
|
|
|
|
}
|
|
|
|
|
2001-07-26 21:42:12 +00:00
|
|
|
return $self;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub DESTROY {
|
|
|
|
}
|
|
|
|
|
2004-10-26 00:12:21 +00:00
|
|
|
sub parse_files($) {
|
2001-07-26 21:42:12 +00:00
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
my $arguments = \@{$self->{_ARGUMENTS}};
|
2001-07-30 18:49:10 +00:00
|
|
|
my $directories = \@{$self->{_DIRECTORIES}};
|
2001-07-26 21:42:12 +00:00
|
|
|
my $c_files = \@{$self->{_C_FILES}};
|
|
|
|
my $h_files = \@{$self->{_H_FILES}};
|
|
|
|
|
|
|
|
my $error = 0;
|
|
|
|
my @files = ();
|
|
|
|
foreach (@$arguments) {
|
|
|
|
if(!-e $_) {
|
|
|
|
$output->write("$_: no such file or directory\n");
|
|
|
|
$error = 1;
|
|
|
|
} else {
|
|
|
|
push @files, $_;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if($error) {
|
|
|
|
exit 1;
|
|
|
|
}
|
|
|
|
|
2001-06-13 19:38:29 +00:00
|
|
|
my @paths = ();
|
|
|
|
my @c_files = ();
|
|
|
|
my @h_files = ();
|
|
|
|
foreach my $file (@files) {
|
|
|
|
if($file =~ /\.c$/) {
|
|
|
|
push @c_files, $file;
|
|
|
|
} elsif($file =~ /\.h$/) {
|
|
|
|
push @h_files, $file;
|
|
|
|
} else {
|
|
|
|
push @paths, $file;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-07 14:46:33 +00:00
|
|
|
if($#c_files == -1 && $#h_files == -1 && $#paths == -1 && -d ".git")
|
2001-06-13 19:38:29 +00:00
|
|
|
{
|
2010-06-07 14:46:33 +00:00
|
|
|
@$c_files = sort split /\0/, `git ls-files -z \\*.c`;
|
|
|
|
@$h_files = sort split /\0/, `git ls-files -z \\*.h`;
|
2001-06-13 19:38:29 +00:00
|
|
|
}
|
2010-06-07 14:46:33 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if($#c_files == -1 && $#h_files == -1 && $#paths == -1)
|
|
|
|
{
|
|
|
|
@paths = ".";
|
|
|
|
}
|
|
|
|
|
|
|
|
if($#paths != -1 || $#c_files != -1) {
|
|
|
|
my $c_command = "find " . join(" ", @paths, @c_files) . " -name \\*.c";
|
|
|
|
my %found;
|
|
|
|
@$c_files = sort(map {
|
|
|
|
s/^\.\/(.*)$/$1/;
|
|
|
|
if(defined($found{$_})) {
|
|
|
|
();
|
|
|
|
} else {
|
|
|
|
$found{$_}++;
|
|
|
|
$_;
|
|
|
|
}
|
|
|
|
} split(/\n/, `$c_command`));
|
|
|
|
}
|
|
|
|
|
|
|
|
if($#paths != -1 || $#h_files != -1) {
|
|
|
|
my $h_command = "find " . join(" ", @paths, @h_files) . " -name \\*.h";
|
|
|
|
my %found;
|
|
|
|
|
|
|
|
@$h_files = sort(map {
|
|
|
|
s/^\.\/(.*)$/$1/;
|
|
|
|
if(defined($found{$_})) {
|
|
|
|
();
|
|
|
|
} else {
|
|
|
|
$found{$_}++;
|
|
|
|
$_;
|
|
|
|
}
|
|
|
|
} split(/\n/, `$h_command`));
|
|
|
|
}
|
2001-06-13 19:38:29 +00:00
|
|
|
}
|
2001-07-30 18:49:10 +00:00
|
|
|
|
|
|
|
my %dirs;
|
|
|
|
foreach my $file (@$c_files, @$h_files) {
|
|
|
|
my $dir = $file;
|
|
|
|
$dir =~ s%/?[^/]+$%%;
|
|
|
|
if(!$dir) { $dir = "."; }
|
|
|
|
$dirs{$dir}++
|
|
|
|
}
|
|
|
|
|
|
|
|
@$directories = sort(keys(%dirs));
|
2001-06-13 19:38:29 +00:00
|
|
|
}
|
|
|
|
|
2004-10-26 00:12:21 +00:00
|
|
|
sub options_set($$) {
|
2001-06-13 19:38:29 +00:00
|
|
|
my $self = shift;
|
|
|
|
|
2001-07-26 21:42:12 +00:00
|
|
|
my $options_long = \%{$self->{_OPTIONS_LONG}};
|
|
|
|
my $options_short = \%{$self->{_OPTIONS_SHORT}};
|
2001-06-13 19:38:29 +00:00
|
|
|
|
|
|
|
local $_ = shift;
|
|
|
|
for my $name (sort(keys(%$options_long))) {
|
|
|
|
my $option = $$options_long{$name};
|
|
|
|
my $key = uc($name);
|
|
|
|
$key =~ tr/-/_/;
|
|
|
|
$$option{key} = $key;
|
|
|
|
my $refvalue = \${$self->{$key}};
|
|
|
|
|
|
|
|
if(/^default$/) {
|
|
|
|
$$refvalue = $$option{default};
|
|
|
|
} elsif(/^all$/) {
|
2002-11-27 20:11:10 +00:00
|
|
|
if($name !~ /^(?:help|debug|verbose|module)$/) {
|
2001-06-13 19:38:29 +00:00
|
|
|
if(ref($$refvalue) ne "HASH") {
|
|
|
|
$$refvalue = 1;
|
|
|
|
} else {
|
|
|
|
$$refvalue = { active => 1, filter => 0, hash => {} };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} elsif(/^none$/) {
|
2002-11-27 20:11:10 +00:00
|
|
|
if($name !~ /^(?:help|debug|verbose|module)$/) {
|
2001-06-13 19:38:29 +00:00
|
|
|
if(ref($$refvalue) ne "HASH") {
|
|
|
|
$$refvalue = 0;
|
|
|
|
} else {
|
|
|
|
$$refvalue = { active => 0, filter => 0, hash => {} };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-10-26 00:12:21 +00:00
|
|
|
sub show_help($) {
|
2001-06-13 19:38:29 +00:00
|
|
|
my $self = shift;
|
|
|
|
|
2001-07-26 21:42:12 +00:00
|
|
|
my $options_long = \%{$self->{_OPTIONS_LONG}};
|
|
|
|
my $options_short = \%{$self->{_OPTIONS_SHORT}};
|
2001-06-13 19:38:29 +00:00
|
|
|
|
|
|
|
my $maxname = 0;
|
|
|
|
for my $name (sort(keys(%$options_long))) {
|
|
|
|
if(length($name) > $maxname) {
|
|
|
|
$maxname = length($name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for my $name (sort(keys(%$options_long))) {
|
|
|
|
my $option = $$options_long{$name};
|
|
|
|
my $description = $$option{description};
|
2004-10-25 21:50:36 +00:00
|
|
|
my $parser = $$option{parser};
|
2001-06-13 19:38:29 +00:00
|
|
|
my $current = ${$self->{$$option{key}}};
|
|
|
|
|
|
|
|
my $value = $current;
|
2002-06-01 02:55:48 +00:00
|
|
|
|
2001-06-13 19:38:29 +00:00
|
|
|
my $command;
|
2004-10-25 21:50:36 +00:00
|
|
|
if(!defined $parser) {
|
2001-06-13 19:38:29 +00:00
|
|
|
if($value) {
|
|
|
|
$command = "--no-$name";
|
|
|
|
} else {
|
|
|
|
$command = "--$name";
|
|
|
|
}
|
|
|
|
} else {
|
2004-10-25 21:50:36 +00:00
|
|
|
if(ref($value) eq "HASH" && $value->{active}) {
|
2001-06-13 19:38:29 +00:00
|
|
|
$command = "--[no-]$name\[=<value>]";
|
|
|
|
} else {
|
|
|
|
$command = "--$name\[=<value>]";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-07-11 17:27:45 +00:00
|
|
|
$output->write($command);
|
2004-10-25 21:50:36 +00:00
|
|
|
$output->write(" " x (($maxname - length($name) + 17) - (length($command) - length($name) + 1)));
|
|
|
|
if(!defined $parser) {
|
2001-06-13 19:38:29 +00:00
|
|
|
if($value) {
|
2001-07-11 17:27:45 +00:00
|
|
|
$output->write("Disable ");
|
2001-06-13 19:38:29 +00:00
|
|
|
} else {
|
2001-07-11 17:27:45 +00:00
|
|
|
$output->write("Enable ");
|
2002-06-01 02:55:48 +00:00
|
|
|
}
|
2001-06-13 19:38:29 +00:00
|
|
|
} else {
|
2004-10-25 21:50:36 +00:00
|
|
|
if(ref($value) eq "HASH")
|
|
|
|
{
|
|
|
|
if ($value->{active}) {
|
|
|
|
$output->write("(Disable) ");
|
|
|
|
} else {
|
|
|
|
$output->write("Enable ");
|
|
|
|
}
|
|
|
|
}
|
2002-06-01 02:55:48 +00:00
|
|
|
}
|
2004-10-25 21:50:36 +00:00
|
|
|
$output->write("$description\n");
|
2001-06-13 19:38:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub AUTOLOAD {
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
my $name = $_options::AUTOLOAD;
|
|
|
|
$name =~ s/^.*::(.[^:]*)$/\U$1/;
|
|
|
|
|
|
|
|
my $refvalue = $self->{$name};
|
|
|
|
if(!defined($refvalue)) {
|
2007-01-18 10:35:50 +00:00
|
|
|
die "<internal>: options.pm: member $name does not exist\n";
|
2001-06-13 19:38:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(ref($$refvalue) ne "HASH") {
|
|
|
|
return $$refvalue;
|
|
|
|
} else {
|
|
|
|
return $$refvalue->{active};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-10-26 00:12:21 +00:00
|
|
|
sub arguments($) {
|
2001-07-26 21:42:12 +00:00
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
my $arguments = \@{$self->{_ARGUMENTS}};
|
|
|
|
|
2002-06-01 02:55:48 +00:00
|
|
|
return @$arguments;
|
2001-07-26 21:42:12 +00:00
|
|
|
}
|
|
|
|
|
2004-10-26 00:12:21 +00:00
|
|
|
sub c_files($) {
|
2002-06-01 02:55:48 +00:00
|
|
|
my $self = shift;
|
2001-07-26 21:42:12 +00:00
|
|
|
|
|
|
|
my $c_files = \@{$self->{_C_FILES}};
|
|
|
|
|
2013-09-20 09:49:34 +00:00
|
|
|
if(!@$c_files) {
|
2001-07-26 21:42:12 +00:00
|
|
|
$self->parse_files;
|
|
|
|
}
|
|
|
|
|
|
|
|
return @$c_files;
|
|
|
|
}
|
|
|
|
|
2004-10-26 00:12:21 +00:00
|
|
|
sub h_files($) {
|
2002-06-01 02:55:48 +00:00
|
|
|
my $self = shift;
|
2001-07-26 21:42:12 +00:00
|
|
|
|
|
|
|
my $h_files = \@{$self->{_H_FILES}};
|
2001-06-13 19:38:29 +00:00
|
|
|
|
2013-09-20 09:49:34 +00:00
|
|
|
if(!@$h_files) {
|
2001-07-26 21:42:12 +00:00
|
|
|
$self->parse_files;
|
|
|
|
}
|
|
|
|
|
|
|
|
return @$h_files;
|
|
|
|
}
|
2001-06-13 19:38:29 +00:00
|
|
|
|
2004-10-26 00:12:21 +00:00
|
|
|
sub directories($) {
|
2002-06-01 02:55:48 +00:00
|
|
|
my $self = shift;
|
2001-07-30 18:49:10 +00:00
|
|
|
|
|
|
|
my $directories = \@{$self->{_DIRECTORIES}};
|
|
|
|
|
2013-09-20 09:49:34 +00:00
|
|
|
if(!@$directories) {
|
2001-07-30 18:49:10 +00:00
|
|
|
$self->parse_files;
|
|
|
|
}
|
|
|
|
|
|
|
|
return @$directories;
|
|
|
|
}
|
|
|
|
|
2001-06-13 19:38:29 +00:00
|
|
|
1;
|