2 process command line, GNU style.
4 this is Copyleft (c) 1996--2006 Han-Wen Nienhuys, <hanwen@xs4all.nl>
7 #include "getopt-long.hh"
14 #include "international.hh"
15 #include "std-string.hh"
19 gettext (char const *s)
28 Getopt_long::get_argument_index ()
31 if (!optional_argument_str0_
32 || sscanf (optional_argument_str0_, "%ld", &l) != 1)
33 report (E_ILLEGALARG);
38 const Long_option_init *
39 Getopt_long::parselong ()
41 char const *optnm = arg_value_char_a_a_[array_index_] + 2;
44 char const *endopt = strchr (optnm, '=');
45 int searchlen = (endopt) ? endopt - optnm : strlen (optnm);
48 for (int i = 0; i < table_len_; i++)
50 char const *ln = option_a_[i].longname_str0_;
52 if (ln && !strncmp (ln, optnm, searchlen))
54 found_option_ = option_a_ + i;
61 report (E_UNKNOWNOPTION);
67 if (found_option_->take_arg_str0_)
70 optional_argument_str0_ = endopt +1; // a '='
73 optional_argument_str0_ = arg_value_char_a_a_[array_index_];
76 if (!optional_argument_str0_)
81 optional_argument_str0_ = 0;
83 report (E_NOARGEXPECT);
90 Long_option_init::to_string () const
94 str += "-" + shortname_char_;
95 if (shortname_char_ && longname_str0_)
98 str += string ("`--") + longname_str0_ + "'";
103 Long_option_init::str_for_help () const
107 s = "-" + ::to_string (shortname_char_);
111 s = s + ((shortname_char_ && longname_str0_) ? ", " : " ");
114 s = s + "--" + longname_str0_;
123 s = s + gettext (take_arg_str0_);
128 // report an error, GNU style.
130 Getopt_long::report (Errorcod c)
136 string str = arg_value_char_a_a_[0];
141 str += _f ("option `%s' requires an argument",
142 found_option_->to_string ());
145 str += _f ("option `%s' doesn't allow an argument",
146 found_option_->to_string ());
148 case E_UNKNOWNOPTION:
149 str += _f ("unrecognized option: `%s'",
150 string (argument_index_
151 ? string ("-" + string (1, arg_value_char_a_a_[array_index_][argument_index_]))
152 : string (arg_value_char_a_a_[array_index_])));
155 str += _f ("invalid argument `%s' to option `%s'",
156 optional_argument_str0_, found_option_->to_string ());
161 fprintf (error_out_, "%s\n", str.c_str ());
165 const Long_option_init *
166 Getopt_long::parseshort ()
168 char c = arg_value_char_a_a_[array_index_][argument_index_];
172 for (int i = 0; i < table_len_; i++)
173 if (option_a_[i].shortname_char_ == c)
175 found_option_ = option_a_ + i;
181 report (E_UNKNOWNOPTION);
186 if (!found_option_->take_arg_str0_)
188 optional_argument_str0_ = 0;
189 return found_option_;
191 optional_argument_str0_ = arg_value_char_a_a_[array_index_] + argument_index_;
196 if (!optional_argument_str0_[0])
198 optional_argument_str0_ = arg_value_char_a_a_[array_index_];
201 if (!optional_argument_str0_)
202 report (E_ARGEXPECT);
204 return found_option_;
207 const Long_option_init *
208 Getopt_long::operator () ()
218 return parseshort ();
220 char const *argument = arg_value_char_a_a_[array_index_];
222 if (argument[0] != '-')
225 if (argument[1] == '-') {// what to do with "command -- bla"
236 return parseshort ();
243 Getopt_long::Getopt_long (int c, char **v, Long_option_init *lo)
247 arg_value_char_a_a_ = v;
252 // reached end of option table?
254 for (int i = 0; option_a_[i].longname_str0_ || option_a_[i].shortname_char_; i++)
259 Getopt_long::ok () const
261 return array_index_ < argument_count_;
268 while (array_index_ < argument_count_
269 && !arg_value_char_a_a_[array_index_][argument_index_])
277 Getopt_long::current_arg ()
279 if (array_index_ >= argument_count_)
281 char const *a = arg_value_char_a_a_[array_index_];
282 return a + argument_index_;
286 Getopt_long::get_next_arg ()
288 char const *a = current_arg ();
297 const int EXTRA_SPACES = 5;
300 Long_option_init::table_string (Long_option_init *l)
305 for (int i = 0; l[i].shortname_char_ || l[i].longname_str0_; i++)
306 wid = max (int(wid), int(l[i].str_for_help ().length ()));
308 for (int i = 0; l[i].shortname_char_ || l[i].longname_str0_; i++)
310 string s = " " + l[i].str_for_help ();
311 s += string (wid - s.length () + EXTRA_SPACES, ' ');
313 string help_text (gettext (l[i].help_str0_));
314 replace_all (help_text, "\n",
315 "\n" + string (wid + EXTRA_SPACES + 2, ' '));
316 tabstr += s + help_text + "\n";
323 Long_option_init::compare (Long_option_init const &a, Long_option_init const &b)
325 if (a.shortname_char_ && b.shortname_char_ && a.shortname_char_- b.shortname_char_)
326 return a.shortname_char_ - b.shortname_char_;
328 if (b.shortname_char_ && a.longname_str0_)
330 char s[2] = {b.shortname_char_, 0};
331 return strcmp (a.longname_str0_, s);
333 if (a.shortname_char_ && b.longname_str0_)
335 char s[2] = {a.shortname_char_, 0};
336 return strcmp (s, b.longname_str0_);
339 return strcmp (a.longname_str0_, b.longname_str0_);