release commit
[lilypond.git] / flower / getopt-long.cc
blob643527c91a679247199722e5f6f9ced65531216f
1 /*
2 process command line, GNU style.
4 this is Copyleft (c) 1996--2004 Han-Wen Nienhuys, <hanwen@cs.uu.nl>
5 */
7 #include <string.h>
8 #include <stdio.h>
9 #include <assert.h>
10 #include <stdlib.h>
12 #include <iostream>
14 #include "config.h"
15 #include "getopt-long.hh"
16 #include "international.hh"
17 #include "string-convert.hh"
20 #if !HAVE_GETTEXT
21 inline char*
22 gettext (char const* s)
24 return (char*)s;
26 #else
27 #include <libintl.h>
28 #endif
30 long
31 Getopt_long::get_argument_index ()
33 long l;
34 if (!optional_argument_str0_
35 || sscanf (optional_argument_str0_, "%ld", &l) != 1)
36 report (E_ILLEGALARG);
38 return l;
41 const Long_option_init *
42 Getopt_long::parselong ()
44 char const *optnm = arg_value_char_a_a_[array_index_] + 2 ;
45 assert (*optnm);
47 char const *endopt = strchr (optnm, '=');
48 int searchlen = (endopt) ? endopt - optnm : strlen (optnm);
50 found_option_=0;
51 for (int i=0; i< table_len_; i++)
53 char const *ln = option_a_[i].longname_str0_;
55 if (ln && !strncmp (ln, optnm, searchlen))
57 found_option_ = option_a_+i;
58 break;
62 if (!found_option_)
64 report (E_UNKNOWNOPTION);
65 return 0;
67 array_index_++;
68 argument_index_ = 0;
71 if (found_option_->take_arg_str0_)
73 if (endopt)
74 optional_argument_str0_ = endopt +1; // a '='
75 else
77 optional_argument_str0_ = arg_value_char_a_a_[array_index_];
78 array_index_++;
80 if (!optional_argument_str0_)
81 report (E_ARGEXPECT);
84 else
86 optional_argument_str0_ = 0;
87 if (endopt)
88 report (E_NOARGEXPECT);
91 return found_option_;
94 String
95 Long_option_init::to_string () const
97 String str;
98 if (shortname_char_)
99 str += "-" + shortname_char_;
100 if (shortname_char_ && longname_str0_)
101 str += ", ";
102 if (longname_str0_)
103 str += String ("`--") + longname_str0_ + "'";
104 return str;
107 String
108 Long_option_init::str_for_help () const
110 String s;
111 if (shortname_char_)
112 s = "-" + ::to_string (shortname_char_);
113 else
114 s = " ";
116 s = s + ((shortname_char_ && longname_str0_) ? ", " : " ");
118 if (longname_str0_)
119 s = s + "--" + longname_str0_;
121 if (take_arg_str0_)
123 if (longname_str0_)
124 s = s + "=";
125 else
126 s = s + " ";
128 s = s + gettext (take_arg_str0_);
130 return s;
133 // report an error, GNU style.
134 void
135 Getopt_long::report (Errorcod c)
137 error_ = c;
138 if (!error_out_)
139 return;
141 String str = arg_value_char_a_a_[0];
142 str += ": ";
143 switch (c)
145 case E_ARGEXPECT:
146 str += _f ("option `%s' requires an argument",
147 found_option_->to_string ());
148 break;
149 case E_NOARGEXPECT:
150 str += _f ("option `%s' doesn't allow an argument",
151 found_option_->to_string ());
152 break;
153 case E_UNKNOWNOPTION:
154 str += _f ("unrecognized option: `%s'",
155 String (argument_index_
156 ? String ("-" + String_convert::form_string ("%c",
157 arg_value_char_a_a_[array_index_][argument_index_]))
158 : String (arg_value_char_a_a_[array_index_])));
159 break;
160 case E_ILLEGALARG:
161 str += _f ("invalid argument `%s' to option `%s'",
162 optional_argument_str0_, found_option_->to_string ());
163 break;
164 default:
165 assert (false);
167 fprintf(error_out_, "%s\n", str.to_str0 ());
168 exit (2);
171 const Long_option_init *
172 Getopt_long::parseshort ()
174 char c=arg_value_char_a_a_[array_index_][argument_index_];
175 found_option_=0;
176 assert (c);
178 for (int i=0; i < table_len_; i++)
179 if (option_a_[i].shortname_char_ == c)
181 found_option_ = option_a_+i;
182 break;
185 if (!found_option_)
187 report (E_UNKNOWNOPTION);
188 return 0;
191 argument_index_++;
192 if (!found_option_->take_arg_str0_)
194 optional_argument_str0_ = 0;
195 return found_option_;
197 optional_argument_str0_ = arg_value_char_a_a_[array_index_] + argument_index_;
199 array_index_ ++;
200 argument_index_ = 0;
202 if (!optional_argument_str0_[0])
204 optional_argument_str0_ = arg_value_char_a_a_[array_index_];
205 array_index_ ++;
207 if (!optional_argument_str0_)
209 report (E_ARGEXPECT);
212 return found_option_;
215 const Long_option_init *
216 Getopt_long::operator () ()
218 if (!ok ())
219 return 0;
221 next ();
222 if (!ok ())
223 return 0;
225 if (argument_index_)
226 return parseshort ();
228 const char * argument = arg_value_char_a_a_[array_index_];
230 if (argument[0] != '-')
231 return 0;
233 if (argument[1] == '-') {// what to do with "command -- bla"
234 if (argument[2])
235 return parselong ();
236 else
237 return 0;
239 else
241 if (argument[ 1 ])
243 argument_index_ = 1;
244 return parseshort ();
246 else
248 return 0;
255 Getopt_long::Getopt_long (int c, char **v, Long_option_init *lo)
257 option_a_ = lo;
258 error_out_ = stderr;
259 arg_value_char_a_a_ = v;
260 argument_count_ = c;
261 array_index_ = 1;
262 argument_index_ = 0;
264 // reached end of option table?
265 table_len_ =0;
266 for (int i = 0; option_a_[i].longname_str0_ ||option_a_[i].shortname_char_; i++)
267 table_len_ ++;
271 bool
272 Getopt_long::ok () const
274 return array_index_ < argument_count_;
277 void
278 Getopt_long::next ()
280 error_ = E_NOERROR;
281 while (array_index_ < argument_count_
282 && !arg_value_char_a_a_[array_index_][argument_index_])
284 array_index_++;
285 argument_index_ = 0;
289 char const *
290 Getopt_long::current_arg ()
292 if (array_index_ >= argument_count_)
293 return 0;
294 char const * a = arg_value_char_a_a_[array_index_];
295 return a + argument_index_;
298 char const *
299 Getopt_long::get_next_arg ()
301 char const * a = current_arg ();
302 if (a)
304 array_index_ ++;
305 argument_index_= 0;
307 return a;
311 const int EXTRA_SPACES = 5;
313 String
314 Long_option_init::table_string (Long_option_init *l)
316 String argstr = "ARG";
317 String tabstr = "";
319 int wid = 0;
320 for (int i=0; l[i].shortname_char_ || l[i].longname_str0_; i++)
322 wid = wid >? l[i].str_for_help ().length ();
325 for (int i=0; l[i].shortname_char_ || l[i].longname_str0_; i++)
327 String s = " " + l[i].str_for_help ();
328 s += String_convert::char_string (' ', wid - s.length () + EXTRA_SPACES);
330 tabstr += s + gettext (l[i].help_str0_) + "\n";
334 return tabstr;
338 Long_option_init::compare (Long_option_init const &a, Long_option_init const &b)
340 if (a.shortname_char_ && b.shortname_char_ && a.shortname_char_- b.shortname_char_)
341 return a.shortname_char_ - b.shortname_char_;
343 if (b.shortname_char_ && a.longname_str0_)
345 char s[2] = {b.shortname_char_, 0};
346 return strcmp (a.longname_str0_, s);
348 if (a.shortname_char_ && b.longname_str0_)
350 char s[2] = {a.shortname_char_, 0};
351 return strcmp (s, b.longname_str0_);
354 return strcmp (a.longname_str0_, b.longname_str0_);