2 process command line, GNU style.
4 this is (Copyleft) 1996, Han-Wen Nienhuys, <hanwen@cs.uu.nl>
14 #include "getopt-long.hh"
15 #include "international.hh"
16 #include "string-convert.hh"
21 gettext (char const* s)
30 Getopt_long::argument_to_i ()
33 if (!optional_argument_ch_C_
34 || sscanf (optional_argument_ch_C_, "%ld", &l) != 1)
35 report (E_ILLEGALARG);
40 const Long_option_init *
41 Getopt_long::parselong ()
43 char const *optnm = arg_value_ch_a_a_[array_index_i_] + 2 ;
46 char const *endopt = strchr (optnm, '=');
47 int searchlen = (endopt) ? endopt - optnm : strlen (optnm);
50 for (int i=0; i< table_len_i_; i++)
52 char const *ln = option_a_[i].longname_sz_;
54 if (ln && !strncmp (ln, optnm, searchlen))
56 found_option_l_ = option_a_+i;
63 report (E_UNKNOWNOPTION);
67 argument_index_i_ = 0;
70 if (found_option_l_->take_arg_sz_)
73 optional_argument_ch_C_ = endopt +1; // a '='
76 optional_argument_ch_C_ = arg_value_ch_a_a_[array_index_i_];
79 if (!optional_argument_ch_C_)
85 optional_argument_ch_C_ = 0;
87 report (E_NOARGEXPECT);
90 return found_option_l_;
94 Long_option_init::str () const
98 str += "-" + shortname_ch_;
99 if (shortname_ch_ && longname_sz_)
102 str += String ("`--") + longname_sz_ + "'";
107 Long_option_init::str_for_help () const
111 s = "-" + to_str (shortname_ch_);
115 s = s + ((shortname_ch_ && longname_sz_) ? "," : " ");
118 s = s + "--" + longname_sz_;
127 s = s + gettext (take_arg_sz_);
132 // report an error, GNU style.
134 Getopt_long::report (Errorcod c)
137 if (!error_ostream_l_)
140 String str = arg_value_ch_a_a_[0];
145 str += _f ("option `%s' requires an argument",
146 found_option_l_->str ());
149 str += _f ("option `%s' doesn't allow an argument",
150 found_option_l_->str ());
152 case E_UNKNOWNOPTION:
153 str += _f ("unrecognized option: `%s'",
154 String (argument_index_i_
155 ? String ("-" + String_convert::form_str ("%c",
156 arg_value_ch_a_a_[array_index_i_][argument_index_i_]))
157 : String (arg_value_ch_a_a_[array_index_i_])));
160 str += _f ("invalid argument `%s' to option `%s'",
161 optional_argument_ch_C_, found_option_l_->str ());
166 *error_ostream_l_ << str << endl;
170 const Long_option_init *
171 Getopt_long::parseshort ()
173 char c=arg_value_ch_a_a_[array_index_i_][argument_index_i_];
177 for (int i=0; i < table_len_i_; i++)
178 if (option_a_[i].shortname_ch_ == c)
180 found_option_l_ = option_a_+i;
184 if (!found_option_l_)
186 report (E_UNKNOWNOPTION);
191 if (!found_option_l_->take_arg_sz_)
193 optional_argument_ch_C_ = 0;
194 return found_option_l_;
196 optional_argument_ch_C_ = arg_value_ch_a_a_[array_index_i_] + argument_index_i_;
199 argument_index_i_ = 0;
201 if (!optional_argument_ch_C_[0])
203 optional_argument_ch_C_ = arg_value_ch_a_a_[array_index_i_];
206 if (!optional_argument_ch_C_)
208 report (E_ARGEXPECT);
211 return found_option_l_;
214 const Long_option_init *
215 Getopt_long::operator () ()
224 if (argument_index_i_)
225 return parseshort ();
227 const char * argument_C = arg_value_ch_a_a_[array_index_i_];
229 if (argument_C[0] != '-')
232 if (argument_C[1] == '-') {// what to do with "command -- bla"
242 argument_index_i_ = 1;
243 return parseshort ();
254 Getopt_long::Getopt_long (int c, char **v, Long_option_init *lo)
257 error_ostream_l_ = &cerr;
258 arg_value_ch_a_a_ = v;
259 argument_count_i_ = c;
261 argument_index_i_ = 0;
263 // reached end of option table?
265 for (int i = 0; option_a_[i].longname_sz_ ||option_a_[i].shortname_ch_; i++)
271 Getopt_long::ok () const
273 return array_index_i_ < argument_count_i_;
280 while (array_index_i_ < argument_count_i_
281 && !arg_value_ch_a_a_[array_index_i_][argument_index_i_])
284 argument_index_i_ = 0;
289 Getopt_long::current_arg ()
291 if (array_index_i_ >= argument_count_i_)
293 char const * a = arg_value_ch_a_a_[array_index_i_];
294 return a + argument_index_i_;
298 Getopt_long::get_next_arg ()
300 char const * a = current_arg ();
304 argument_index_i_= 0;
310 const int EXTRA_SPACES = 5;
313 Long_option_init::table_str (Long_option_init *l)
315 String argstr = "ARG";
319 for (int i=0; l[i].shortname_ch_ || l[i].longname_sz_; i++)
321 wid = wid >? l[i].str_for_help ().length_i ();
324 for (int i=0; l[i].shortname_ch_ || l[i].longname_sz_; i++)
326 String s = " " + l[i].str_for_help ();
327 s += String_convert::char_str (' ', wid - s.length_i () + EXTRA_SPACES);
329 tabstr += s + gettext (l[i].help_sz_) + "\n";
337 Long_option_init::compare (Long_option_init const &a, Long_option_init const &b)
339 if (a.shortname_ch_ && b.shortname_ch_ && a.shortname_ch_- b.shortname_ch_)
340 return a.shortname_ch_ - b.shortname_ch_;
342 if (b.shortname_ch_ && a.longname_sz_)
344 char s[2] = {b.shortname_ch_, 0};
345 return strcmp (a.longname_sz_, s);
347 if (a.shortname_ch_ && b.longname_sz_)
349 char s[2] = {a.shortname_ch_, 0};
350 return strcmp (s, b.longname_sz_);
353 return strcmp (a.longname_sz_, b.longname_sz_);