]> git.donarmstrong.com Git - lilypond.git/blob - flower/lgetopt.cc
a73334fe008ee59f767388a5af82631677efe06d
[lilypond.git] / flower / lgetopt.cc
1 /*
2    process command line, GNU style.
3
4    this is (Copyleft) 1996, Han-Wen Nienhuys, <hanwen@stack.nl>
5  */
6 #include <stdio.h>
7 #include <iostream.h>
8 #include <assert.h>
9 #include "lgetopt.hh"
10
11 long
12 Getopt_long::argument_to_i()
13 {
14   long l;
15   if (!optional_argument_ch_C_ 
16         || sscanf (optional_argument_ch_C_, "%ld", &l) != 1)
17         report (E_ILLEGALARG);
18   
19   return l;
20 }
21
22 const Long_option_init *
23 Getopt_long::parselong()
24 {
25   char const *optnm = arg_value_ch_a_a_[array_index_i_] + 2 ;
26   assert (*optnm);
27   
28   char const *endopt = strchr (optnm, '=');
29   int searchlen  = (endopt) ? endopt - optnm : strlen (optnm);
30   
31   found_option_l_=0;
32   for (int i=0; i< table_len_i_; i++) 
33     {
34         char const *ln = option_a_[i].longname;
35
36         if (ln && !strncmp (ln, optnm, searchlen)) 
37           {
38             found_option_l_ = option_a_+i;
39             break;
40           }
41   }     
42
43   if (!found_option_l_) 
44     {
45         report (E_UNKNOWNOPTION);
46         return 0;
47     }
48   array_index_i_++;
49   argument_index_i_ = 0;
50
51   
52   if (found_option_l_->take_arg) 
53     {
54         if (endopt)
55             optional_argument_ch_C_ = endopt +1; // a '='
56         else 
57           {
58             optional_argument_ch_C_ = arg_value_ch_a_a_[array_index_i_];
59             array_index_i_++;
60           }
61         if (!optional_argument_ch_C_)
62             report (E_ARGEXPECT);
63
64     }
65   else 
66     {
67         optional_argument_ch_C_ = 0;
68         if (endopt)
69             report (E_NOARGEXPECT);
70     }
71   
72   return found_option_l_;
73 }
74
75
76 void
77 Long_option_init::printon (ostream &errorout)const
78 {
79   if (shortname)        
80         errorout <<"-" << shortname;
81   if (shortname && longname)
82         errorout << ", ";
83   if (longname) 
84         errorout << "`--" << longname << "'";
85 }
86
87 // report an error, GNU style.
88 void
89 Getopt_long::report (Errorcod c)
90 {
91   error_ = c;
92   if (!error_ostream_l_)
93         return;
94
95   *error_ostream_l_ << arg_value_ch_a_a_[0] << ": ";
96   switch (c) 
97     {
98   case E_ARGEXPECT:
99         *error_ostream_l_<< "option ";
100         found_option_l_->printon (*error_ostream_l_);
101         *error_ostream_l_ << "requires an argument"<<endl;
102         break;
103   case  E_NOARGEXPECT:
104         *error_ostream_l_ << "option `--" <<
105             found_option_l_->longname << "' does not allow an argument"<<endl;
106         break;
107         
108   case E_UNKNOWNOPTION:
109         *error_ostream_l_ << "unrecognized option ";
110         if (argument_index_i_)
111             *error_ostream_l_ << "-" << arg_value_ch_a_a_[array_index_i_][argument_index_i_] << endl;
112         else
113             *error_ostream_l_ << arg_value_ch_a_a_[array_index_i_] << endl;
114
115         break;
116   case E_ILLEGALARG:
117         *error_ostream_l_ << "illegal argument `" << optional_argument_ch_C_ << "\'to option ";
118         found_option_l_->printon (*error_ostream_l_);
119         *error_ostream_l_ << '\n';
120   default:
121         assert (false);
122     }
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   
178   if (argument_index_i_)
179         return parseshort();
180   
181   const char * argument_C = arg_value_ch_a_a_[array_index_i_];
182   
183   if (argument_C[0] != '-')
184         return 0;
185
186   if (argument_C[1] == '-') {// what to do with "command  --  bla"
187         if ( argument_C[2])
188             return parselong();
189         else
190             return 0;
191     }
192   else 
193     {
194         if (argument_C[ 1 ]) 
195           {
196             argument_index_i_ = 1;
197             return parseshort();
198           }
199         else 
200           {
201             return 0;
202           }
203     }
204 }
205
206 Getopt_long::Getopt_long (int c, char  **v, Long_option_init *lo)
207 {
208   option_a_ = lo;
209   error_ostream_l_ = &cerr;
210   arg_value_ch_a_a_ = v;
211   argument_count_i_ = c;
212   array_index_i_ = 1;
213   argument_index_i_ = 0;
214
215   //    reached end of option table?
216   table_len_i_ =0;
217   for (int i = 0;  option_a_[i].longname ||option_a_[i].shortname; i++)
218         table_len_i_ ++;
219 }
220
221 bool
222 Getopt_long::ok()const
223 {
224   return  array_index_i_ < argument_count_i_;
225 }
226
227 void
228 Getopt_long::next()
229 {
230   error_ = E_NOERROR;
231   while (array_index_i_ < argument_count_i_
232            && !arg_value_ch_a_a_[array_index_i_][argument_index_i_]) 
233              {
234         array_index_i_++;
235         argument_index_i_ = 0;
236     }
237 }
238    
239 char const *
240 Getopt_long::current_arg()
241 {
242   if (array_index_i_ >= argument_count_i_)
243         return 0;
244   char const * a = arg_value_ch_a_a_[array_index_i_];
245   return a + argument_index_i_;
246 }
247
248 char const *
249 Getopt_long::get_next_arg()
250 {
251   char const * a = current_arg();
252   if (a) 
253     {
254         array_index_i_ ++;
255         argument_index_i_= 0;
256     }
257   return a;
258 }