Merge branch 'master' of scm.dev.nokia.troll.no:qt/oslo-staging-1 into master-integration
[qt-netbsd.git] / tools / qdoc3 / location.cpp
blob19625da9e2a2907334c9deb96e3ca780a079bb22
1 /****************************************************************************
2 **
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the tools applications of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
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.
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.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
38 ** $QT_END_LICENSE$
40 ****************************************************************************/
42 #include <QtDebug>
43 #include "config.h"
44 #include "location.h"
46 #include <qregexp.h>
47 #include <qtranslator.h>
48 #include <stdlib.h>
49 #include <limits.h>
51 #include <stdio.h>
53 QT_BEGIN_NAMESPACE
55 QT_STATIC_CONST_IMPL Location Location::null;
57 int Location::tabSize;
58 QString Location::programName;
59 QRegExp *Location::spuriousRegExp = 0;
61 /*!
62 \class Location
64 \brief The Location class keeps track of where we are in a file.
66 It maintains a stack of file positions. A file position
67 consists of the file path, line number, and column number.
68 The location is used for printing error messages that are
69 tied to a location in a file.
72 /*!
73 Constructs an empty location.
75 Location::Location()
76 : stk(0), stkTop(&stkBottom), stkDepth(0), etcetera(false)
78 // nothing.
81 /*!
82 Constructs a location with (fileName, 1, 1) on its file
83 position stack.
85 Location::Location(const QString& fileName)
86 : stk(0), stkTop(&stkBottom), stkDepth(0), etcetera(false)
88 push(fileName);
91 /*!
92 The copy constructor copies the contents of \a other into
93 this Location using the assignment operator.
95 Location::Location(const Location& other)
96 : stk(0), stkTop(&stkBottom), stkDepth(0), etcetera(false)
98 *this = other;
102 The assignment operator does a deep copy of the entire
103 state of \a other into this Location.
105 Location& Location::operator=(const Location& other)
107 QStack<StackEntry> *oldStk = stk;
109 stkBottom = other.stkBottom;
110 if (other.stk == 0) {
111 stk = 0;
112 stkTop = &stkBottom;
114 else {
115 stk = new QStack<StackEntry>(*other.stk);
116 stkTop = &stk->top();
118 stkDepth = other.stkDepth;
119 etcetera = other.etcetera;
120 delete oldStk;
121 return *this;
125 If the file position on top of the stack has a line number
126 less than 1, set its line number to 1 and its column number
127 to 1. Otherwise, do nothing.
129 void Location::start()
131 if (stkTop->lineNo < 1) {
132 stkTop->lineNo = 1;
133 stkTop->columnNo = 1;
138 Advance the current file position, using \a ch to decide how to do
139 that. If \a ch is a \c{'\\n'}, increment the current line number and
140 set the column number to 1. If \ch is a \c{'\\t'}, increment to the
141 next tab column. Otherwise, increment the column number by 1.
143 The current file position is the one on top of the position stack.
145 void Location::advance(QChar ch)
147 if (ch == QLatin1Char('\n')) {
148 stkTop->lineNo++;
149 stkTop->columnNo = 1;
151 else if (ch == QLatin1Char('\t')) {
152 stkTop->columnNo =
153 1 + tabSize * (stkTop->columnNo + tabSize-1) / tabSize;
155 else {
156 stkTop->columnNo++;
161 Pushes \a filePath onto the file position stack. The current
162 file position becomes (\a filePath, 1, 1).
164 \sa pop()
166 void Location::push(const QString& filePath)
168 if (stkDepth++ >= 1) {
169 if (stk == 0)
170 stk = new QStack<StackEntry>;
171 stk->push(StackEntry());
172 stkTop = &stk->top();
175 stkTop->filePath = filePath;
176 stkTop->lineNo = INT_MIN;
177 stkTop->columnNo = 1;
181 Pops the top of the internal stack. The current file position
182 becomes the next one in the new top of stack.
184 \sa push()
186 void Location::pop()
188 if (--stkDepth == 0) {
189 stkBottom = StackEntry();
191 else {
192 stk->pop();
193 if (stk->isEmpty()) {
194 delete stk;
195 stk = 0;
196 stkTop = &stkBottom;
198 else {
199 stkTop = &stk->top();
204 /*! \fn bool Location::isEmpty() const
206 Returns true if there is no file name set yet; returns false
207 otherwise. The functions filePath(), lineNo() and columnNo()
208 must not be called on an empty Location object.
211 /*! \fn const QString& Location::filePath() const
212 Returns the current path and file name.
213 Must not be called on an empty Location object.
215 \sa lineNo(), columnNo()
219 Returns the file name part of the file path, ie the
220 current file. Must not be called on an empty Location
221 object.
223 QString Location::fileName() const
225 QString fp = filePath();
226 return fp.mid(fp.lastIndexOf('/') + 1);
229 /*! \fn int Location::lineNo() const
230 Returns the current line number.
231 Must not be called on an empty Location object.
233 \sa filePath(), columnNo()
236 /*! \fn int Location::columnNo() const
237 Returns the current column number.
238 Must not be called on an empty Location object.
240 \sa filePath(), lineNo()
244 Writes \a message and \a detals to stderr as a formatted
245 warning message.
247 void Location::warning(const QString& message, const QString& details) const
249 emitMessage(Warning, message, details);
253 Writes \a message and \a detals to stderr as a formatted
254 error message.
256 void Location::error(const QString& message, const QString& details) const
258 emitMessage(Error, message, details);
262 Writes \a message and \a detals to stderr as a formatted
263 error message and then exits the program.
265 void Location::fatal(const QString& message, const QString& details) const
267 emitMessage(Error, message, details);
268 information("Aborting");
269 exit(EXIT_FAILURE);
273 Gets several parameters from the \a config, including
274 tab size, program name, and a regular expression that
275 appears to be used for matching certain error messages
276 so that emitMessage() can avoid printing them.
278 void Location::initialize(const Config& config)
280 tabSize = config.getInt(CONFIG_TABSIZE);
281 programName = config.programName();
283 QRegExp regExp = config.getRegExp(CONFIG_SPURIOUS);
284 if (regExp.isValid()) {
285 spuriousRegExp = new QRegExp(regExp);
287 else {
288 config.lastLocation().warning(tr("Invalid regular expression '%1'")
289 .arg(regExp.pattern()));
294 Apparently, all this does is delete the regular expression
295 used for intercepting certain error messages that should
296 not be emitted by emitMessage().
298 void Location::terminate()
300 delete spuriousRegExp;
301 spuriousRegExp = 0;
305 Prints \a message to \c stdout followed by a \c{'\n'}.
307 void Location::information(const QString& message)
309 printf("%s\n", message.toLatin1().data());
310 fflush(stdout);
314 Report a program bug, including the \a hint.
316 void Location::internalError(const QString& hint)
318 Location::null.fatal(tr("Internal error (%1)").arg(hint),
319 tr("There is a bug in %1. Seek advice from your local"
320 " %2 guru.")
321 .arg(programName).arg(programName));
325 Formats \a message and \a details into a single string
326 and outputs that string to \c stderr. \a type specifies
327 whether the \a message is an error or a warning.
329 void Location::emitMessage(MessageType type,
330 const QString& message,
331 const QString& details) const
333 if (type == Warning &&
334 spuriousRegExp != 0 &&
335 spuriousRegExp->exactMatch(message))
336 return;
338 QString result = message;
339 if (!details.isEmpty())
340 result += "\n[" + details + "]";
341 result.replace("\n", "\n ");
342 if (type == Error)
343 result.prepend(tr("error: "));
344 result.prepend(toString());
345 fprintf(stderr, "%s\n", result.toLatin1().data());
346 fflush(stderr);
350 Converts the location to a string to be prepended to error
351 messages.
353 QString Location::toString() const
355 QString str;
357 if (isEmpty()) {
358 str = programName;
360 else {
361 Location loc2 = *this;
362 loc2.setEtc(false);
363 loc2.pop();
364 if (!loc2.isEmpty()) {
365 QString blah = tr("In file included from ");
366 for (;;) {
367 str += blah;
368 str += loc2.top();
369 loc2.pop();
370 if (loc2.isEmpty())
371 break;
372 str += tr(",");
373 str += QLatin1Char('\n');
374 blah.fill(' ');
376 str += tr(":");
377 str += QLatin1Char('\n');
379 str += top();
381 str += QLatin1String(": ");
382 return str;
385 QString Location::top() const
387 QString str = filePath();
388 if (lineNo() >= 1) {
389 str += QLatin1Char(':');
390 str += QString::number(lineNo());
391 #if 0
392 if (columnNo() >= 1)
393 str += ":" + QString::number(columnNo());
394 #endif
396 if (etc())
397 str += QLatin1String(" (etc.)");
398 return str;
401 QT_END_NAMESPACE