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