1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the tools applications of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
54 QT_STATIC_CONST_IMPL Location Location::null;
56 int Location::tabSize;
57 QString Location::programName;
58 QRegExp *Location::spuriousRegExp = 0;
63 \brief The Location class provides a way to mark a location in a file.
65 It maintains a stack of file positions. A file position
66 consists of the file path, line number, and column number.
67 The location is used for printing error messages that are
68 tied to a location in a file.
72 Constructs an empty location.
75 : stk(0), stkTop(&stkBottom), stkDepth(0), etcetera(false)
81 Constructs a location with (fileName, 1, 1) on its file
84 Location::Location(const QString& fileName)
85 : stk(0), stkTop(&stkBottom), stkDepth(0), etcetera(false)
91 The copy constructor copies the contents of \a other into
92 this Location using the assignment operator.
94 Location::Location(const Location& other)
95 : stk(0), stkTop(&stkBottom), stkDepth(0), etcetera(false)
101 The assignment operator does a deep copy of the entire
102 state of \a other into this Location.
104 Location& Location::operator=(const Location& other)
106 QStack<StackEntry> *oldStk = stk;
108 stkBottom = other.stkBottom;
109 if (other.stk == 0) {
114 stk = new QStack<StackEntry>(*other.stk);
115 stkTop = &stk->top();
117 stkDepth = other.stkDepth;
118 etcetera = other.etcetera;
124 If the file position on top of the stack has a line number
125 less than 1, set its line number to 1 and its column number
126 to 1. Otherwise, do nothing.
128 void Location::start()
130 if (stkTop->lineNo < 1) {
132 stkTop->columnNo = 1;
137 Advance the current file position, using \a ch to decide how to do
138 that. If \a ch is a \c{'\\n'}, increment the current line number and
139 set the column number to 1. If \ch is a \c{'\\t'}, increment to the
140 next tab column. Otherwise, increment the column number by 1.
142 The current file position is the one on top of the position stack.
144 void Location::advance(QChar ch)
146 if (ch == QLatin1Char('\n')) {
148 stkTop->columnNo = 1;
150 else if (ch == QLatin1Char('\t')) {
152 1 + tabSize * (stkTop->columnNo + tabSize-1) / tabSize;
160 Pushes \a filePath onto the file position stack. The current
161 file position becomes (\a filePath, 1, 1).
165 void Location::push(const QString& filePath)
167 if (stkDepth++ >= 1) {
169 stk = new QStack<StackEntry>;
170 stk->push(StackEntry());
171 stkTop = &stk->top();
174 stkTop->filePath = filePath;
175 stkTop->lineNo = INT_MIN;
176 stkTop->columnNo = 1;
180 Pops the top of the internal stack. The current file position
181 becomes the next one in the new top of stack.
187 if (--stkDepth == 0) {
188 stkBottom = StackEntry();
192 if (stk->isEmpty()) {
198 stkTop = &stk->top();
203 /*! \fn bool Location::isEmpty() const
205 Returns true if there is no file name set yet; returns false
206 otherwise. The functions filePath(), lineNo() and columnNo()
207 must not be called on an empty Location object.
210 /*! \fn const QString& Location::filePath() const
211 Returns the current path and file name.
212 Must not be called on an empty Location object.
214 \sa lineNo(), columnNo()
218 Returns the file name part of the file path, ie the
219 current file. Must not be called on an empty Location
222 QString Location::fileName() const
224 QString fp = filePath();
225 return fp.mid(fp.lastIndexOf('/') + 1);
228 /*! \fn int Location::lineNo() const
229 Returns the current line number.
230 Must not be called on an empty Location object.
232 \sa filePath(), columnNo()
235 /*! \fn int Location::columnNo() const
236 Returns the current column number.
237 Must not be called on an empty Location object.
239 \sa filePath(), lineNo()
243 Writes \a message and \a detals to stderr as a formatted
246 void Location::warning(const QString& message, const QString& details) const
248 emitMessage(Warning, message, details);
252 Writes \a message and \a detals to stderr as a formatted
255 void Location::error(const QString& message, const QString& details) const
257 emitMessage(Error, message, details);
261 Writes \a message and \a detals to stderr as a formatted
262 error message and then exits the program.
264 void Location::fatal(const QString& message, const QString& details) const
266 emitMessage(Error, message, details);
267 information(message);
268 information(details);
269 information("Aborting");
274 Gets several parameters from the \a config, including
275 tab size, program name, and a regular expression that
276 appears to be used for matching certain error messages
277 so that emitMessage() can avoid printing them.
279 void Location::initialize(const Config& config)
281 tabSize = config.getInt(CONFIG_TABSIZE);
282 programName = config.programName();
284 QRegExp regExp = config.getRegExp(CONFIG_SPURIOUS);
285 if (regExp.isValid()) {
286 spuriousRegExp = new QRegExp(regExp);
289 config.lastLocation().warning(tr("Invalid regular expression '%1'")
290 .arg(regExp.pattern()));
295 Apparently, all this does is delete the regular expression
296 used for intercepting certain error messages that should
297 not be emitted by emitMessage().
299 void Location::terminate()
301 delete spuriousRegExp;
306 Prints \a message to \c stdout followed by a \c{'\n'}.
308 void Location::information(const QString& message)
310 printf("%s\n", message.toLatin1().data());
315 Report a program bug, including the \a hint.
317 void Location::internalError(const QString& hint)
319 Location::null.fatal(tr("Internal error (%1)").arg(hint),
320 tr("There is a bug in %1. Seek advice from your local"
322 .arg(programName).arg(programName));
326 Formats \a message and \a details into a single string
327 and outputs that string to \c stderr. \a type specifies
328 whether the \a message is an error or a warning.
330 void Location::emitMessage(MessageType type,
331 const QString& message,
332 const QString& details) const
334 if (type == Warning &&
335 spuriousRegExp != 0 &&
336 spuriousRegExp->exactMatch(message))
339 QString result = message;
340 if (!details.isEmpty())
341 result += "\n[" + details + QLatin1Char(']');
342 result.replace("\n", "\n ");
344 result.prepend(tr("error: "));
345 result.prepend(toString());
346 fprintf(stderr, "%s\n", result.toLatin1().data());
351 Converts the location to a string to be prepended to error
354 QString Location::toString() const
362 Location loc2 = *this;
365 if (!loc2.isEmpty()) {
366 QString blah = tr("In file included from ");
374 str += QLatin1Char('\n');
378 str += QLatin1Char('\n');
382 str += QLatin1String(": ");
386 QString Location::top() const
388 QString str = filePath();
390 str += QLatin1Char(':');
391 str += QString::number(lineNo());
394 str += QLatin1String(" (etc.)");