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

Last change on this file since 500 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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