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