source: trunk/tools/qdoc3/main.cpp@ 1030

Last change on this file since 1030 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 15.6 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the tools applications of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42/*
43 main.cpp
44*/
45
46#include <qglobal.h>
47#include <stdlib.h>
48#include "apigenerator.h"
49#include "codemarker.h"
50#include "codeparser.h"
51#include "config.h"
52#include "cppcodemarker.h"
53#include "cppcodeparser.h"
54#include "cpptoqsconverter.h"
55#include "doc.h"
56#include "htmlgenerator.h"
57#include "jambiapiparser.h"
58#include "javacodemarker.h"
59#include "javadocgenerator.h"
60#include "linguistgenerator.h"
61#include "loutgenerator.h"
62#include "mangenerator.h"
63#include "plaincodemarker.h"
64#include "polyarchiveextractor.h"
65#include "polyuncompressor.h"
66#include "qsakernelparser.h"
67#include "qscodemarker.h"
68#include "qscodeparser.h"
69#include "sgmlgenerator.h"
70#include "webxmlgenerator.h"
71#include "ditaxmlgenerator.h"
72#include "tokenizer.h"
73#include "tree.h"
74#include <qdebug.h>
75
76#include "qtranslator.h"
77#ifndef QT_BOOTSTRAPPED
78# include "qcoreapplication.h"
79#endif
80
81QT_BEGIN_NAMESPACE
82
83/*
84 The default indent for code is 4.
85 The default value for false is 0.
86 The default language is c++.
87 The default output format is html.
88 The default tab size is 8.
89 And those are all the default values for configuration variables.
90 */
91static const struct {
92 const char *key;
93 const char *value;
94} defaults[] = {
95 { CONFIG_CODEINDENT, "4" },
96 { CONFIG_FALSEHOODS, "0" },
97 { CONFIG_LANGUAGE, "Cpp" },
98 { CONFIG_OUTPUTFORMATS, "HTML" },
99 { CONFIG_TABSIZE, "8" },
100 { 0, 0 }
101};
102
103static bool slow = false;
104static bool showInternal = false;
105static bool obsoleteLinks = false;
106static QStringList defines;
107static QHash<QString, Tree *> trees;
108static QString appArg; // application
109
110/*!
111 Find the Tree for language \a lang and return a pointer to it.
112 If there is no Tree for language \a lang in the Tree table, add
113 a new one. The Tree table is indexed by \a lang strings.
114 */
115static Tree* treeForLanguage(const QString &lang)
116{
117 Tree* tree = trees.value(lang);
118 if (tree == 0) {
119 tree = new Tree;
120 trees.insert( lang, tree );
121 }
122 return tree;
123}
124
125/*!
126 Print the help message to \c stdout.
127 */
128static void printHelp()
129{
130 Location::information(tr("Usage: qdoc [options] file1.qdocconf ...\n"
131 "Options:\n"
132 " -help "
133 "Display this information and exit\n"
134 " -version "
135 "Display version of qdoc and exit\n"
136 " -D<name> "
137 "Define <name> as a macro while parsing sources\n"
138 " -slow "
139 "Turn on features that slow down qdoc\n"
140 " -showinternal "
141 "Include stuff marked internal\n"
142 " -obsoletelinks "
143 "Report links from obsolete items to non-obsolete items") );
144}
145
146/*!
147 Prints the qdoc version number to stdout.
148 */
149static void printVersion()
150{
151 QString s = tr("qdoc version %1").arg(QT_VERSION_STR);
152 Location::information(s);
153}
154
155/*!
156 Processes the qdoc config file \a fileName. This is the
157 controller for all of qdoc.
158 */
159static void processQdocconfFile(const QString &fileName)
160{
161#ifndef QT_NO_TRANSLATION
162 QList<QTranslator *> translators;
163#endif
164
165 /*
166 The Config instance represents the configuration data for qdoc.
167 All the other classes are initialized with the config. Here we
168 initialize the configuration with some default values.
169 */
170 Config config(tr("qdoc"));
171 int i = 0;
172 while (defaults[i].key) {
173 config.setStringList(defaults[i].key,
174 QStringList() << defaults[i].value);
175 ++i;
176 }
177 config.setStringList(CONFIG_SLOW, QStringList(slow ? "true" : "false"));
178 config.setStringList(CONFIG_SHOWINTERNAL,
179 QStringList(showInternal ? "true" : "false"));
180 config.setStringList(CONFIG_OBSOLETELINKS,
181 QStringList(obsoleteLinks ? "true" : "false"));
182
183 /*
184 With the default configuration values in place, load
185 the qdoc configuration file. Note that the configuration
186 file may include other configuration files.
187
188 The Location class keeps track of the current location
189 in the file being processed, mainly for error reporting
190 purposes.
191 */
192 Location::initialize(config);
193 config.load(fileName);
194
195 /*
196 Set the application to which qdoc will create the output.
197 The two applications are:
198
199 creator: additional formatting for viewing in
200 the Creator application.
201
202 online: full-featured online version with search and
203 links to Qt topics
204 */
205 if (appArg.isEmpty()) {
206 qDebug() << "Warning: Application flag not specified on"
207 << "command line. Options are -creator (default)"
208 << "and -online.";
209 appArg = "creator";
210 }
211 config.setStringList(CONFIG_APPLICATION, QStringList(appArg));
212
213 /*
214 Add the defines to the configuration variables.
215 */
216 QStringList defs = defines + config.getStringList(CONFIG_DEFINES);
217 config.setStringList(CONFIG_DEFINES,defs);
218 Location::terminate();
219
220 QString prevCurrentDir = QDir::currentPath();
221 QString dir = QFileInfo(fileName).path();
222 if (!dir.isEmpty())
223 QDir::setCurrent(dir);
224
225 /*
226 Initialize all the classes and data structures with the
227 qdoc configuration.
228 */
229 Location::initialize(config);
230 Tokenizer::initialize(config);
231 Doc::initialize(config);
232 CppToQsConverter::initialize(config);
233 CodeMarker::initialize(config);
234 CodeParser::initialize(config);
235 Generator::initialize(config);
236
237#ifndef QT_NO_TRANSLATION
238 /*
239 Load the language translators, if the configuration specifies any.
240 */
241 QStringList fileNames = config.getStringList(CONFIG_TRANSLATORS);
242 QStringList::Iterator fn = fileNames.begin();
243 while (fn != fileNames.end()) {
244 QTranslator *translator = new QTranslator(0);
245 if (!translator->load(*fn))
246 config.lastLocation().error(tr("Cannot load translator '%1'")
247 .arg(*fn));
248 QCoreApplication::instance()->installTranslator(translator);
249 translators.append(translator);
250 ++fn;
251 }
252#endif
253
254 //QSet<QString> outputLanguages = config.getStringSet(CONFIG_OUTPUTLANGUAGES);
255
256 /*
257 Get the source language (Cpp) from the configuration
258 and the location in the configuration file where the
259 source language was set.
260 */
261 QString lang = config.getString(CONFIG_LANGUAGE);
262 Location langLocation = config.lastLocation();
263
264 /*
265 Initialize the tree where all the parsed sources will be stored.
266 The tree gets built as the source files are parsed, and then the
267 documentation output is generated by traversing the tree.
268 */
269 Tree *tree = new Tree;
270 tree->setVersion(config.getString(CONFIG_VERSION));
271
272 /*
273 There must be a code parser for the source code language, e.g. C++.
274 If there isn't one, give up.
275 */
276 CodeParser *codeParser = CodeParser::parserForLanguage(lang);
277 if (codeParser == 0)
278 config.lastLocation().fatal(tr("Cannot parse programming language '%1'").arg(lang));
279
280 /*
281 By default, the only output format is HTML.
282 */
283 QSet<QString> outputFormats = config.getStringSet(CONFIG_OUTPUTFORMATS);
284 Location outputFormatsLocation = config.lastLocation();
285
286 /*
287 There must be a code marker for the source code language, e.g. C++.
288 If there isn't one, give up.
289 */
290 CodeMarker *marker = CodeMarker::markerForLanguage(lang);
291 if (!marker && !outputFormats.isEmpty())
292 langLocation.fatal(tr("Cannot output documentation for programming language '%1'").arg(lang));
293
294 /*
295 Read some XML indexes. What are they???
296 */
297 QStringList indexFiles = config.getStringList(CONFIG_INDEXES);
298 tree->readIndexes(indexFiles);
299
300 /*
301 Get all the header files: "*.ch *.h *.h++ *.hh *.hpp *.hxx"
302 Put them in a set.
303 */
304 QSet<QString> excludedDirs;
305 QStringList excludedDirsList = config.getStringList(CONFIG_EXCLUDEDIRS);
306 foreach (const QString &excludeDir, excludedDirsList)
307 excludedDirs.insert(QDir::fromNativeSeparators(excludeDir));
308 QSet<QString> headers = QSet<QString>::fromList(
309 config.getAllFiles(CONFIG_HEADERS, CONFIG_HEADERDIRS,
310 codeParser->headerFileNameFilter(),
311 excludedDirs));
312
313 /*
314 Parse each header file in the set and add it to the big tree.
315 */
316 QSet<QString>::ConstIterator h = headers.begin();
317 while (h != headers.end()) {
318 codeParser->parseHeaderFile(config.location(), *h, tree);
319 ++h;
320 }
321 codeParser->doneParsingHeaderFiles(tree);
322
323 /*
324 Get all the source text files: "*.cpp *.qdoc *.mm"
325 Put them in a set.
326 */
327 QSet<QString> sources = QSet<QString>::fromList(
328 config.getAllFiles(CONFIG_SOURCES, CONFIG_SOURCEDIRS,
329 codeParser->sourceFileNameFilter(),
330 excludedDirs));
331
332 /*
333 Parse each source text file in the set and add it to the big tree.
334 */
335 QSet<QString>::ConstIterator s = sources.begin();
336 while (s != sources.end()) {
337 codeParser->parseSourceFile(config.location(), *s, tree);
338 ++s;
339 }
340 codeParser->doneParsingSourceFiles(tree);
341
342 /*
343 Now the big tree has been built from all the header and
344 source files. Resolve all the class names, function names,
345 targets, URLs, links, and other stuff that needs resolving.
346 */
347 tree->resolveGroups();
348 tree->resolveTargets();
349
350 /*
351 Now the tree has been built, and all the stuff that needed
352 resolving has been resolved. Now it is time to traverse
353 the big tree and generate the documentation output.
354 */
355 QSet<QString>::ConstIterator of = outputFormats.begin();
356 while (of != outputFormats.end()) {
357 Generator *generator = Generator::generatorForFormat(*of);
358 if (generator == 0)
359 outputFormatsLocation.fatal(tr("Unknown output format '%1'")
360 .arg(*of));
361 generator->generateTree(tree, marker);
362 ++of;
363 }
364
365 /*
366 Generate the XML tag file, if it was requested.
367 */
368 QString tagFile = config.getString(CONFIG_TAGFILE);
369 if (!tagFile.isEmpty()) {
370 tree->generateTagFile(tagFile);
371 }
372
373 tree->setVersion("");
374 Generator::terminate();
375 CodeParser::terminate();
376 CodeMarker::terminate();
377 CppToQsConverter::terminate();
378 Doc::terminate();
379 Tokenizer::terminate();
380 Location::terminate();
381 QDir::setCurrent(prevCurrentDir);
382
383#ifndef QT_NO_TRANSLATION
384 qDeleteAll(translators);
385#endif
386#ifdef DEBUG_SHUTDOWN_CRASH
387 qDebug() << "main(): Delete tree";
388#endif
389 delete tree;
390#ifdef DEBUG_SHUTDOWN_CRASH
391 qDebug() << "main(): Tree deleted";
392#endif
393}
394
395QT_END_NAMESPACE
396
397int main(int argc, char **argv)
398{
399 QT_USE_NAMESPACE
400
401#ifndef QT_BOOTSTRAPPED
402 QCoreApplication app(argc, argv);
403#endif
404 QString cf = "qsauncompress \1 \2";
405 PolyArchiveExtractor qsaExtractor(QStringList() << "qsa",cf);
406 cf = "tar -C \2 -xf \1";
407 PolyArchiveExtractor tarExtractor(QStringList() << "tar",cf);
408 cf = "tar -C \2 -Zxf \1";
409 PolyArchiveExtractor tazExtractor(QStringList() << "taz",cf);
410 cf = "tar -C \2 -jxf \1";
411 PolyArchiveExtractor tbz2Extractor(QStringList() << "tbz" << "tbz2",cf);
412 cf = "tar -C \2 -zxf \1";
413 PolyArchiveExtractor tgzExtractor(QStringList() << "tgz",cf);
414 cf = "unzip \1 -d \2";
415 PolyArchiveExtractor zipExtractor(QStringList() << "zip",cf);
416 cf = "bunzip2 -c \1 > \2";
417 PolyUncompressor bz2Uncompressor(QStringList() << "bz" << "bz2",cf);
418 cf = "gunzip -c \1 > \2";
419 PolyUncompressor gzAndZUncompressor(QStringList() << "gz" << "z" << "Z",cf);
420 cf = "unzip -c \1 > \2";
421 PolyUncompressor zipUncompressor(QStringList() << "zip",cf);
422
423 /*
424 Create code parsers for the languages to be parsed,
425 and create a tree for C++.
426 */
427 CppCodeParser cppParser;
428 Tree *cppTree = treeForLanguage(cppParser.language());
429
430 QsCodeParser qsParser(cppTree);
431 QsaKernelParser qsaKernelParser(cppTree);
432 JambiApiParser jambiParser(cppTree);
433
434 /*
435 Create code markers for plain text, C++, Java, and qs.
436 */
437 PlainCodeMarker plainMarker;
438 CppCodeMarker cppMarker;
439 JavaCodeMarker javaMarker;
440 QsCodeMarker qsMarker;
441
442 ApiGenerator apiGenerator;
443 HtmlGenerator htmlGenerator;
444 JavadocGenerator javadocGenerator;
445 LinguistGenerator linguistGenerator;
446 LoutGenerator loutGenerator;
447 ManGenerator manGenerator;
448 SgmlGenerator smglGenerator;
449 WebXMLGenerator webxmlGenerator;
450 DitaXmlGenerator ditaxmlGenerator;
451
452 QStringList qdocFiles;
453 QString opt;
454 int i = 1;
455
456 while (i < argc) {
457 opt = argv[i++];
458
459 if (opt == "-help") {
460 printHelp();
461 return EXIT_SUCCESS;
462 }
463 else if (opt == "-version") {
464 printVersion();
465 return EXIT_SUCCESS;
466 }
467 else if (opt == "--") {
468 while (i < argc)
469 qdocFiles.append(argv[i++]);
470 }
471 else if (opt.startsWith("-D")) {
472 QString define = opt.mid(2);
473 defines += define;
474 }
475 else if (opt == "-slow") {
476 slow = true;
477 }
478 else if (opt == "-showinternal") {
479 showInternal = true;
480 }
481 else if (opt == "-obsoletelinks") {
482 obsoleteLinks = true;
483 }
484 else if (opt == "-creator")
485 appArg = "creator";
486 else if (opt == "-online")
487 appArg = "online";
488 else {
489 qdocFiles.append(opt);
490 }
491 }
492
493 if (qdocFiles.isEmpty()) {
494 printHelp();
495 return EXIT_FAILURE;
496 }
497
498 /*
499 Main loop.
500 */
501 foreach (QString qf, qdocFiles) {
502 //qDebug() << "PROCESSING:" << qf;
503 processQdocconfFile(qf);
504 }
505
506 qDeleteAll(trees);
507 return EXIT_SUCCESS;
508}
509
Note: See TracBrowser for help on using the repository browser.