source: gsdl/trunk/perllib/parsargv.pm@ 14374

Last change on this file since 14374 was 8716, checked in by kjdon, 19 years ago

added some changes made by Emanuel Dejanu (Simple Words)

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 5.6 KB
Line 
1###########################################################################
2#
3# parseargv.pm --
4# A component of the Greenstone digital library software
5# from the New Zealand Digital Library Project at the
6# University of Waikato, New Zealand.
7#
8# Copyright (C) 1999 New Zealand Digital Library Project
9#
10# This program is free software; you can redistribute it and/or modify
11# it under the terms of the GNU General Public License as published by
12# the Free Software Foundation; either version 2 of the License, or
13# (at your option) any later version.
14#
15# This program is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with this program; if not, write to the Free Software
22# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23#
24###########################################################################
25
26package parsargv;
27#
28# parse(ARGVREF, [SPEC, VARREF] ...)
29#
30# Parse command line arguments.
31#
32# ARGVREF is an array reference, usually to @ARGV. The remaining
33# arguments are paired (SPEC, VARREF). SPEC is a specification string
34# for a particular argument; VARREF is a variable reference that will
35# receive the argument.
36#
37# SPEC is in one of the following forms:
38#
39# ARG/REGEX/DEFAULT ARG is the name of command line argument. REGEX is
40# a regular expression that gives legal values for the argument.
41# DEFAULT is the default value assigned to VARREF if the option does
42# not appear on the command line. Example
43#
44#
45# ARG/REGEX ARG and REGEX are as above. Since no default is given, ARG
46# must appear on the command line; if it doesn't, parse() returns 0.
47#
48# ARG ARG is as above. ARG is a boolean option. VARREF is assigned 0 if ARG
49# is not on the command line; 1 otherwise.
50#
51# SPEC may start with a punctuation character, in which case this
52# character will be used instead of '/' as a delimiter. Useful when '/'
53# is needed in the REGEX part.
54#
55# VARREF is a reference to a scalar or an array. If VARREF is an array
56# reference, then multiple command line options are allowed an append. Example:
57#
58# Command line: -day mon -day fri
59#
60# parse(\@ARGV, "day/(mon|tue|wed|thu|fri)", \@days)
61#
62# days => ('mon', 'fri')
63#
64# Returns 0 if there was an error, nonzero otherwise.
65#
66
67
68sub parse
69{
70 my $arglist = shift;
71 my ($spec, $var);
72 my %option;
73
74 my @rest = @_;
75
76
77 # if the last argument is the string "allow_extra_options" then options
78 # in \@rest without a corresponding SPEC will be ignored (i.e. the "$arg is
79 # not a valid option" error won't occur)\n";
80 my $allow_extra_options = pop @rest;
81 if (defined ($allow_extra_options)) {
82 if ($allow_extra_options eq "allow_extra_options") {
83 $allow_extra_options = 1;
84 } else {
85 # put it back where we got it
86 push (@rest, $allow_extra_options);
87 $allow_extra_options = 0;
88 }
89 } else {
90 $allow_extra_options = 0;
91 }
92
93 while (($spec, $var) = splice(@rest, 0, 2))
94 {
95
96 die "Variable for $spec is not a valid type."
97 unless ref($var) eq 'SCALAR' || ref($var) eq 'ARRAY'
98 || (ref($var) eq 'REF' && ref($$var) eq 'GLOB');
99
100 my $delimiter;
101 if ($spec !~ /^\w/)
102 {
103 $delimiter = substr($spec, 0, 1);
104 $spec = substr($spec, 1);
105 }
106 else
107 {
108 $delimiter = '/';
109 }
110 my ($name, $regex, $default) = split(/$delimiter/, $spec, 3);
111
112
113 if ($name)
114 {
115 if ($default && $default !~ /$regex/)
116 {
117 die "Default value for $name doesn't match regex ($spec).";
118 }
119 $option{$name} = {'name' => $name,
120 'regex' => $regex,
121 'default' => $default,
122 'varref' => $var,
123 'set' => 0};
124 }
125 else
126 {
127 die "Invalid argument ($spec) for parsargv.";
128 }
129 }
130
131 my @argv;
132 my $arg;
133 my $parse_options = 1;
134 my $errors = 0;
135
136 while ($arg = shift(@$arglist))
137 {
138 if ($parse_options && $arg eq '--')
139 {
140 $parse_options = 0;
141 next;
142 }
143
144 if ($parse_options && $arg =~ /^-+\w/)
145 {
146 $arg =~ s/^-+//;
147
148 if (defined $option{$arg})
149 {
150 &process_arg($option{$arg}, $arglist, \$errors);
151 }
152 elsif (!$allow_extra_options)
153 {
154 print STDOUT "$arg is not a valid option.\n";
155 $errors++;
156 }
157 }
158 else
159 {
160 push(@argv, $arg);
161 }
162 }
163 @$arglist = @argv;
164
165 foreach $arg (keys %option)
166 {
167 if ($option{$arg}->{'set'} == 0)
168 {
169 if (defined $option{$arg}->{'default'})
170 {
171 &set_var($option{$arg}, $option{$arg}->{'default'});
172 }
173 elsif (!$option{$arg}->{'regex'})
174 {
175 &set_var($option{$arg}, 0)
176 }
177 elsif (ref($option{$arg}->{'varref'}) ne 'ARRAY')
178 {
179 print STDOUT "Missing command line argument -$arg.\n";
180 $errors++;
181 }
182 }
183 }
184 return $errors == 0;
185}
186
187sub process_arg
188{
189 my ($option, $arglist, $errors) = @_;
190
191 if ($option->{'regex'} && @$arglist > 0 && $arglist->[0] !~ /^-+\w/)
192 {
193 if ($arglist->[0] =~ /$option->{'regex'}/)
194 {
195 &set_var($option, shift(@$arglist));
196 }
197 else
198 {
199 print STDOUT "Bad value for -$option->{'name'} argument.\n";
200 $$errors++;
201 }
202 }
203 elsif (!$option->{'regex'})
204 {
205 &set_var($option, 1);
206 }
207 else
208 {
209 print STDOUT "No value given for -$option->{'name'}.\n";
210 $$errors++;
211 }
212}
213
214sub set_var
215{
216 my ($option, $value) = @_;
217 my $type = ref($option->{'varref'});
218
219 if ($type eq 'SCALAR')
220 {
221 ${$option->{'varref'}} = $value;
222 }
223 elsif ($type eq 'ARRAY')
224 {
225 push(@{$option->{'varref'}}, $value);
226 }
227 $option->{'set'} = 1;
228}
229
2301;
231
232
233
234
235
236
237
238
Note: See TracBrowser for help on using the repository browser.