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