]> git.donarmstrong.com Git - lilypond.git/blob - flower/getopt-long.cc
patch::: 1.3.34.jcn2
[lilypond.git] / flower / getopt-long.cc
1 /*
2    process command line, GNU style.
3
4    this is (Copyleft) 1996, Han-Wen Nienhuys, <hanwen@cs.uu.nl>
5  */
6
7 #include <string.h>
8 #include <stdio.h>
9 #include <iostream.h>
10 #include <assert.h>
11 #include "config.h"
12 #include "getopt-long.hh"
13 #include "international.hh"
14 #include "string-convert.hh"
15
16
17 #if !HAVE_GETTEXT
18 inline char*
19 gettext (char const* s)
20 {
21   return (char*)s;
22 }
23 #else
24 #include <libintl.h>
25 #endif
26
27 long
28 Getopt_long::argument_to_i()
29 {
30   long l;
31   if (!optional_argument_ch_C_
32       || sscanf (optional_argument_ch_C_, "%ld", &l) != 1)
33     report (E_ILLEGALARG);
34
35   return l;
36 }
37
38 const Long_option_init *
39 Getopt_long::parselong()
40 {
41   char const *optnm = arg_value_ch_a_a_[array_index_i_] + 2 ;
42   assert (*optnm);
43
44   char const *endopt = strchr (optnm, '=');
45   int searchlen  = (endopt) ? endopt - optnm : strlen (optnm);
46
47   found_option_l_=0;
48   for (int i=0; i< table_len_i_; i++)
49     {
50       char const *ln = option_a_[i].longname_sz_;
51
52       if (ln && !strncmp (ln, optnm, searchlen))
53         {
54           found_option_l_ = option_a_+i;
55           break;
56         }
57     }
58
59   if (!found_option_l_)
60     {
61       report (E_UNKNOWNOPTION);
62       return 0;
63     }
64   array_index_i_++;
65   argument_index_i_ = 0;
66
67
68   if (found_option_l_->take_arg_sz_)
69     {
70       if (endopt)
71         optional_argument_ch_C_ = endopt +1; // a '='
72       else
73         {
74           optional_argument_ch_C_ = arg_value_ch_a_a_[array_index_i_];
75           array_index_i_++;
76         }
77       if (!optional_argument_ch_C_)
78         report (E_ARGEXPECT);
79
80     }
81   else
82     {
83       optional_argument_ch_C_ = 0;
84       if (endopt)
85         report (E_NOARGEXPECT);
86     }
87
88   return found_option_l_;
89 }
90
91 String
92 Long_option_init::str () const
93 {
94   String str;
95   if (shortname_ch_)
96     str +=  "-" + shortname_ch_;
97   if (shortname_ch_ && longname_sz_)
98     str += ", ";
99   if (longname_sz_)
100     str += String ("`--") + longname_sz_ + "'";
101   return str;
102 }
103
104 String
105 Long_option_init::str_for_help () const
106 {
107   String s;
108   if (shortname_ch_)
109     s = "-" + to_str (shortname_ch_);
110   else
111     s = "  ";
112
113   s = s + ((shortname_ch_ && longname_sz_) ? "," : " ");
114
115   if (longname_sz_)
116     s = s + "--" + longname_sz_;
117
118   if (take_arg_sz_)
119     {
120       if (longname_sz_)
121         s = s + "=";
122       else
123         s = s + " ";
124       
125       s = s + gettext (take_arg_sz_);
126     }
127   return s;
128 }
129
130 // report an error, GNU style.
131 void
132 Getopt_long::report (Errorcod c)
133 {
134   error_ = c;
135   if (!error_ostream_l_)
136     return;
137
138   String str = arg_value_ch_a_a_[0];
139   str += ": ";
140   switch (c)
141     {
142     case E_ARGEXPECT:
143       str += _f ("option `%s' requires an argument",
144         found_option_l_->str ());
145       break;
146     case  E_NOARGEXPECT:
147       str += _f ("option `%s' doesn't allow an argument",
148         found_option_l_->str ());
149       break;
150     case E_UNKNOWNOPTION:
151       str += _f ("unrecognized option: `%s'",
152       String (argument_index_i_ 
153               ? String ("-" + String_convert::form_str ("%c", 
154                 arg_value_ch_a_a_[array_index_i_][argument_index_i_]))
155               : String (arg_value_ch_a_a_[array_index_i_])));
156       break;
157     case E_ILLEGALARG:
158       str += _f ("invalid argument `%s' to option `%s'",
159         optional_argument_ch_C_, found_option_l_->str ());
160       break;
161     default:
162       assert (false);
163     }
164   *error_ostream_l_ << str << endl;
165   exit (2);
166 }
167
168 const Long_option_init *
169 Getopt_long::parseshort()
170 {
171   char c=arg_value_ch_a_a_[array_index_i_][argument_index_i_];
172   found_option_l_=0;
173   assert (c);
174
175   for (int i=0; i < table_len_i_; i++)
176     if (option_a_[i].shortname_ch_ == c)
177       {
178         found_option_l_  = option_a_+i;
179         break;
180       }
181
182   if (!found_option_l_)
183     {
184       report (E_UNKNOWNOPTION);
185       return 0;
186     }
187
188   argument_index_i_++;
189   if (!found_option_l_->take_arg_sz_)
190     {
191       optional_argument_ch_C_ = 0;
192       return found_option_l_;
193     }
194   optional_argument_ch_C_ = arg_value_ch_a_a_[array_index_i_] + argument_index_i_;
195
196   array_index_i_ ++;
197   argument_index_i_ = 0;
198
199   if (!optional_argument_ch_C_[0])
200     {
201       optional_argument_ch_C_ = arg_value_ch_a_a_[array_index_i_];
202       array_index_i_ ++;
203     }
204   if (!optional_argument_ch_C_)
205     {
206       report (E_ARGEXPECT);
207     }
208
209   return found_option_l_;
210 }
211
212 const Long_option_init *
213 Getopt_long::operator()()
214 {
215   if (!ok())
216     return 0;
217
218   next();
219   if (!ok ())
220     return 0;
221
222   if (argument_index_i_)
223     return parseshort();
224
225   const char * argument_C = arg_value_ch_a_a_[array_index_i_];
226
227   if (argument_C[0] != '-')
228     return 0;
229
230   if (argument_C[1] == '-') {// what to do with "command  --  bla"
231     if (argument_C[2])
232       return parselong();
233     else
234       return 0;
235   }
236   else
237     {
238       if (argument_C[ 1 ])
239         {
240           argument_index_i_ = 1;
241           return parseshort();
242         }
243       else
244         {
245           return 0;
246         }
247     }
248 }
249
250
251
252 Getopt_long::Getopt_long (int c, char  **v, Long_option_init *lo)
253 {
254   option_a_ = lo;
255   error_ostream_l_ = &cerr;
256   arg_value_ch_a_a_ = v;
257   argument_count_i_ = c;
258   array_index_i_ = 1;
259   argument_index_i_ = 0;
260
261   //    reached end of option table?
262   table_len_i_ =0;
263   for (int i = 0;  option_a_[i].longname_sz_ ||option_a_[i].shortname_ch_; i++)
264     table_len_i_ ++;
265
266 }
267
268 bool
269 Getopt_long::ok() const
270 {
271   return  array_index_i_ < argument_count_i_;
272 }
273
274 void
275 Getopt_long::next()
276 {
277   error_ = E_NOERROR;
278   while (array_index_i_ < argument_count_i_
279          && !arg_value_ch_a_a_[array_index_i_][argument_index_i_])
280     {
281       array_index_i_++;
282       argument_index_i_ = 0;
283     }
284 }
285
286 char const *
287 Getopt_long::current_arg()
288 {
289   if (array_index_i_ >= argument_count_i_)
290     return 0;
291   char const * a = arg_value_ch_a_a_[array_index_i_];
292   return a + argument_index_i_;
293 }
294
295 char const *
296 Getopt_long::get_next_arg()
297 {
298   char const * a = current_arg();
299   if (a)
300     {
301       array_index_i_ ++;
302       argument_index_i_= 0;
303     }
304   return a;
305 }
306
307
308 const int EXTRA_SPACES = 5;
309
310 String
311 Long_option_init::table_str (Long_option_init *l) 
312 {
313   String argstr = "ARG";
314   String tabstr = "";
315
316   int wid = 0;
317   for (int i=0; l[i].shortname_ch_ || l[i].longname_sz_; i++)
318     {
319       wid = wid >? l[i].str_for_help ().length_i ();
320     }
321
322   for (int i=0; l[i].shortname_ch_ || l[i].longname_sz_; i++)
323     {
324       String s  =  "  " + l[i].str_for_help ();
325       s += String_convert::char_str (' ', wid - s.length_i () + EXTRA_SPACES);
326
327       tabstr += s + gettext (l[i].help_sz_) + "\n";
328     }
329
330     
331   return tabstr;
332 }
333
334 int
335 Long_option_init::compare (Long_option_init const &a, Long_option_init const &b)
336 {
337   if (a.shortname_ch_ && b.shortname_ch_ && a.shortname_ch_- b.shortname_ch_)
338     return a.shortname_ch_ - b.shortname_ch_;
339
340   if (b.shortname_ch_ && a.longname_sz_)
341     {
342       char s[2] = {b.shortname_ch_, 0};
343       return strcmp (a.longname_sz_, s);
344     }
345   if (a.shortname_ch_ && b.longname_sz_)
346     {
347       char s[2] = {a.shortname_ch_, 0};
348       return strcmp (s, b.longname_sz_);
349     }
350   
351   return strcmp (a.longname_sz_, b.longname_sz_);
352 }