1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 #include <precomp.h>
25 #include <cosv/commandline.hxx>
26
27 // NOT FULLY DECLARED SERVICES
28 #include <cosv/file.hxx>
29
30
31 namespace csv
32 {
33
34 namespace
35 {
36
37 const intt C_nNoOption = -1;
38
39 const char * sIncludeOptionShort = "-A:";
40 const char * sIncludeOptionLong = "--Arguments:";
41 const uintt nIncludeOptionShort_Length = strlen(sIncludeOptionShort);
42 const uintt nIncludeOptionLong_Length = strlen(sIncludeOptionLong);
43
44
45 /** Analyses, if an option is the one to include a file with
46 further command line arguments.
47 */
48 bool IsIncludeOption(
49 const String & i_option );
50
51 /** Gets the file name from an include-arguments-option.
52 */
53 String IncludeFile_fromIncludeOption(
54 const String & i_option );
55
56
57 bool
IsIncludeOption(const String & i_option)58 IsIncludeOption(const String & i_option)
59 {
60 return strncmp(i_option, sIncludeOptionShort, nIncludeOptionShort_Length) == 0
61 OR
62 strncmp(i_option, sIncludeOptionLong, nIncludeOptionLong_Length) == 0;
63 }
64
65 String
IncludeFile_fromIncludeOption(const String & i_option)66 IncludeFile_fromIncludeOption(const String & i_option)
67 {
68 if ( strncmp(i_option, sIncludeOptionShort, nIncludeOptionShort_Length)
69 == 0 )
70 {
71 return String(i_option, nIncludeOptionShort_Length, str::maxsize);
72 }
73 else
74 if ( strncmp(i_option, sIncludeOptionLong, nIncludeOptionLong_Length)
75 == 0 )
76 {
77 return String(i_option, nIncludeOptionLong_Length, str::maxsize);
78 }
79 return String::Null_();
80 }
81
82
83 } // end anonymous namespace
84
85
86
87
88 /** Local helper class for searching a possible option name in a vector of
89 ->OptionDescription.
90 */
91 struct CommandLine::
92 FindOptionByText
93 {
operator ()csv::CommandLine::FindOptionByText94 bool operator()(
95 const CommandLine::OptionDescription &
96 i_option )
97 { return i_option.sText == sOption; }
98
99 /// @param i_searchText [i_searchText != ""]
FindOptionByTextcsv::CommandLine::FindOptionByText100 FindOptionByText(
101 const String & i_option )
102 : sOption(i_option) { }
103 private:
104 const String sOption;
105 };
106
107
108 typedef std::vector<StringVector::const_iterator> StringCIteratorList;
109 typedef std::vector<intt> OptionIdList;
110
111 bool
Interpret(int argc,char * argv[])112 CommandLine::Interpret( int argc,
113 char * argv[] )
114 {
115 Get_Arguments(argc,argv);
116 csv_assert(aOptionPoints.size() == aOptionIds.size());
117
118 StringVector::const_iterator
119 itNext = aCommandLine.begin();
120 ++itNext; // Move 1 forward from program name.
121 StringVector::const_iterator
122 itEnd = aCommandLine.end();
123 StringCIteratorList::const_iterator
124 itOptPtsEnd = aOptionPoints.end();
125
126 OptionIdList::const_iterator
127 itOptIds = aOptionIds.begin();
128 for ( StringCIteratorList::const_iterator itOptPts = aOptionPoints.begin();
129 itOptPts != itOptPtsEnd AND bIsOk;
130 ++itOptPts, ++itOptIds )
131 {
132 // May be, there are arguments which do not belong to the last option:
133 // itNext != *is
134 Handle_FreeArguments(itNext, *itOptPts);
135
136 itNext = do_HandleOption( *itOptIds,
137 *itOptPts + 1,
138 itOptPts+1 == itOptPtsEnd ? itEnd : *(itOptPts+1) );
139 csv_assert(itNext <= itEnd);
140 } // end for (is)
141 Handle_FreeArguments(itNext, itEnd);
142
143 return bIsOk;
144 }
145
CommandLine()146 CommandLine::CommandLine()
147 : aOptions(),
148 aCommandLine(),
149 bIsOk(false)
150 {
151 }
152
153 void
Add_Option(intt i_id,String i_text)154 CommandLine::Add_Option( intt i_id,
155 String i_text )
156 {
157 aOptions.push_back(OptionDescription( i_id,
158 i_text ));
159 }
160
161 void
Get_Arguments(int argc,char * argv[])162 CommandLine::Get_Arguments( int argc,
163 char * argv[] )
164 {
165 aCommandLine.erase(aCommandLine.begin(),aCommandLine.end());
166 aCommandLine.reserve(argc);
167
168 char ** pArgEnd = argv + argc;
169 for ( char ** pArg = &argv[0];
170 pArg != pArgEnd;
171 ++pArg )
172 {
173 Store_Argument(*pArg);
174 } // end for
175 Find_OptionPoints();
176 bIsOk = true;
177 }
178
179 intt
Find_Option(const String & i_text) const180 CommandLine::Find_Option( const String & i_text ) const
181 {
182 if (i_text.empty())
183 return C_nNoOption;
184
185 FindOptionByText aSearch(i_text);
186 OptionList::const_iterator
187 itFound = std::find_if( aOptions.begin(),
188 aOptions.end(),
189 aSearch );
190 if (itFound != aOptions.end())
191 {
192 return (*itFound).nId;
193 }
194 return C_nNoOption;
195 }
196
197 bool
Store_Argument(const String & i_arg)198 CommandLine::Store_Argument( const String & i_arg )
199 {
200 if ( NOT IsIncludeOption(i_arg) )
201 {
202 aCommandLine.push_back(i_arg);
203 return true;
204 }
205
206 return Try2Include_Options(i_arg);
207 }
208
209 void
Find_OptionPoints()210 CommandLine::Find_OptionPoints()
211 {
212 StringVector::const_iterator itEnd = aCommandLine.end();
213 for ( StringVector::const_iterator it = aCommandLine.begin() + 1;
214 it != itEnd;
215 ++it )
216 {
217 intt nOption = Find_Option(*it);
218 if (nOption != C_nNoOption)
219 {
220 aOptionPoints.push_back(it);
221 aOptionIds.push_back(nOption);
222 }
223 } // end for (i)
224 }
225
226 void
Handle_FreeArguments(StringVector::const_iterator i_begin,StringVector::const_iterator i_end)227 CommandLine::Handle_FreeArguments( StringVector::const_iterator i_begin,
228 StringVector::const_iterator i_end )
229 {
230 for ( StringVector::const_iterator it = i_begin;
231 it != i_end AND bIsOk;
232 ++it )
233 {
234 do_HandleFreeArgument(*it);
235 }
236 }
237
238 bool
Try2Include_Options(const String & i_includeOption)239 CommandLine::Try2Include_Options(const String & i_includeOption)
240 {
241 static StringVector
242 aIncludedOptionFiles_;
243
244 const String
245 aOptionFile(IncludeFile_fromIncludeOption(i_includeOption));
246
247 // Avoid recursion deadlock 1
248 if ( std::find( aIncludedOptionFiles_.begin(),
249 aIncludedOptionFiles_.end(),
250 aOptionFile )
251 != aIncludedOptionFiles_.end() )
252 {
253 Cerr() << "\nError: Self inclusion of option file "
254 << aOptionFile
255 << ".\n"
256 << Endl();
257 return false;
258 }
259
260 // Avoid recursion deadlock 2
261 aIncludedOptionFiles_.push_back(aOptionFile);
262
263 bool ok = Include_Options(aOptionFile);
264
265 // Avoid recursion deadlock 3
266 aIncludedOptionFiles_.pop_back();
267
268 return ok;
269 }
270
271 bool
Include_Options(const String & i_optionsFile)272 CommandLine::Include_Options( const String & i_optionsFile )
273 {
274 StreamStr
275 aIncludedText(500);
276 bool ok = Load_Options(aIncludedText, i_optionsFile);
277 if (NOT ok)
278 return false;
279
280 StringVector
281 aIncludedOptions;
282 Split(aIncludedOptions, aIncludedText.c_str());
283
284 StringVector::const_iterator itEnd = aIncludedOptions.end();
285 for ( StringVector::const_iterator it = aIncludedOptions.begin();
286 it != itEnd;
287 ++it )
288 {
289 Store_Argument(*it);
290 } // end for
291
292 return true;
293 }
294
295 bool
Load_Options(StreamStr & o_text,const String & i_optionsFile)296 CommandLine::Load_Options( StreamStr & o_text,
297 const String & i_optionsFile )
298 {
299 if (i_optionsFile.empty())
300 return false;
301
302 File
303 aOptionsFile(i_optionsFile, CFM_READ);
304 OpenCloseGuard
305 aOFGuard(aOptionsFile);
306 if (NOT aOFGuard)
307 {
308 Cerr() << "\nError: Options file "
309 << i_optionsFile
310 << " not found.\n"
311 << Endl();
312 return false;
313 }
314
315 StreamStr
316 aLoad(aOptionsFile);
317 o_text.swap(aLoad);
318 return true;
319 }
320
321
322
323
324 /****************** OptionDescription ***********************/
325
326
327 CommandLine::
OptionDescription(intt i_id,String i_text)328 OptionDescription::OptionDescription( intt i_id,
329 String i_text )
330 : nId(i_id),
331 sText(i_text)
332 {
333 }
334
335
336
337
338 } // namespace csv
339