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 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 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 { 94 bool operator()( 95 const CommandLine::OptionDescription & 96 i_option ) 97 { return i_option.sText == sOption; } 98 99 /// @param i_searchText [i_searchText != ""] 100 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 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 146 CommandLine::CommandLine() 147 : aOptions(), 148 aCommandLine(), 149 bIsOk(false) 150 { 151 } 152 153 void 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 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 180 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 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 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 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 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 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 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:: 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