lilypond-1.3.141
[lilypond.git] / flower / getopt-long.cc
blob8e210efe2006bba701020b0ab3b76b8ecbfcd65f
1 /*
2 process command line, GNU style.
4 this is (Copyleft) 1996, Han-Wen Nienhuys, <hanwen@cs.uu.nl>
5 */
7 #include <string.h>
8 #include <stdio.h>
9 #include <iostream.h>
10 #include <assert.h>
11 #include <stdlib.h>
13 #include "config.h"
14 #include "getopt-long.hh"
15 #include "international.hh"
16 #include "string-convert.hh"
19 #if !HAVE_GETTEXT
20 inline char*
21 gettext (char const* s)
23 return (char*)s;
25 #else
26 #include <libintl.h>
27 #endif
29 long
30 Getopt_long::argument_to_i ()
32 long l;
33 if (!optional_argument_ch_C_
34 || sscanf (optional_argument_ch_C_, "%ld", &l) != 1)
35 report (E_ILLEGALARG);
37 return l;
40 const Long_option_init *
41 Getopt_long::parselong ()
43 char const *optnm = arg_value_ch_a_a_[array_index_i_] + 2 ;
44 assert (*optnm);
46 char const *endopt = strchr (optnm, '=');
47 int searchlen = (endopt) ? endopt - optnm : strlen (optnm);
49 found_option_l_=0;
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;
57 break;
61 if (!found_option_l_)
63 report (E_UNKNOWNOPTION);
64 return 0;
66 array_index_i_++;
67 argument_index_i_ = 0;
70 if (found_option_l_->take_arg_sz_)
72 if (endopt)
73 optional_argument_ch_C_ = endopt +1; // a '='
74 else
76 optional_argument_ch_C_ = arg_value_ch_a_a_[array_index_i_];
77 array_index_i_++;
79 if (!optional_argument_ch_C_)
80 report (E_ARGEXPECT);
83 else
85 optional_argument_ch_C_ = 0;
86 if (endopt)
87 report (E_NOARGEXPECT);
90 return found_option_l_;
93 String
94 Long_option_init::str () const
96 String str;
97 if (shortname_ch_)
98 str += "-" + shortname_ch_;
99 if (shortname_ch_ && longname_sz_)
100 str += ", ";
101 if (longname_sz_)
102 str += String ("`--") + longname_sz_ + "'";
103 return str;
106 String
107 Long_option_init::str_for_help () const
109 String s;
110 if (shortname_ch_)
111 s = "-" + to_str (shortname_ch_);
112 else
113 s = " ";
115 s = s + ((shortname_ch_ && longname_sz_) ? "," : " ");
117 if (longname_sz_)
118 s = s + "--" + longname_sz_;
120 if (take_arg_sz_)
122 if (longname_sz_)
123 s = s + "=";
124 else
125 s = s + " ";
127 s = s + gettext (take_arg_sz_);
129 return s;
132 // report an error, GNU style.
133 void
134 Getopt_long::report (Errorcod c)
136 error_ = c;
137 if (!error_ostream_l_)
138 return;
140 String str = arg_value_ch_a_a_[0];
141 str += ": ";
142 switch (c)
144 case E_ARGEXPECT:
145 str += _f ("option `%s' requires an argument",
146 found_option_l_->str ());
147 break;
148 case E_NOARGEXPECT:
149 str += _f ("option `%s' doesn't allow an argument",
150 found_option_l_->str ());
151 break;
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_])));
158 break;
159 case E_ILLEGALARG:
160 str += _f ("invalid argument `%s' to option `%s'",
161 optional_argument_ch_C_, found_option_l_->str ());
162 break;
163 default:
164 assert (false);
166 *error_ostream_l_ << str << endl;
167 exit (2);
170 const Long_option_init *
171 Getopt_long::parseshort ()
173 char c=arg_value_ch_a_a_[array_index_i_][argument_index_i_];
174 found_option_l_=0;
175 assert (c);
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;
181 break;
184 if (!found_option_l_)
186 report (E_UNKNOWNOPTION);
187 return 0;
190 argument_index_i_++;
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_;
198 array_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_];
204 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 () ()
217 if (!ok ())
218 return 0;
220 next ();
221 if (!ok ())
222 return 0;
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] != '-')
230 return 0;
232 if (argument_C[1] == '-') {// what to do with "command -- bla"
233 if (argument_C[2])
234 return parselong ();
235 else
236 return 0;
238 else
240 if (argument_C[ 1 ])
242 argument_index_i_ = 1;
243 return parseshort ();
245 else
247 return 0;
254 Getopt_long::Getopt_long (int c, char **v, Long_option_init *lo)
256 option_a_ = lo;
257 error_ostream_l_ = &cerr;
258 arg_value_ch_a_a_ = v;
259 argument_count_i_ = c;
260 array_index_i_ = 1;
261 argument_index_i_ = 0;
263 // reached end of option table?
264 table_len_i_ =0;
265 for (int i = 0; option_a_[i].longname_sz_ ||option_a_[i].shortname_ch_; i++)
266 table_len_i_ ++;
270 bool
271 Getopt_long::ok () const
273 return array_index_i_ < argument_count_i_;
276 void
277 Getopt_long::next ()
279 error_ = E_NOERROR;
280 while (array_index_i_ < argument_count_i_
281 && !arg_value_ch_a_a_[array_index_i_][argument_index_i_])
283 array_index_i_++;
284 argument_index_i_ = 0;
288 char const *
289 Getopt_long::current_arg ()
291 if (array_index_i_ >= argument_count_i_)
292 return 0;
293 char const * a = arg_value_ch_a_a_[array_index_i_];
294 return a + argument_index_i_;
297 char const *
298 Getopt_long::get_next_arg ()
300 char const * a = current_arg ();
301 if (a)
303 array_index_i_ ++;
304 argument_index_i_= 0;
306 return a;
310 const int EXTRA_SPACES = 5;
312 String
313 Long_option_init::table_str (Long_option_init *l)
315 String argstr = "ARG";
316 String tabstr = "";
318 int wid = 0;
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";
333 return tabstr;
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_);