]> git.donarmstrong.com Git - lilypond.git/blob - flower/getopt-long.cc
release: 1.0.1
[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 <stdio.h>
8 #include <iostream.h>
9 #include <assert.h>
10 #include "getopt-long.hh"
11 #include "international.hh"
12
13 long
14 Getopt_long::argument_to_i()
15 {
16   long l;
17   if (!optional_argument_ch_C_
18       || sscanf (optional_argument_ch_C_, "%ld", &l) != 1)
19     report (E_ILLEGALARG);
20
21   return l;
22 }
23
24 const Long_option_init *
25 Getopt_long::parselong()
26 {
27   char const *optnm = arg_value_ch_a_a_[array_index_i_] + 2 ;
28   assert (*optnm);
29
30   char const *endopt = strchr (optnm, '=');
31   int searchlen  = (endopt) ? endopt - optnm : strlen (optnm);
32
33   found_option_l_=0;
34   for (int i=0; i< table_len_i_; i++)
35     {
36       char const *ln = option_a_[i].longname;
37
38       if (ln && !strncmp (ln, optnm, searchlen))
39         {
40           found_option_l_ = option_a_+i;
41           break;
42         }
43     }
44
45   if (!found_option_l_)
46     {
47       report (E_UNKNOWNOPTION);
48       return 0;
49     }
50   array_index_i_++;
51   argument_index_i_ = 0;
52
53
54   if (found_option_l_->take_arg)
55     {
56       if (endopt)
57         optional_argument_ch_C_ = endopt +1; // a '='
58       else
59         {
60           optional_argument_ch_C_ = arg_value_ch_a_a_[array_index_i_];
61           array_index_i_++;
62         }
63       if (!optional_argument_ch_C_)
64         report (E_ARGEXPECT);
65
66     }
67   else
68     {
69       optional_argument_ch_C_ = 0;
70       if (endopt)
71         report (E_NOARGEXPECT);
72     }
73
74   return found_option_l_;
75 }
76
77 String
78 Long_option_init::str () const
79 {
80   String str;
81   if (shortname)
82     str +=  "-" + shortname;
83   if (shortname && longname)
84     str += ", ";
85   if (longname)
86     str += String ("`--") + longname + "'";
87   return str;
88 }
89
90 // report an error, GNU style.
91 void
92 Getopt_long::report (Errorcod c)
93 {
94   error_ = c;
95   if (!error_ostream_l_)
96     return;
97
98   String str = arg_value_ch_a_a_[0];
99   str += ": ";
100   switch (c)
101     {
102     case E_ARGEXPECT:
103       str += _f ("option `%s\' requires an argument",
104         found_option_l_->str ());
105       break;
106     case  E_NOARGEXPECT:
107       str += _f ("option `%s\' doesn't allow an argument",
108         found_option_l_->str ());
109       break;
110     case E_UNKNOWNOPTION:
111       str += _f ("unrecognized option: `%s\'",
112       String (argument_index_i_ 
113               ? String ("-" + _f("%c",arg_value_ch_a_a_[array_index_i_][argument_index_i_]))
114               : String (arg_value_ch_a_a_[array_index_i_])));
115       break;
116     case E_ILLEGALARG:
117       str += _f ("invalid argument `%s\' to option `%s'",
118         optional_argument_ch_C_, found_option_l_->str ());
119     default:
120       assert (false);
121     }
122   *error_ostream_l_ << str << endl;
123   exit (2);
124 }
125
126 const Long_option_init *
127 Getopt_long::parseshort()
128 {
129   char c=arg_value_ch_a_a_[array_index_i_][argument_index_i_];
130   found_option_l_=0;
131   assert (c);
132
133   for (int i=0; i < table_len_i_; i++)
134     if (option_a_[i].shortname == c)
135       {
136         found_option_l_  = option_a_+i;
137         break;
138       }
139
140   if (!found_option_l_)
141     {
142       report (E_UNKNOWNOPTION);
143       return 0;
144     }
145
146   argument_index_i_++;
147   if (!found_option_l_->take_arg)
148     {
149       optional_argument_ch_C_ = 0;
150       return found_option_l_;
151     }
152   optional_argument_ch_C_ = arg_value_ch_a_a_[array_index_i_] + argument_index_i_;
153
154   array_index_i_ ++;
155   argument_index_i_ = 0;
156
157   if (!optional_argument_ch_C_[0])
158     {
159       optional_argument_ch_C_ = arg_value_ch_a_a_[array_index_i_];
160       array_index_i_ ++;
161     }
162   if (!optional_argument_ch_C_)
163     {
164       report (E_ARGEXPECT);
165     }
166
167   return found_option_l_;
168 }
169
170 const Long_option_init *
171 Getopt_long::operator()()
172 {
173   if (!ok())
174     return 0;
175
176   next();
177   if (!ok ())
178     return 0;
179
180   if (argument_index_i_)
181     return parseshort();
182
183   const char * argument_C = arg_value_ch_a_a_[array_index_i_];
184
185   if (argument_C[0] != '-')
186     return 0;
187
188   if (argument_C[1] == '-') {// what to do with "command  --  bla"
189     if (argument_C[2])
190       return parselong();
191     else
192       return 0;
193   }
194   else
195     {
196       if (argument_C[ 1 ])
197         {
198           argument_index_i_ = 1;
199           return parseshort();
200         }
201       else
202         {
203           return 0;
204         }
205     }
206 }
207
208 Getopt_long::Getopt_long (int c, char  **v, Long_option_init *lo)
209 {
210   option_a_ = lo;
211   error_ostream_l_ = &cerr;
212   arg_value_ch_a_a_ = v;
213   argument_count_i_ = c;
214   array_index_i_ = 1;
215   argument_index_i_ = 0;
216
217   //    reached end of option table?
218   table_len_i_ =0;
219   for (int i = 0;  option_a_[i].longname ||option_a_[i].shortname; i++)
220     table_len_i_ ++;
221 }
222
223 bool
224 Getopt_long::ok() const
225 {
226   return  array_index_i_ < argument_count_i_;
227 }
228
229 void
230 Getopt_long::next()
231 {
232   error_ = E_NOERROR;
233   while (array_index_i_ < argument_count_i_
234          && !arg_value_ch_a_a_[array_index_i_][argument_index_i_])
235     {
236       array_index_i_++;
237       argument_index_i_ = 0;
238     }
239 }
240
241 char const *
242 Getopt_long::current_arg()
243 {
244   if (array_index_i_ >= argument_count_i_)
245     return 0;
246   char const * a = arg_value_ch_a_a_[array_index_i_];
247   return a + argument_index_i_;
248 }
249
250 char const *
251 Getopt_long::get_next_arg()
252 {
253   char const * a = current_arg();
254   if (a)
255     {
256       array_index_i_ ++;
257       argument_index_i_= 0;
258     }
259   return a;
260 }