2 process command line, GNU style.
4 this is (Copyleft) 1996, Han-Wen Nienhuys, <hanwen@cs.uu.nl>
11 #include "getopt-long.hh"
12 #include "international.hh"
13 #include "string-convert.hh"
17 gettext (char const* s)
26 Getopt_long::argument_to_i()
29 if (!optional_argument_ch_C_
30 || sscanf (optional_argument_ch_C_, "%ld", &l) != 1)
31 report (E_ILLEGALARG);
36 const Long_option_init *
37 Getopt_long::parselong()
39 char const *optnm = arg_value_ch_a_a_[array_index_i_] + 2 ;
42 char const *endopt = strchr (optnm, '=');
43 int searchlen = (endopt) ? endopt - optnm : strlen (optnm);
46 for (int i=0; i< table_len_i_; i++)
48 char const *ln = option_a_[i].longname_sz_;
50 if (ln && !strncmp (ln, optnm, searchlen))
52 found_option_l_ = option_a_+i;
59 report (E_UNKNOWNOPTION);
63 argument_index_i_ = 0;
66 if (found_option_l_->take_arg_sz_)
69 optional_argument_ch_C_ = endopt +1; // a '='
72 optional_argument_ch_C_ = arg_value_ch_a_a_[array_index_i_];
75 if (!optional_argument_ch_C_)
81 optional_argument_ch_C_ = 0;
83 report (E_NOARGEXPECT);
86 return found_option_l_;
90 Long_option_init::str () const
94 str += "-" + shortname_ch_;
95 if (shortname_ch_ && longname_sz_)
98 str += String ("`--") + longname_sz_ + "'";
103 Long_option_init::str_for_help () const
107 s = "-" + to_str (shortname_ch_);
111 s = s + ((shortname_ch_ && longname_sz_) ? "," : " ");
114 s = s + "--" + longname_sz_;
123 s = s + gettext (take_arg_sz_);
128 // report an error, GNU style.
130 Getopt_long::report (Errorcod c)
133 if (!error_ostream_l_)
136 String str = arg_value_ch_a_a_[0];
141 str += _f ("Option `%s' requires an argument",
142 found_option_l_->str ());
145 str += _f ("Option `%s' doesn't allow an argument",
146 found_option_l_->str ());
148 case E_UNKNOWNOPTION:
149 str += _f ("unrecognized option: `%s'",
150 String (argument_index_i_
151 ? String ("-" + String_convert::form_str ("%c",
152 arg_value_ch_a_a_[array_index_i_][argument_index_i_]))
153 : String (arg_value_ch_a_a_[array_index_i_])));
156 str += _f ("invalid argument `%s' to option `%s'",
157 optional_argument_ch_C_, found_option_l_->str ());
161 *error_ostream_l_ << str << endl;
165 const Long_option_init *
166 Getopt_long::parseshort()
168 char c=arg_value_ch_a_a_[array_index_i_][argument_index_i_];
172 for (int i=0; i < table_len_i_; i++)
173 if (option_a_[i].shortname_ch_ == c)
175 found_option_l_ = option_a_+i;
179 if (!found_option_l_)
181 report (E_UNKNOWNOPTION);
186 if (!found_option_l_->take_arg_sz_)
188 optional_argument_ch_C_ = 0;
189 return found_option_l_;
191 optional_argument_ch_C_ = arg_value_ch_a_a_[array_index_i_] + argument_index_i_;
194 argument_index_i_ = 0;
196 if (!optional_argument_ch_C_[0])
198 optional_argument_ch_C_ = arg_value_ch_a_a_[array_index_i_];
201 if (!optional_argument_ch_C_)
203 report (E_ARGEXPECT);
206 return found_option_l_;
209 const Long_option_init *
210 Getopt_long::operator()()
219 if (argument_index_i_)
222 const char * argument_C = arg_value_ch_a_a_[array_index_i_];
224 if (argument_C[0] != '-')
227 if (argument_C[1] == '-') {// what to do with "command -- bla"
237 argument_index_i_ = 1;
249 Getopt_long::Getopt_long (int c, char **v, Long_option_init *lo)
252 error_ostream_l_ = &cerr;
253 arg_value_ch_a_a_ = v;
254 argument_count_i_ = c;
256 argument_index_i_ = 0;
258 // reached end of option table?
260 for (int i = 0; option_a_[i].longname_sz_ ||option_a_[i].shortname_ch_; i++)
266 Getopt_long::ok() const
268 return array_index_i_ < argument_count_i_;
275 while (array_index_i_ < argument_count_i_
276 && !arg_value_ch_a_a_[array_index_i_][argument_index_i_])
279 argument_index_i_ = 0;
284 Getopt_long::current_arg()
286 if (array_index_i_ >= argument_count_i_)
288 char const * a = arg_value_ch_a_a_[array_index_i_];
289 return a + argument_index_i_;
293 Getopt_long::get_next_arg()
295 char const * a = current_arg();
299 argument_index_i_= 0;
305 const int EXTRA_SPACES = 5;
308 Long_option_init::table_str (Long_option_init *l)
310 String argstr = "ARG";
314 for (int i=0; l[i].shortname_ch_ || l[i].longname_sz_; i++)
316 wid = wid >? l[i].str_for_help ().length_i ();
319 for (int i=0; l[i].shortname_ch_ || l[i].longname_sz_; i++)
321 String s = " " + l[i].str_for_help ();
322 s += String_convert::char_str (' ', wid - s.length_i () + EXTRA_SPACES);
324 tabstr += s + gettext (l[i].help_sz_) + "\n";
332 Long_option_init::compare (Long_option_init const &a, Long_option_init const &b)
334 if (a.shortname_ch_ && b.shortname_ch_ && a.shortname_ch_- b.shortname_ch_)
335 return a.shortname_ch_ - b.shortname_ch_;
337 if (b.shortname_ch_ && a.longname_sz_)
339 char s[2] = {b.shortname_ch_, 0};
340 return strcmp (a.longname_sz_, s);
342 if (a.shortname_ch_ && b.longname_sz_)
344 char s[2] = {a.shortname_ch_, 0};
345 return strcmp (s, b.longname_sz_);
348 return strcmp (a.longname_sz_, b.longname_sz_);