2 process command line, GNU style.
4 this is (Copyleft) 1996, Han-Wen Nienhuys, <hanwen@cs.uu.nl>
15 #include "getopt-long.hh"
16 #include "international.hh"
17 #include "string-convert.hh"
22 gettext (char const* s)
31 Getopt_long::argument_to_i ()
34 if (!optional_argument_ch_C_
35 || sscanf (optional_argument_ch_C_, "%ld", &l) != 1)
36 report (E_ILLEGALARG);
41 const Long_option_init *
42 Getopt_long::parselong ()
44 char const *optnm = arg_value_ch_a_a_[array_index_i_] + 2 ;
47 char const *endopt = strchr (optnm, '=');
48 int searchlen = (endopt) ? endopt - optnm : strlen (optnm);
51 for (int i=0; i< table_len_i_; i++)
53 char const *ln = option_a_[i].longname_sz_;
55 if (ln && !strncmp (ln, optnm, searchlen))
57 found_option_l_ = option_a_+i;
64 report (E_UNKNOWNOPTION);
68 argument_index_i_ = 0;
71 if (found_option_l_->take_arg_sz_)
74 optional_argument_ch_C_ = endopt +1; // a '='
77 optional_argument_ch_C_ = arg_value_ch_a_a_[array_index_i_];
80 if (!optional_argument_ch_C_)
86 optional_argument_ch_C_ = 0;
88 report (E_NOARGEXPECT);
91 return found_option_l_;
95 Long_option_init::str () const
99 str += "-" + shortname_ch_;
100 if (shortname_ch_ && longname_sz_)
103 str += String ("`--") + longname_sz_ + "'";
108 Long_option_init::str_for_help () const
112 s = "-" + to_str (shortname_ch_);
116 s = s + ((shortname_ch_ && longname_sz_) ? "," : " ");
119 s = s + "--" + longname_sz_;
128 s = s + gettext (take_arg_sz_);
133 // report an error, GNU style.
135 Getopt_long::report (Errorcod c)
141 String str = arg_value_ch_a_a_[0];
146 str += _f ("option `%s' requires an argument",
147 found_option_l_->str ());
150 str += _f ("option `%s' doesn't allow an argument",
151 found_option_l_->str ());
153 case E_UNKNOWNOPTION:
154 str += _f ("unrecognized option: `%s'",
155 String (argument_index_i_
156 ? String ("-" + String_convert::form_str ("%c",
157 arg_value_ch_a_a_[array_index_i_][argument_index_i_]))
158 : String (arg_value_ch_a_a_[array_index_i_])));
161 str += _f ("invalid argument `%s' to option `%s'",
162 optional_argument_ch_C_, found_option_l_->str ());
167 fprintf(error_out_, "%s\n", str.ch_C());
171 const Long_option_init *
172 Getopt_long::parseshort ()
174 char c=arg_value_ch_a_a_[array_index_i_][argument_index_i_];
178 for (int i=0; i < table_len_i_; i++)
179 if (option_a_[i].shortname_ch_ == c)
181 found_option_l_ = option_a_+i;
185 if (!found_option_l_)
187 report (E_UNKNOWNOPTION);
192 if (!found_option_l_->take_arg_sz_)
194 optional_argument_ch_C_ = 0;
195 return found_option_l_;
197 optional_argument_ch_C_ = arg_value_ch_a_a_[array_index_i_] + argument_index_i_;
200 argument_index_i_ = 0;
202 if (!optional_argument_ch_C_[0])
204 optional_argument_ch_C_ = arg_value_ch_a_a_[array_index_i_];
207 if (!optional_argument_ch_C_)
209 report (E_ARGEXPECT);
212 return found_option_l_;
215 const Long_option_init *
216 Getopt_long::operator () ()
225 if (argument_index_i_)
226 return parseshort ();
228 const char * argument_C = arg_value_ch_a_a_[array_index_i_];
230 if (argument_C[0] != '-')
233 if (argument_C[1] == '-') {// what to do with "command -- bla"
243 argument_index_i_ = 1;
244 return parseshort ();
255 Getopt_long::Getopt_long (int c, char **v, Long_option_init *lo)
259 arg_value_ch_a_a_ = v;
260 argument_count_i_ = c;
262 argument_index_i_ = 0;
264 // reached end of option table?
266 for (int i = 0; option_a_[i].longname_sz_ ||option_a_[i].shortname_ch_; i++)
272 Getopt_long::ok () const
274 return array_index_i_ < argument_count_i_;
281 while (array_index_i_ < argument_count_i_
282 && !arg_value_ch_a_a_[array_index_i_][argument_index_i_])
285 argument_index_i_ = 0;
290 Getopt_long::current_arg ()
292 if (array_index_i_ >= argument_count_i_)
294 char const * a = arg_value_ch_a_a_[array_index_i_];
295 return a + argument_index_i_;
299 Getopt_long::get_next_arg ()
301 char const * a = current_arg ();
305 argument_index_i_= 0;
311 const int EXTRA_SPACES = 5;
314 Long_option_init::table_str (Long_option_init *l)
316 String argstr = "ARG";
320 for (int i=0; l[i].shortname_ch_ || l[i].longname_sz_; i++)
322 wid = wid >? l[i].str_for_help ().length_i ();
325 for (int i=0; l[i].shortname_ch_ || l[i].longname_sz_; i++)
327 String s = " " + l[i].str_for_help ();
328 s += String_convert::char_str (' ', wid - s.length_i () + EXTRA_SPACES);
330 tabstr += s + gettext (l[i].help_sz_) + "\n";
338 Long_option_init::compare (Long_option_init const &a, Long_option_init const &b)
340 if (a.shortname_ch_ && b.shortname_ch_ && a.shortname_ch_- b.shortname_ch_)
341 return a.shortname_ch_ - b.shortname_ch_;
343 if (b.shortname_ch_ && a.longname_sz_)
345 char s[2] = {b.shortname_ch_, 0};
346 return strcmp (a.longname_sz_, s);
348 if (a.shortname_ch_ && b.longname_sz_)
350 char s[2] = {a.shortname_ch_, 0};
351 return strcmp (s, b.longname_sz_);
354 return strcmp (a.longname_sz_, b.longname_sz_);