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