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

Last change on this file since 814 was 651, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.2 sources.

File size: 14.4 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 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 <QtCore>
48#include <stdlib.h>
49#include "apigenerator.h"
50#include "codemarker.h"
51#include "codeparser.h"
52#include "config.h"
53#include "cppcodemarker.h"
54#include "cppcodeparser.h"
55#include "cpptoqsconverter.h"
56#include "doc.h"
57#include "htmlgenerator.h"
58#include "jambiapiparser.h"
59#include "javacodemarker.h"
60#include "javadocgenerator.h"
61#include "linguistgenerator.h"
62#include "loutgenerator.h"
63#include "mangenerator.h"
64#include "plaincodemarker.h"
65#include "polyarchiveextractor.h"
66#include "polyuncompressor.h"
67#include "qsakernelparser.h"
68#include "qscodemarker.h"
69#include "qscodeparser.h"
70#include "sgmlgenerator.h"
71#include "webxmlgenerator.h"
72#include "tokenizer.h"
73#include "tree.h"
74
75QT_BEGIN_NAMESPACE
76
77/*
78 The default indent for code is 4.
79 The default value for false is 0.
80 The default language is c++.
81 The default output format is html.
82 The default tab size is 8.
83 And those are all the default values for configuration variables.
84 */
85static const struct {
86 const char *key;
87 const char *value;
88} defaults[] = {
89 { CONFIG_CODEINDENT, "4" },
90 { CONFIG_FALSEHOODS, "0" },
91 { CONFIG_LANGUAGE, "Cpp" },
92 { CONFIG_OUTPUTFORMATS, "HTML" },
93 { CONFIG_TABSIZE, "8" },
94 { 0, 0 }
95};
96
97static bool slow = false;
98static bool showInternal = false;
99static bool obsoleteLinks = false;
100static QStringList defines;
101static QHash<QString, Tree *> trees;
102
103/*!
104 Find the Tree for language \a lang and return a pointer to it.
105 If there is no Tree for language \a lang in the Tree table, add
106 a new one. The Tree table is indexed by \a lang strings.
107 */
108static Tree* treeForLanguage(const QString &lang)
109{
110 Tree* tree = trees.value(lang);
111 if (tree == 0) {
112 tree = new Tree;
113 trees.insert( lang, tree );
114 }
115 return tree;
116}
117
118/*!
119 Print the help message to \c stdout.
120 */
121static void printHelp()
122{
123 Location::information(tr("Usage: qdoc [options] file1.qdocconf ...\n"
124 "Options:\n"
125 " -help "
126 "Display this information and exit\n"
127 " -version "
128 "Display version of qdoc and exit\n"
129 " -D<name> "
130 "Define <name> as a macro while parsing sources\n"
131 " -slow "
132 "Turn on features that slow down qdoc\n"
133 " -showinternal "
134 "Include stuff marked internal\n"
135 " -obsoletelinks "
136 "Report links from obsolete items to non-obsolete items") );
137}
138
139/*!
140 Prints the qdoc version number to stdout.
141 */
142static void printVersion()
143{
144 QString s = QString(tr("qdoc version ")) + QString(QT_VERSION_STR);
145 Location::information(s);
146}
147
148/*!
149 Processes the qdoc config file \a fileName. This is the
150 controller for all of qdoc.
151 */
152static void processQdocconfFile(const QString &fileName)
153{
154 QList<QTranslator *> translators;
155
156 /*
157 The Config instance represents the configuration data for qdoc.
158 All the other classes are initialized with the config. Here we
159 initialize the configuration with some default values.
160 */
161 Config config(tr("qdoc"));
162 int i = 0;
163 while (defaults[i].key) {
164 config.setStringList(defaults[i].key,
165 QStringList() << defaults[i].value);
166 ++i;
167 }
168 config.setStringList(CONFIG_SLOW, QStringList(slow ? "true" : "false"));
169 config.setStringList(CONFIG_SHOWINTERNAL,
170 QStringList(showInternal ? "true" : "false"));
171 config.setStringList(CONFIG_OBSOLETELINKS,
172 QStringList(obsoleteLinks ? "true" : "false"));
173
174 /*
175 With the default configuration values in place, load
176 the qdoc configuration file. Note that the configuration
177 file may include other configuration files.
178
179 The Location class keeps track of the current location
180 in the file being processed, mainly for error reporting
181 purposes.
182 */
183 Location::initialize(config);
184 config.load(fileName);
185
186 /*
187 Add the defines to the configuration variables.
188 */
189 QStringList defs = defines + config.getStringList(CONFIG_DEFINES);
190 config.setStringList(CONFIG_DEFINES,defs);
191 Location::terminate();
192
193 QString prevCurrentDir = QDir::currentPath();
194 QString dir = QFileInfo(fileName).path();
195 if (!dir.isEmpty())
196 QDir::setCurrent(dir);
197
198 /*
199 Initialize all the classes and data structures with the
200 qdoc configuration.
201 */
202 Location::initialize(config);
203 Tokenizer::initialize(config);
204 Doc::initialize(config);
205 CppToQsConverter::initialize(config);
206 CodeMarker::initialize(config);
207 CodeParser::initialize(config);
208 Generator::initialize(config);
209
210 /*
211 Load the language translators, if the configuration specifies any.
212 */
213 QStringList fileNames = config.getStringList(CONFIG_TRANSLATORS);
214 QStringList::Iterator fn = fileNames.begin();
215 while (fn != fileNames.end()) {
216 QTranslator *translator = new QTranslator(0);
217 if (!translator->load(*fn))
218 config.lastLocation().error(tr("Cannot load translator '%1'")
219 .arg(*fn));
220 QCoreApplication::instance()->installTranslator(translator);
221 translators.append(translator);
222 ++fn;
223 }
224
225 //QSet<QString> outputLanguages = config.getStringSet(CONFIG_OUTPUTLANGUAGES);
226
227 /*
228 Get the source language (Cpp) from the configuration
229 and the location in the configuration file where the
230 source language was set.
231 */
232 QString lang = config.getString(CONFIG_LANGUAGE);
233 Location langLocation = config.lastLocation();
234
235 /*
236 Initialize the tree where all the parsed sources will be stored.
237 The tree gets built as the source files are parsed, and then the
238 documentation output is generated by traversing the tree.
239 */
240 Tree *tree = new Tree;
241 tree->setVersion(config.getString(CONFIG_VERSION));
242
243 /*
244 There must be a code parser for the source code language, e.g. C++.
245 If there isn't one, give up.
246 */
247 CodeParser *codeParser = CodeParser::parserForLanguage(lang);
248 if (codeParser == 0)
249 config.lastLocation().fatal(tr("Cannot parse programming language '%1'").arg(lang));
250
251 /*
252 By default, the only output format is HTML.
253 */
254 QSet<QString> outputFormats = config.getStringSet(CONFIG_OUTPUTFORMATS);
255 Location outputFormatsLocation = config.lastLocation();
256
257 /*
258 There must be a code marker for the source code language, e.g. C++.
259 If there isn't one, give up.
260 */
261 CodeMarker *marker = CodeMarker::markerForLanguage(lang);
262 if (!marker && !outputFormats.isEmpty())
263 langLocation.fatal(tr("Cannot output documentation for programming language '%1'").arg(lang));
264
265 /*
266 Read some XML indexes. What are they???
267 */
268 QStringList indexFiles = config.getStringList(CONFIG_INDEXES);
269 tree->readIndexes(indexFiles);
270
271 /*
272 Get all the header files: "*.ch *.h *.h++ *.hh *.hpp *.hxx"
273 Put them in a set.
274 */
275 QSet<QString> excludedDirs;
276 QStringList excludedDirsList = config.getStringList(CONFIG_EXCLUDEDIRS);
277 foreach (const QString &excludeDir, excludedDirsList)
278 excludedDirs.insert(QDir::fromNativeSeparators(excludeDir));
279 QSet<QString> headers = QSet<QString>::fromList(
280 config.getAllFiles(CONFIG_HEADERS, CONFIG_HEADERDIRS,
281 codeParser->headerFileNameFilter(),
282 excludedDirs));
283
284 /*
285 Parse each header file in the set and add it to the big tree.
286 */
287 QSet<QString>::ConstIterator h = headers.begin();
288 while (h != headers.end()) {
289 codeParser->parseHeaderFile(config.location(), *h, tree);
290 ++h;
291 }
292 codeParser->doneParsingHeaderFiles(tree);
293
294 /*
295 Get all the source text files: "*.cpp *.qdoc *.mm"
296 Put them in a set.
297 */
298 QSet<QString> sources = QSet<QString>::fromList(
299 config.getAllFiles(CONFIG_SOURCES, CONFIG_SOURCEDIRS,
300 codeParser->sourceFileNameFilter(),
301 excludedDirs));
302
303 /*
304 Parse each source text file in the set and add it to the big tree.
305 */
306 QSet<QString>::ConstIterator s = sources.begin();
307 while (s != sources.end()) {
308 codeParser->parseSourceFile(config.location(), *s, tree);
309 ++s;
310 }
311 codeParser->doneParsingSourceFiles(tree);
312
313 /*
314 Now the big tree has been built from all the header and
315 source files. Resolve all the class names, function names,
316 targets, URLs, links, and other stuff that needs resolving.
317 */
318 tree->resolveGroups();
319 tree->resolveTargets();
320
321 /*
322 Now the tree has been built, and all the stuff that needed
323 resolving has been resolved. Now it is time to traverse
324 the big tree and generate the documentation output.
325 */
326 QSet<QString>::ConstIterator of = outputFormats.begin();
327 while (of != outputFormats.end()) {
328 Generator *generator = Generator::generatorForFormat(*of);
329 if (generator == 0)
330 outputFormatsLocation.fatal(tr("Unknown output format '%1'")
331 .arg(*of));
332 generator->generateTree(tree, marker);
333 ++of;
334 }
335
336 /*
337 Generate the XML tag file, if it was requested.
338 */
339 QString tagFile = config.getString(CONFIG_TAGFILE);
340 if (!tagFile.isEmpty())
341 tree->generateTagFile(tagFile);
342
343 tree->setVersion("");
344 Generator::terminate();
345 CodeParser::terminate();
346 CodeMarker::terminate();
347 CppToQsConverter::terminate();
348 Doc::terminate();
349 Tokenizer::terminate();
350 Location::terminate();
351 QDir::setCurrent(prevCurrentDir);
352
353 foreach (QTranslator *translator, translators)
354 delete translator;
355 delete tree;
356}
357
358QT_END_NAMESPACE
359
360int main(int argc, char **argv)
361{
362 QT_USE_NAMESPACE
363
364 QCoreApplication app(argc, argv);
365 QString cf = "qsauncompress \1 \2";
366 PolyArchiveExtractor qsaExtractor(QStringList() << "qsa",cf);
367 cf = "tar -C \2 -xf \1";
368 PolyArchiveExtractor tarExtractor(QStringList() << "tar",cf);
369 cf = "tar -C \2 -Zxf \1";
370 PolyArchiveExtractor tazExtractor(QStringList() << "taz",cf);
371 cf = "tar -C \2 -jxf \1";
372 PolyArchiveExtractor tbz2Extractor(QStringList() << "tbz" << "tbz2",cf);
373 cf = "tar -C \2 -zxf \1";
374 PolyArchiveExtractor tgzExtractor(QStringList() << "tgz",cf);
375 cf = "unzip \1 -d \2";
376 PolyArchiveExtractor zipExtractor(QStringList() << "zip",cf);
377 cf = "bunzip2 -c \1 > \2";
378 PolyUncompressor bz2Uncompressor(QStringList() << "bz" << "bz2",cf);
379 cf = "gunzip -c \1 > \2";
380 PolyUncompressor gzAndZUncompressor(QStringList() << "gz" << "z" << "Z",cf);
381 cf = "unzip -c \1 > \2";
382 PolyUncompressor zipUncompressor(QStringList() << "zip",cf);
383
384 /*
385 Create code parsers for the languages to be parsed,
386 and create a tree for C++.
387 */
388 CppCodeParser cppParser;
389 Tree *cppTree = treeForLanguage(cppParser.language());
390
391 QsCodeParser qsParser(cppTree);
392 QsaKernelParser qsaKernelParser(cppTree);
393 JambiApiParser jambiParser(cppTree);
394
395 /*
396 Create code markers for plain text, C++, Java, and qs.
397 */
398 PlainCodeMarker plainMarker;
399 CppCodeMarker cppMarker;
400 JavaCodeMarker javaMarker;
401 QsCodeMarker qsMarker;
402
403 ApiGenerator apiGenerator;
404 HtmlGenerator htmlGenerator;
405 JavadocGenerator javadocGenerator;
406 LinguistGenerator linguistGenerator;
407 LoutGenerator loutGenerator;
408 ManGenerator manGenerator;
409 SgmlGenerator smglGenerator;
410 WebXMLGenerator webxmlGenerator;
411
412 QStringList qdocFiles;
413 QString opt;
414 int i = 1;
415
416 while (i < argc) {
417 opt = argv[i++];
418
419 if (opt == "-help") {
420 printHelp();
421 return EXIT_SUCCESS;
422 }
423 else if (opt == "-version") {
424 printVersion();
425 return EXIT_SUCCESS;
426 }
427 else if (opt == "--") {
428 while (i < argc)
429 qdocFiles.append(argv[i++]);
430 }
431 else if (opt.startsWith("-D")) {
432 QString define = opt.mid(2);
433 defines += define;
434 }
435 else if (opt == "-slow") {
436 slow = true;
437 }
438 else if (opt == "-showinternal") {
439 showInternal = true;
440 }
441 else if (opt == "-obsoletelinks") {
442 obsoleteLinks = true;
443 }
444 else {
445 qdocFiles.append(opt);
446 }
447 }
448
449 if (qdocFiles.isEmpty()) {
450 printHelp();
451 return EXIT_FAILURE;
452 }
453
454 /*
455 Main loop.
456 */
457 foreach (QString qf, qdocFiles)
458 processQdocconfFile(qf);
459
460 qDeleteAll(trees);
461 return EXIT_SUCCESS;
462}
463
Note: See TracBrowser for help on using the repository browser.