2 process command line, GNU style.
4 this is (Copyleft) 1996, Han-Wen Nienhuys, <hanwen@cs.uu.nl>
12 #include "getopt-long.hh"
13 #include "international.hh"
14 #include "string-convert.hh"
19 gettext (char const* s)
28 Getopt_long::argument_to_i()
31 if (!optional_argument_ch_C_
32 || sscanf (optional_argument_ch_C_, "%ld", &l) != 1)
33 report (E_ILLEGALARG);
38 const Long_option_init *
39 Getopt_long::parselong()
41 char const *optnm = arg_value_ch_a_a_[array_index_i_] + 2 ;
44 char const *endopt = strchr (optnm, '=');
45 int searchlen = (endopt) ? endopt - optnm : strlen (optnm);
48 for (int i=0; i< table_len_i_; i++)
50 char const *ln = option_a_[i].longname_sz_;
52 if (ln && !strncmp (ln, optnm, searchlen))
54 found_option_l_ = option_a_+i;
61 report (E_UNKNOWNOPTION);
65 argument_index_i_ = 0;
68 if (found_option_l_->take_arg_sz_)
71 optional_argument_ch_C_ = endopt +1; // a '='
74 optional_argument_ch_C_ = arg_value_ch_a_a_[array_index_i_];
77 if (!optional_argument_ch_C_)
83 optional_argument_ch_C_ = 0;
85 report (E_NOARGEXPECT);
88 return found_option_l_;
92 Long_option_init::str () const
96 str += "-" + shortname_ch_;
97 if (shortname_ch_ && longname_sz_)
100 str += String ("`--") + longname_sz_ + "'";
105 Long_option_init::str_for_help () const
109 s = "-" + to_str (shortname_ch_);
113 s = s + ((shortname_ch_ && longname_sz_) ? "," : " ");
116 s = s + "--" + longname_sz_;
125 s = s + gettext (take_arg_sz_);
130 // report an error, GNU style.
132 Getopt_long::report (Errorcod c)
135 if (!error_ostream_l_)
138 String str = arg_value_ch_a_a_[0];
143 str += _f ("Option `%s' requires an argument",
144 found_option_l_->str ());
147 str += _f ("Option `%s' doesn't allow an argument",
148 found_option_l_->str ());
150 case E_UNKNOWNOPTION:
151 str += _f ("unrecognized option: `%s'",
152 String (argument_index_i_
153 ? String ("-" + String_convert::form_str ("%c",
154 arg_value_ch_a_a_[array_index_i_][argument_index_i_]))
155 : String (arg_value_ch_a_a_[array_index_i_])));
158 str += _f ("invalid argument `%s' to option `%s'",
159 optional_argument_ch_C_, found_option_l_->str ());
163 *error_ostream_l_ << str << endl;
167 const Long_option_init *
168 Getopt_long::parseshort()
170 char c=arg_value_ch_a_a_[array_index_i_][argument_index_i_];
174 for (int i=0; i < table_len_i_; i++)
175 if (option_a_[i].shortname_ch_ == c)
177 found_option_l_ = option_a_+i;
181 if (!found_option_l_)
183 report (E_UNKNOWNOPTION);
188 if (!found_option_l_->take_arg_sz_)
190 optional_argument_ch_C_ = 0;
191 return found_option_l_;
193 optional_argument_ch_C_ = arg_value_ch_a_a_[array_index_i_] + argument_index_i_;
196 argument_index_i_ = 0;
198 if (!optional_argument_ch_C_[0])
200 optional_argument_ch_C_ = arg_value_ch_a_a_[array_index_i_];
203 if (!optional_argument_ch_C_)
205 report (E_ARGEXPECT);
208 return found_option_l_;
211 const Long_option_init *
212 Getopt_long::operator()()
221 if (argument_index_i_)
224 const char * argument_C = arg_value_ch_a_a_[array_index_i_];
226 if (argument_C[0] != '-')
229 if (argument_C[1] == '-') {// what to do with "command -- bla"
239 argument_index_i_ = 1;
251 Getopt_long::Getopt_long (int c, char **v, Long_option_init *lo)
254 error_ostream_l_ = &cerr;
255 arg_value_ch_a_a_ = v;
256 argument_count_i_ = c;
258 argument_index_i_ = 0;
260 // reached end of option table?
262 for (int i = 0; option_a_[i].longname_sz_ ||option_a_[i].shortname_ch_; i++)
268 Getopt_long::ok() const
270 return array_index_i_ < argument_count_i_;
277 while (array_index_i_ < argument_count_i_
278 && !arg_value_ch_a_a_[array_index_i_][argument_index_i_])
281 argument_index_i_ = 0;
286 Getopt_long::current_arg()
288 if (array_index_i_ >= argument_count_i_)
290 char const * a = arg_value_ch_a_a_[array_index_i_];
291 return a + argument_index_i_;
295 Getopt_long::get_next_arg()
297 char const * a = current_arg();
301 argument_index_i_= 0;
307 const int EXTRA_SPACES = 5;
310 Long_option_init::table_str (Long_option_init *l)
312 String argstr = "ARG";
316 for (int i=0; l[i].shortname_ch_ || l[i].longname_sz_; i++)
318 wid = wid >? l[i].str_for_help ().length_i ();
321 for (int i=0; l[i].shortname_ch_ || l[i].longname_sz_; i++)
323 String s = " " + l[i].str_for_help ();
324 s += String_convert::char_str (' ', wid - s.length_i () + EXTRA_SPACES);
326 tabstr += s + gettext (l[i].help_sz_) + "\n";
334 Long_option_init::compare (Long_option_init const &a, Long_option_init const &b)
336 if (a.shortname_ch_ && b.shortname_ch_ && a.shortname_ch_- b.shortname_ch_)
337 return a.shortname_ch_ - b.shortname_ch_;
339 if (b.shortname_ch_ && a.longname_sz_)
341 char s[2] = {b.shortname_ch_, 0};
342 return strcmp (a.longname_sz_, s);
344 if (a.shortname_ch_ && b.longname_sz_)
346 char s[2] = {a.shortname_ch_, 0};
347 return strcmp (s, b.longname_sz_);
350 return strcmp (a.longname_sz_, b.longname_sz_);