source: trunk/tools/qdoc3/config.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: 26.4 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 config.cpp
44*/
45
46#include <QDir>
47#include <QVariant>
48#include <QFile>
49#include <QTemporaryFile>
50#include <QTextStream>
51
52#include "archiveextractor.h"
53#include "config.h"
54#include "uncompressor.h"
55#include <stdlib.h>
56
57QT_BEGIN_NAMESPACE
58
59/*
60 An entry on the MetaStack.
61 */
62class MetaStackEntry
63{
64public:
65 void open();
66 void close();
67
68 QStringList accum;
69 QStringList next;
70};
71
72/*
73 */
74void MetaStackEntry::open()
75{
76 next.append(QString());
77}
78
79/*
80 */
81void MetaStackEntry::close()
82{
83 accum += next;
84 next.clear();
85}
86
87/*
88 ###
89*/
90class MetaStack : private QStack<MetaStackEntry>
91{
92public:
93 MetaStack();
94
95 void process(QChar ch, const Location& location);
96 QStringList getExpanded(const Location& location);
97};
98
99MetaStack::MetaStack()
100{
101 push(MetaStackEntry());
102 top().open();
103}
104
105void MetaStack::process(QChar ch, const Location& location)
106{
107 if (ch == QLatin1Char('{')) {
108 push(MetaStackEntry());
109 top().open();
110 }
111 else if (ch == QLatin1Char('}')) {
112 if (count() == 1)
113 location.fatal(tr("Unexpected '}'"));
114
115 top().close();
116 QStringList suffixes = pop().accum;
117 QStringList prefixes = top().next;
118
119 top().next.clear();
120 QStringList::ConstIterator pre = prefixes.begin();
121 while (pre != prefixes.end()) {
122 QStringList::ConstIterator suf = suffixes.begin();
123 while (suf != suffixes.end()) {
124 top().next << (*pre + *suf);
125 ++suf;
126 }
127 ++pre;
128 }
129 }
130 else if (ch == QLatin1Char(',') && count() > 1) {
131 top().close();
132 top().open();
133 }
134 else {
135 QStringList::Iterator pre = top().next.begin();
136 while (pre != top().next.end()) {
137 *pre += ch;
138 ++pre;
139 }
140 }
141}
142
143QStringList MetaStack::getExpanded(const Location& location)
144{
145 if (count() > 1)
146 location.fatal(tr("Missing '}'"));
147
148 top().close();
149 return top().accum;
150}
151
152QT_STATIC_CONST_IMPL QString Config::dot = QLatin1String(".");
153QMap<QString, QString> Config::uncompressedFiles;
154QMap<QString, QString> Config::extractedDirs;
155int Config::numInstances;
156
157/*!
158 \class Config
159 \brief The Config class contains the configuration variables
160 for controlling how qdoc produces documentation.
161
162 Its load() function, reads, parses, and processes a qdocconf file.
163 */
164
165/*!
166 The constructor sets the \a programName and initializes all
167 internal state variables to empty values.
168 */
169Config::Config(const QString& programName)
170 : prog(programName)
171{
172 loc = Location::null;
173 lastLoc = Location::null;
174 locMap.clear();
175 stringValueMap.clear();
176 stringListValueMap.clear();
177 numInstances++;
178}
179
180/*!
181 The destructor deletes all the temporary files and
182 directories it built.
183 */
184Config::~Config()
185{
186 if (--numInstances == 0) {
187 QMap<QString, QString>::ConstIterator f = uncompressedFiles.begin();
188 while (f != uncompressedFiles.end()) {
189 QDir().remove(*f);
190 ++f;
191 }
192 uncompressedFiles.clear();
193
194 QMap<QString, QString>::ConstIterator d = extractedDirs.begin();
195 while (d != extractedDirs.end()) {
196 removeDirContents(*d);
197 QDir dir(*d);
198 QString name = dir.dirName();
199 dir.cdUp();
200 dir.rmdir(name);
201 ++d;
202 }
203 extractedDirs.clear();
204 }
205}
206
207/*!
208 Loads and parses the qdoc configuration file \a fileName.
209 This function calls the other load() function, which does
210 the loading, parsing, and processing of the configuration
211 file.
212
213 Intializes the location variables returned by location()
214 and lastLocation().
215 */
216void Config::load(const QString& fileName)
217{
218 load(Location::null, fileName);
219 if (loc.isEmpty()) {
220 loc = Location(fileName);
221 }
222 else {
223 loc.setEtc(true);
224 }
225 lastLoc = Location::null;
226}
227
228/*!
229 Joins all the strings in \a values into a single string with the
230 individual \a values separated by ' '. Then it inserts the result
231 into the string list map with \a var as the key.
232
233 It also inserts the \a values string list into a separate map,
234 also with \a var as the key.
235 */
236void Config::setStringList(const QString& var, const QStringList& values)
237{
238 stringValueMap[var] = values.join(QLatin1String(" "));
239 stringListValueMap[var] = values;
240}
241
242/*!
243 Looks up the configuarion variable \a var in the string
244 map and returns the boolean value.
245 */
246bool Config::getBool(const QString& var) const
247{
248 return QVariant(getString(var)).toBool();
249}
250
251/*!
252 Looks up the configuration variable \a var in the string list
253 map. Iterates through the string list found, interpreting each
254 string in the list as an integer and adding it to a total sum.
255 Returns the sum.
256 */
257int Config::getInt(const QString& var) const
258{
259 QStringList strs = getStringList(var);
260 QStringList::ConstIterator s = strs.begin();
261 int sum = 0;
262
263 while (s != strs.end()) {
264 sum += (*s).toInt();
265 ++s;
266 }
267 return sum;
268}
269
270/*!
271 First, this function looks up the configuration variable \a var
272 in the location map and, if found, sets the internal variable
273 \c{lastLoc} to the Location that \a var maps to.
274
275 Then it looks up the configuration variable \a var in the string
276 map, and returns the string that \a var maps to.
277 */
278QString Config::getString(const QString& var) const
279{
280 if (!locMap[var].isEmpty())
281 (Location&) lastLoc = locMap[var];
282 return stringValueMap[var];
283}
284
285/*!
286 Looks up the configuration variable \a var in the string
287 list map, converts the string list it maps to into a set
288 of strings, and returns the set.
289 */
290QSet<QString> Config::getStringSet(const QString& var) const
291{
292 return QSet<QString>::fromList(getStringList(var));
293}
294
295/*!
296 First, this function looks up the configuration variable \a var
297 in the location map and, if found, sets the internal variable
298 \c{lastLoc} the Location that \a var maps to.
299
300 Then it looks up the configuration variable \a var in the string
301 list map, and returns the string list that \a var maps to.
302 */
303QStringList Config::getStringList(const QString& var) const
304{
305 if (!locMap[var].isEmpty())
306 (Location&) lastLoc = locMap[var];
307 return stringListValueMap[var];
308}
309
310/*!
311 Calls getRegExpList() with the control variable \a var and
312 iterates through the resulting list of regular expressions,
313 concatening them with some extras characters to form a single
314 QRegExp, which is returned/
315
316 \sa getRegExpList()
317 */
318QRegExp Config::getRegExp(const QString& var) const
319{
320 QString pattern;
321 QList<QRegExp> subRegExps = getRegExpList(var);
322 QList<QRegExp>::ConstIterator s = subRegExps.begin();
323
324 while (s != subRegExps.end()) {
325 if (!(*s).isValid())
326 return *s;
327 if (!pattern.isEmpty())
328 pattern += QLatin1Char('|');
329 pattern += QLatin1String("(?:") + (*s).pattern() + QLatin1Char(')');
330 ++s;
331 }
332 if (pattern.isEmpty())
333 pattern = QLatin1String("$x"); // cannot match
334 return QRegExp(pattern);
335}
336
337/*!
338 Looks up the configuration variable \a var in the string list
339 map, converts the string list to a list of regular expressions,
340 and returns it.
341 */
342QList<QRegExp> Config::getRegExpList(const QString& var) const
343{
344 QStringList strs = getStringList(var);
345 QStringList::ConstIterator s = strs.begin();
346 QList<QRegExp> regExps;
347
348 while (s != strs.end()) {
349 regExps += QRegExp(*s);
350 ++s;
351 }
352 return regExps;
353}
354
355/*!
356 This function is slower than it could be.
357 */
358QSet<QString> Config::subVars(const QString& var) const
359{
360 QSet<QString> result;
361 QString varDot = var + QLatin1Char('.');
362 QMap<QString, QString>::ConstIterator v = stringValueMap.begin();
363 while (v != stringValueMap.end()) {
364 if (v.key().startsWith(varDot)) {
365 QString subVar = v.key().mid(varDot.length());
366 int dot = subVar.indexOf(QLatin1Char('.'));
367 if (dot != -1)
368 subVar.truncate(dot);
369 result.insert(subVar);
370 }
371 ++v;
372 }
373 return result;
374}
375
376/*!
377 Builds and returns a list of file pathnames for the file
378 type specified by \a filesVar (e.g. "headers" or "sources").
379 The files are found in the directories specified by
380 \a dirsVar, and they are filtered by \a defaultNameFilter
381 if a better filter can't be constructed from \a filesVar.
382 The directories in \a excludedDirs are avoided.
383 */
384QStringList Config::getAllFiles(const QString &filesVar,
385 const QString &dirsVar,
386 const QString &defaultNameFilter,
387 const QSet<QString> &excludedDirs)
388{
389 QStringList result = getStringList(filesVar);
390 QStringList dirs = getStringList(dirsVar);
391
392 QString nameFilter = getString(filesVar + dot +
393 QLatin1String(CONFIG_FILEEXTENSIONS));
394 if (nameFilter.isEmpty())
395 nameFilter = defaultNameFilter;
396
397 QStringList::ConstIterator d = dirs.begin();
398 while (d != dirs.end()) {
399 result += getFilesHere(*d, nameFilter, excludedDirs);
400 ++d;
401 }
402 return result;
403}
404
405/*!