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
CommandLine()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
~CommandLine()265 CommandLine::~CommandLine()
266 {
267 csv::erase_container_of_heap_ptrs(aCommands);
268 pTheInstance_ = 0;
269 }
270
271 int
Run() const272 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 &
Get_()301 CommandLine::Get_()
302 {
303 csv_assert(pTheInstance_ != 0);
304 return *pTheInstance_;
305 }
306
307 bool
DoesTransform_SinceTag() const308 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 &
DisplayOf_SinceTagValue(const String & i_sVersionNumber) const320 CommandLine::DisplayOf_SinceTagValue( const String & i_sVersionNumber ) const
321 {
322 return pSinceTransformator->DisplayOf(i_sVersionNumber);
323 }
324
325 void
do_Init(int argc,char * argv[])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_ExternNamespace)
359 {
360 sExternNamespace = *(++it);
361 ++it;
362 if ( strncmp(sExternNamespace.c_str(), "::", 2) != 0)
363 {
364 throw command::X_CommandLine(
365 "-extnsp needs an absolute qualified namespace, starting with \"::\"."
366 );
367 }
368 }
369 else if (*it == command::C_opt_ExternRoot)
370 {
371 ++it;
372 StreamLock sl(1000);
373 if ( csv::compare(*it, 0, "http://", 7) != 0 )
374 {
375 sl() << "http://" << *it;
376 }
377 if ( *(sl().end()-1) != '/')
378 sl() << '/';
379 sExternRoot = sl().c_str();
380
381 ++it;
382 }
383 // else if (*it == command::C_opt_CreateXml)
384 // do_clCreateXml(it,itEnd);
385 // else if (command::C_opt_Load)
386 // do_clLoad(it,itEnd);
387 // else if (*it == command::C_opt_Save)
388 // do_clSave(it,itEnd);
389 else if (*it == "-h" OR *it == "-?" OR *it == "?")
390 // Leads to displaying help, because bInitOk stays on false.
391 return;
392 else if ( *it == command::C_opt_Parse )
393 // Only for backwards compatibility.
394 // Just ignore "-parse".
395 ++it;
396 else
397 {
398 StreamLock sl(200);
399 throw command::X_CommandLine(
400 sl() << "Unknown commandline option \""
401 << *it
402 << "\"."
403 << c_str );
404 }
405 } // end for
406 sort_Commands();
407
408 bInitOk = true;
409
410 } // end try
411 catch ( command::X_CommandLine & xxx )
412 {
413 xxx.Report( Cerr() );
414 }
415 catch ( csv::Exception & xxx )
416 {
417 xxx.GetInfo( Cerr() );
418 }
419 }
420
421 void
do_PrintUse() const422 CommandLine::do_PrintUse() const
423 {
424 Cout() << C_sUserGuide << Endl();
425 }
426
427 bool
inq_CheckParameters() const428 CommandLine::inq_CheckParameters() const
429 {
430 if (NOT bInitOk OR aCommands.size() == 0)
431 return false;
432 return true;
433 }
434
435 void
load_IncludedCommands(StringVector & out,const char * i_filePath)436 CommandLine::load_IncludedCommands( StringVector & out,
437 const char * i_filePath )
438 {
439 CharacterSource
440 aIncludedCommands;
441 csv::File
442 aFile(i_filePath, csv::CFM_READ);
443 if (NOT aFile.open())
444 {
445 Cerr() << "Command include file \""
446 << i_filePath
447 << "\" not found."
448 << Endl();
449 throw command::X_CommandLine("Invalid file in option -I:<command-file>.");
450 }
451 aIncludedCommands.LoadText(aFile);
452 aFile.close();
453
454 bool bInToken = false;
455 StreamLock aTransmit(200);
456 for ( ; NOT aIncludedCommands.IsFinished(); aIncludedCommands.MoveOn() )
457 {
458 if (bInToken)
459 {
460 if (aIncludedCommands.CurChar() <= 32)
461 {
462 const char *
463 pToken = aIncludedCommands.CutToken();
464 bInToken = false;
465
466 if ( strncmp(pToken, "-I:", 3) != 0 )
467 {
468 aTransmit().seekp(0);
469 aTransmit() << pToken;
470 aTransmit().replace_all('\\', *csv::ploc::Delimiter());
471 aTransmit().replace_all('/', *csv::ploc::Delimiter());
472 out.push_back(String(aTransmit().c_str()));
473 }
474 else
475 load_IncludedCommands(out, pToken+3);
476 }
477 }
478 else
479 {
480 if (aIncludedCommands.CurChar() > 32)
481 {
482 aIncludedCommands.CutToken();
483 bInToken = true;
484 }
485 } // endif (bInToken) else
486
487 } // end while()
488 }
489
490 namespace
491 {
492 inline int
v_nr(StringVector::const_iterator it)493 v_nr(StringVector::const_iterator it)
494 {
495 return int( *(*it).c_str() ) - int('0');
496 }
497 } // anonymous namespace
498
499 void
do_clVerbose(opt_iter & it,opt_iter itEnd)500 CommandLine::do_clVerbose( opt_iter & it,
501 opt_iter itEnd )
502 {
503 ++it;
504 if ( it == itEnd ? true : v_nr(it) < 0 OR v_nr(it) > 7 )
505 throw command::X_CommandLine( "Missing or invalid number in -v option." );
506 nDebugStyle = v_nr(it);
507 ++it;
508 }
509
510 void
do_clParse(opt_iter & it,opt_iter itEnd)511 CommandLine::do_clParse( opt_iter & it,
512 opt_iter itEnd )
513 {
514 command::Command *
515 pCmd_Parse = new command::Parse;
516 pCmd_Parse->Init(it, itEnd);
517 aCommands.push_back(pCmd_Parse);
518 }
519
520 void
do_clCreateHtml(opt_iter & it,opt_iter itEnd)521 CommandLine::do_clCreateHtml( opt_iter & it,
522 opt_iter itEnd )
523 {
524 pCommand_CreateHtml = new command::CreateHtml;
525 pCommand_CreateHtml->Init(it, itEnd);
526 aCommands.push_back(pCommand_CreateHtml);
527 }
528
529 void
do_clSinceFile(opt_iter & it,opt_iter itEnd)530 CommandLine::do_clSinceFile( opt_iter & it,
531 opt_iter itEnd )
532 {
533 pSinceTransformator->Init(it, itEnd);
534 }
535
536
537 namespace
538 {
539
540 struct Less_RunningRank
541 {
operator ()autodoc::__anon7cfc98910211::Less_RunningRank542 bool operator()(
543 const command::Command * const &
544 i1,
545 const command::Command * const &
546 i2 ) const
547 { return i1->RunningRank() < i2->RunningRank(); }
548 };
549
550 } // anonymous namespace
551
552
553
554 void
sort_Commands()555 CommandLine::sort_Commands()
556 {
557 std::sort( aCommands.begin(),
558 aCommands.end(),
559 Less_RunningRank() );
560 }
561
562 } // namespace autodoc
563