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 #include <precomp.h> 23 #include <adc_cl.hxx> 24 25 26 // NOT FULLY DEFINED SERVICES 27 #include <algorithm> 28 #include <cosv/x.hxx> 29 #include <cosv/file.hxx> 30 #include <cosv/tpl/tpltools.hxx> 31 #include <ary/ary.hxx> 32 #include <tools/tkpchars.hxx> 33 #include <adc_msg.hxx> 34 #include "adc_cmds.hxx" 35 #include "adc_cmd_parse.hxx" 36 #include "cmd_sincedata.hxx" 37 38 39 namespace autodoc 40 { 41 42 CommandLine * CommandLine::pTheInstance_ = 0; 43 44 const char * const C_sUserGuide = 45 "\n\n\n" 46 " General Use of Autodoc\n" 47 " ----------------------\n" 48 "\n" 49 " Example for C++:\n" 50 "\n" 51 " -html <OutputDirectory> -name \"UDK 3.x anything\" -lg c++\n" 52 " -p <ProjName> <ProjectRootDirectory>\n" 53 " -t <SourceDir_relativeToProjectRoot>\n" 54 "\n" 55 " There may be several projects specified by -p.\n" 56 "\n" 57 "\n" 58 " Example for IDL:\n" 59 "\n" 60 " -html <OutputDirectory> -name \"UDK 3.x anything\" -lg idl\n" 61 " -t <SourceDir1> <SourceDir2>\n" 62 "\n" 63 " For both languages, instead of or in addition to -t may be\n" 64 " used -d (no subdirectories) or -f (just one file). There can\n" 65 " be multiple arguments after each of these options (-t -d -f).\n" 66 "\n" 67 "\n" 68 " Replacing @since Tag Content\n" 69 " ----------------------------\n" 70 "\n" 71 " In both languages you can give a transformation file to replace\n" 72 " entries in @since tags by different entries.\n" 73 " This file is given by the option\n" 74 " -sincefile <TransformationFilePath>\n" 75 " This option has to appear between the -html and the -lg option.\n" 76 " Example:\n" 77 " -html <OutputDirectory> -sincefile replacesince.txt\n" 78 " -name \"UDK 3.x anything\" -lg idl -t <SourceDir>\n" 79 "\n" 80 "\n"; 81 82 83 #if 0 // FUTURE 84 "\n\n\n" 85 " Use of Autodoc\n" 86 " --------------\n" 87 "\n" 88 " Basics:\n" 89 "\n" 90 " Autodoc may perform different tasks.\n" 91 "\n" 92 " Possible tasks are\n" 93 " - parsing source code\n" 94 " - creating HTML-output.\n" 95 " On the command line each task starts with a specific\n" 96 " option:\n" 97 " '-parse' for parsing source code,\n" 98 " '-html' for creating HTML.\n" 99 " All command line options, related to one task, have to follow before\n" 100 " the starting option of the next task.\n" 101 "\n" 102 " Within the task '-parse', there may be defined different projects.\n" 103 " A project definition is started with '-p'.\n" 104 " All not project specific options within the task '-parse' have to\n" 105 " appear in front of the first '-p'.\n" 106 " There can be no project at all. Then all options, available for\n" 107 " projects, can be used like for one nameless default project, without using\n" 108 " '-p', but these options still have to appear behind all other\n" 109 " options of the task '-parse'.\n" 110 "\n" 111 "\n" 112 " Legend:\n" 113 "\n" 114 " <SomeText> Describes an argument.\n" 115 " 'SomeText' Within '...' is the literal value of an argument.\n" 116 " + There can be multiple arguments.\n" 117 " | Separator for alternative literal values of an argument.\n" 118 "\n" 119 "\n" 120 " Syntax:\n" 121 "\n" 122 " -parse\n" 123 " -name <RepositoryName>]\n" 124 " -lg 'c++'|'idl'\n" 125 " -extg <AdditonalExtensions>+\n" 126 " -docg 'usehtml'\n" 127 " -p <ProjectName> <ProjectRootDir>\n" 128 " -l 'c++'|'idl'\n" 129 " -ext <AdditonalExtensions>+\n" 130 " -doc 'usehtml'\n" 131 " -d <SourceDir_relative2ProjectRootDir_nosubdirs>+\n" 132 " -t <SourceTree_relative2ProjectRootDir>+\n" 133 " -f <SourceFile_relative2ProjectRootDir>+\n" 134 " -html <OutputDir>\n" 135 " -xlinks <Namespace> <ExternLinksRootDir>\n" 136 " -i <CommandFilePath>\n" 137 " -v <VerboseNr>\n" 138 "\n" 139 "\n" 140 " Detailed Options Description:\n" 141 "\n" 142 " Option Arguments\n" 143 " ----------------------------------------------------------\n" 144 "\n" 145 " -parse \n\n" 146 " Starts the task \"Parse source code\".\n" 147 " May be omitted, if it would be the first option on the\n" 148 " command line.\n" 149 "\n" 150 " -name <RepositoryName>\n\n" 151 " This name is used for naming the repository in\n" 152 " human readable output. In future it may be used also for\n" 153 " identifiing a repository in searches.\n" 154 "\n" 155 " -lg 'c++|'idl'\n\n" 156 " Identifies the programming language to be parsed.\n" 157 " 'c++': C++\n" 158 " Files with extensions '.h', '.hxx' are parsed.\n" 159 " 'idl': UNO-IDL\n" 160 " Files with extensions '.idl' are parsed.\n" 161 " Here the language is set globally for all projects.\n" 162 " A project can override this by using '-l'.\n" 163 "\n" 164 " -extg <.AdditionalExtension>+\n\n" 165 " Has to follow immediately behind '-lg'.\n" 166 " Specifies additional extensions, that will be recognised as\n" 167 " source code files of the previously specified programming\n" 168 " language. Each extension has to start with '.'.\n" 169 " It is possible to include extensionless files, too,\n" 170 " by the argument '.'\n" 171 " Here these extensions are set globally for all projects.\n" 172 " A project can override this by using '-l' and '-ext'.\n" 173 "\n" 174 " -docg 'html'|'nohtml'\n\n" 175 " Specifies the default for all comments in source code, so \n" 176 " that HTML-tags are interpreted as such or else treated as\n" 177 " regular text.\n" 178 " Without this option, the default is 'nohtml'.\n" 179 " Here the default is set globally for all projects.\n" 180 " A project can override this by using '-doc'.\n" 181 "\n" 182 " -p <ProjectName> <ProjectRootDirectory>\n\n" 183 " ProjectName is used in output as human readable identifier\n" 184 " for the project. ProjectRootDirectory is the path,\n" 185 " where the arguments of '-d', '-t' and '-f' are relative to.\n" 186 " This option can be omitted, then there is no project name\n" 187 " and all paths are relative to the current working directory.\n" 188 "\n" 189 " -l 'c++|'idl'\n\n" 190 " Overrides -lg and -extg for the current project, which is\n" 191 " specified by the last previous '-p'.\n" 192 " For details see at option '-lg'.\n" 193 "\n" 194 " -ext <.AdditionalExtension>+\n\n" 195 " Can be used only immediately behind '-l'.\n" 196 " Overrides -extg for the current project, which is\n" 197 " specified by the last previous '-p'.\n" 198 " For details see at option '-extg'.\n" 199 "\n" 200 " -doc 'html'|'nohtml'\n\n" 201 " Overrides -docg for the current project, which is\n" 202 " specified by the last previous '-p'.\n" 203 " For details see at option '-docg'.\n" 204 "\n" 205 " -d <SourceDir_relative2ProjectRootDir_nosubdirs>+\n\n" 206 " For the current project all files in the given\n" 207 " directories are parsed, which have valid extensions.\n" 208 " Subdirectories are NOT parsed.\n" 209 "\n" 210 " -t <SourceTree_relative2ProjectRootDir>+\n\n" 211 " For the current project all files in the given\n" 212 " directories AND its subdirectories are parsed, which\n" 213 " have valid extensions.\n" 214 "\n" 215 " -f <SourceFile_relative2ProjectRootDir>+\n\n" 216 " For the current project and language the given files\n" 217 " are parsed. It doesn't matter, if their extensions match\n" 218 " the valid extensions.\n" 219 "\n" 220 " -html <OutputRootDir>\n\n" 221 " Starts the task \"Create HTML output\".\n" 222 "\n" 223 " -xlinks <Namespace> <ExternLinksRootDir>\n\n" 224 " This option allows, to create links to external\n" 225 " HTML-documents.\n" 226 " For all source code objects (like classes or functions)\n" 227 " which belong in the given namespace, the given root\n" 228 " directory is used as a base for links to them.\n" 229 " Presently, this works only for C++-mappings of IDL-items.\n" 230 " The given namespace has to be absolute.\n" 231 "\n" 232 " -i <CommandFilePath>\n\n" 233 " This option is replaced by the contents of the given\n" 234 " file. The file has to be ASCII and each option\n" 235 " has to start in the first column of a new line.\n" 236 " So each valid line starts with a '-'.\n" 237 " Empty lines are allowed.\n" 238 " Comment lines have to start with '#'\n" 239 "\n" 240 " -v <VerboseNumber>\n\n" 241 " Show details during parsing:\n" 242 " 2 shows each parsed letter,\n" 243 " 4 shows stored objects.\n" 244 " 1 shows recognised tokens.\n" 245 " These bit-values can be combined.\n" 246 " This option suppresses errors, because of\n" 247 " missing output options (no '-html').\n"; 248 #endif // 0, FUTURE 249 250 251 CommandLine::CommandLine() 252 : nDebugStyle(0), 253 pSinceTransformator(new command::SinceTagTransformationData), 254 aCommands(), 255 bInitOk(false), 256 pCommand_CreateHtml(0), 257 pReposy( & ary::Repository::Create_() ), 258 bCpp(false), 259 bIdl(false) 260 { 261 csv_assert(pTheInstance_ == 0); 262 pTheInstance_ = this; 263 } 264 265 CommandLine::~CommandLine() 266 { 267 csv::erase_container_of_heap_ptrs(aCommands); 268 pTheInstance_ = 0; 269 } 270 271 int 272 CommandLine::Run() const 273 { 274 Cout() << "\nAutodoc version 2.2.5" 275 << "\n---------------------" 276 << "\n" << Endl(); 277 278 bool 279 ok = true; 280 for ( CommandList::const_iterator it = aCommands.begin(); 281 ok AND it != aCommands.end(); 282 ++it ) 283 { 284 ok = (*it)->Run(); 285 } 286 287 if (pCommand_CreateHtml != 0) 288 { 289 StreamStr aDiagnosticMessagesFile(700); 290 aDiagnosticMessagesFile 291 << pCommand_CreateHtml->OutputDir() 292 << csv::ploc::Delimiter() 293 << "Autodoc_DiagnosticMessages.txt"; 294 TheMessages().WriteFile(aDiagnosticMessagesFile.c_str()); 295 } 296 297 return ok ? 0 : 1; 298 } 299 300 CommandLine & 301 CommandLine::Get_() 302 { 303 csv_assert(pTheInstance_ != 0); 304 return *pTheInstance_; 305 } 306 307 bool 308 CommandLine::DoesTransform_SinceTag() const 309 { 310 return pSinceTransformator->DoesTransform(); 311 } 312 313 //bool 314 //CommandLine::Strip_SinceTagText( String & io_sSinceTagValue ) const 315 //{ 316 // return pSinceTransformator->StripSinceTagText(io_sSinceTagValue); 317 //} 318 319 const String & 320 CommandLine::DisplayOf_SinceTagValue( const String & i_sVersionNumber ) const 321 { 322 return pSinceTransformator->DisplayOf(i_sVersionNumber); 323 } 324 325 void 326 CommandLine::do_Init( int argc, 327 char * argv[] ) 328 { 329 try 330 { 331 bInitOk = false; 332 StringVector aParameters; 333 334 char * * itpEnd = &argv[0] + argc; 335 for ( char * * itp = &argv[1]; itp != itpEnd; ++itp ) 336 { 337 if ( strncmp(*itp, "-I:", 3) != 0 ) 338 aParameters.push_back(String(*itp)); 339 else 340 load_IncludedCommands(aParameters, (*itp)+3); 341 } 342 343 StringVector::const_iterator itEnd = aParameters.end(); 344 for ( StringVector::const_iterator it = aParameters.begin(); 345 it != itEnd; 346 ) 347 { 348 if ( *it == command::C_opt_Verbose ) 349 do_clVerbose(it,itEnd); 350 else if ( *it == command::C_opt_LangAll 351 OR *it == command::C_opt_Name 352 OR *it == command::C_opt_DevmanFile ) 353 do_clParse(it,itEnd); 354 else if (*it == command::C_opt_CreateHtml) 355 do_clCreateHtml(it,itEnd); 356 else if (*it == command::C_opt_SinceFile) 357 do_clSinceFile(it,itEnd); 358 else if (*it == command::C_opt_IgnoreDefine) 359 { 360 AddIgnoreDefine(*(++it)); 361 ++it; 362 } 363 else if (*it == command::C_opt_ExternNamespace) 364 { 365 sExternNamespace = *(++it); 366 ++it; 367 if ( strncmp(sExternNamespace.c_str(), "::", 2) != 0) 368 { 369 throw command::X_CommandLine( 370 "-extnsp needs an absolute qualified namespace, starting with \"::\"." 371 ); 372 } 373 } 374 else if (*it == command::C_opt_ExternRoot) 375 { 376 ++it; 377 StreamLock sl(1000); 378 if ( csv::compare(*it, 0, "http://", 7) != 0 ) 379 { 380 sl() << "http://" << *it; 381 } 382 if ( *(sl().end()-1) != '/') 383 sl() << '/'; 384 sExternRoot = sl().c_str(); 385 386 ++it; 387 } 388 // else if (*it == command::C_opt_CreateXml) 389 // do_clCreateXml(it,itEnd); 390 // else if (command::C_opt_Load) 391 // do_clLoad(it,itEnd); 392 // else if (*it == command::C_opt_Save) 393 // do_clSave(it,itEnd); 394 else if (*it == "-h" OR *it == "-?" OR *it == "?") 395 // Leads to displaying help, because bInitOk stays on false. 396 return; 397 else if ( *it == command::C_opt_Parse ) 398 // Only for backwards compatibility. 399 // Just ignore "-parse". 400 ++it; 401 else 402 { 403 StreamLock sl(200); 404 throw command::X_CommandLine( 405 sl() << "Unknown commandline option \"" 406 << *it 407 << "\"." 408 << c_str ); 409 } 410 } // end for 411 sort_Commands(); 412 413 bInitOk = true; 414 415 } // end try 416 catch ( command::X_CommandLine & xxx ) 417 { 418 xxx.Report( Cerr() ); 419 } 420 catch ( csv::Exception & xxx ) 421 { 422 xxx.GetInfo( Cerr() ); 423 } 424 } 425 426 void 427 CommandLine::do_PrintUse() const 428 { 429 Cout() << C_sUserGuide << Endl(); 430 } 431 432 bool 433 CommandLine::inq_CheckParameters() const 434 { 435 if (NOT bInitOk OR aCommands.size() == 0) 436 return false; 437 return true; 438 } 439 440 void 441 CommandLine::load_IncludedCommands( StringVector & out, 442 const char * i_filePath ) 443 { 444 CharacterSource 445 aIncludedCommands; 446 csv::File 447 aFile(i_filePath, csv::CFM_READ); 448 if (NOT aFile.open()) 449 { 450 Cerr() << "Command include file \"" 451 << i_filePath 452 << "\" not found." 453 << Endl(); 454 throw command::X_CommandLine("Invalid file in option -I:<command-file>."); 455 } 456 aIncludedCommands.LoadText(aFile); 457 aFile.close(); 458 459 bool bInToken = false; 460 StreamLock aTransmit(200); 461 for ( ; NOT aIncludedCommands.IsFinished(); aIncludedCommands.MoveOn() ) 462 { 463 if (bInToken) 464 { 465 if (aIncludedCommands.CurChar() <= 32) 466 { 467 const char * 468 pToken = aIncludedCommands.CutToken(); 469 bInToken = false; 470 471 if ( strncmp(pToken, "-I:", 3) != 0 ) 472 { 473 aTransmit().seekp(0); 474 aTransmit() << pToken; 475 aTransmit().replace_all('\\', *csv::ploc::Delimiter()); 476 aTransmit().replace_all('/', *csv::ploc::Delimiter()); 477 out.push_back(String(aTransmit().c_str())); 478 } 479 else 480 load_IncludedCommands(out, pToken+3); 481 } 482 } 483 else 484 { 485 if (aIncludedCommands.CurChar() > 32) 486 { 487 aIncludedCommands.CutToken(); 488 bInToken = true; 489 } 490 } // endif (bInToken) else 491 492 } // end while() 493 } 494 495 namespace 496 { 497 inline int 498 v_nr(StringVector::const_iterator it) 499 { 500 return int( *(*it).c_str() ) - int('0'); 501 } 502 } // anonymous namespace 503 504 void 505 CommandLine::do_clVerbose( opt_iter & it, 506 opt_iter itEnd ) 507 { 508 ++it; 509 if ( it == itEnd ? true : v_nr(it) < 0 OR v_nr(it) > 7 ) 510 throw command::X_CommandLine( "Missing or invalid number in -v option." ); 511 nDebugStyle = v_nr(it); 512 ++it; 513 } 514 515 void 516 CommandLine::do_clParse( opt_iter & it, 517 opt_iter itEnd ) 518 { 519 command::Command * 520 pCmd_Parse = new command::Parse; 521 pCmd_Parse->Init(it, itEnd); 522 aCommands.push_back(pCmd_Parse); 523 } 524 525 void 526 CommandLine::do_clCreateHtml( opt_iter & it, 527 opt_iter itEnd ) 528 { 529 pCommand_CreateHtml = new command::CreateHtml; 530 pCommand_CreateHtml->Init(it, itEnd); 531 aCommands.push_back(pCommand_CreateHtml); 532 } 533 534 void 535 CommandLine::do_clSinceFile( opt_iter & it, 536 opt_iter itEnd ) 537 { 538 pSinceTransformator->Init(it, itEnd); 539 } 540 541 542 namespace 543 { 544 545 struct Less_RunningRank 546 { 547 bool operator()( 548 const command::Command * const & 549 i1, 550 const command::Command * const & 551 i2 ) const 552 { return i1->RunningRank() < i2->RunningRank(); } 553 }; 554 555 } // anonymous namespace 556 557 558 559 void 560 CommandLine::sort_Commands() 561 { 562 std::sort( aCommands.begin(), 563 aCommands.end(), 564 Less_RunningRank() ); 565 } 566 567 } // namespace autodoc 568