]> git.donarmstrong.com Git - lilypond.git/blob - flower/lgetopt.cc
release: 0.1.24
[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
7 #include <stdio.h>
8 #include <iostream.h>
9 #include <assert.h>
10 #include "lgetopt.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
78 void
79 Long_option_init::printon (ostream &errorout) const
80 {
81   if (shortname)
82     errorout <<"-" << shortname;
83   if (shortname && longname)
84     errorout << ", ";
85   if (longname)
86     errorout << "`--" << longname << "'";
87 }
88
89 // report an error, GNU style.
90 void
91 Getopt_long::report (Errorcod c)
92 {
93   error_ = c;
94   if (!error_ostream_l_)
95     return;
96
97   *error_ostream_l_ << arg_value_ch_a_a_[0] << ": ";
98   switch (c)
99     {
100     case E_ARGEXPECT:
101       *error_ostream_l_<< _("option ");
102       found_option_l_->printon (*error_ostream_l_);
103       *error_ostream_l_ << _("requires an argument")<<endl;
104       break;
105     case  E_NOARGEXPECT:
106       *error_ostream_l_ << _("option `--") <<
107         found_option_l_->longname << _("' does not allow an argument")<<endl;
108       break;
109
110     case E_UNKNOWNOPTION:
111       *error_ostream_l_ << _("unrecognized option ");
112       if (argument_index_i_)
113         *error_ostream_l_ << "-" << arg_value_ch_a_a_[array_index_i_][argument_index_i_] << endl;
114       else
115         *error_ostream_l_ << arg_value_ch_a_a_[array_index_i_] << endl;
116
117       break;
118     case E_ILLEGALARG:
119       *error_ostream_l_ << _("illegal argument `") << optional_argument_ch_C_ << _("\'to option ");
120       found_option_l_->printon (*error_ostream_l_);
121       *error_ostream_l_ << '\n';
122     default:
123       assert (false);
124     }
125   exit (2);
126 }
127
128 const Long_option_init *
129 Getopt_long::parseshort()
130 {
131   char c=arg_value_ch_a_a_[array_index_i_][argument_index_i_];
132   found_option_l_=0;
133   assert (c);
134
135   for (int i=0; i < table_len_i_; i++)
136     if (option_a_[i].shortname == c)
137       {
138         found_option_l_  = option_a_+i;
139         break;
140       }
141
142   if (!found_option_l_)
143     {
144       report (E_UNKNOWNOPTION);
145       return 0;
146     }
147
148   argument_index_i_++;
149   if (!found_option_l_->take_arg)
150     {
151       optional_argument_ch_C_ = 0;
152       return found_option_l_;
153     }
154   optional_argument_ch_C_ = arg_value_ch_a_a_[array_index_i_] + argument_index_i_;
155
156   array_index_i_ ++;
157   argument_index_i_ = 0;
158
159   if (!optional_argument_ch_C_[0])
160     {
161       optional_argument_ch_C_ = arg_value_ch_a_a_[array_index_i_];
162       array_index_i_ ++;
163     }
164   if (!optional_argument_ch_C_)
165     {
166       report (E_ARGEXPECT);
167     }
168
169   return found_option_l_;
170 }
171
172 const Long_option_init *
173 Getopt_long::operator()()
174 {
175   if (!ok())
176     return 0;
177
178   next();
179   if (!ok ())
180     return 0;
181
182   if (argument_index_i_)
183     return parseshort();
184
185   const char * argument_C = arg_value_ch_a_a_[array_index_i_];
186
187   if (argument_C[0] != '-')
188     return 0;
189
190   if (argument_C[1] == '-') {// what to do with "command  --  bla"
191     if (argument_C[2])
192       return parselong();
193     else
194       return 0;
195   }
196   else
197     {
198       if (argument_C[ 1 ])
199         {
200           argument_index_i_ = 1;
201           return parseshort();
202         }
203       else
204         {
205           return 0;
206         }
207     }
208 }
209
210 Getopt_long::Getopt_long (int c, char  **v, Long_option_init *lo)
211 {
212   option_a_ = lo;
213   error_ostream_l_ = &cerr;
214   arg_value_ch_a_a_ = v;
215   argument_count_i_ = c;
216   array_index_i_ = 1;
217   argument_index_i_ = 0;
218
219   //    reached end of option table?
220   table_len_i_ =0;
221   for (int i = 0;  option_a_[i].longname ||option_a_[i].shortname; i++)
222     table_len_i_ ++;
223 }
224
225 bool
226 Getopt_long::ok() const
227 {
228   return  array_index_i_ < argument_count_i_;
229 }
230
231 void
232 Getopt_long::next()
233 {
234   error_ = E_NOERROR;
235   while (array_index_i_ < argument_count_i_
236          && !arg_value_ch_a_a_[array_index_i_][argument_index_i_])
237     {
238       array_index_i_++;
239       argument_index_i_ = 0;
240     }
241 }
242
243 char const *
244 Getopt_long::current_arg()
245 {
246   if (array_index_i_ >= argument_count_i_)
247     return 0;
248   char const * a = arg_value_ch_a_a_[array_index_i_];
249   return a + argument_index_i_;
250 }
251
252 char const *
253 Getopt_long::get_next_arg()
254 {
255   char const * a = current_arg();
256   if (a)
257     {
258       array_index_i_ ++;
259       argument_index_i_= 0;
260     }
261   return a;
262 }