1 /****************************************************************************
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the tools applications of the Qt Toolkit.
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
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.
40 ****************************************************************************/
47 #include <qtranslator.h>
55 QT_STATIC_CONST_IMPL Location
Location::null
;
57 int Location::tabSize
;
58 QString
Location::programName
;
59 QRegExp
*Location::spuriousRegExp
= 0;
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.
73 Constructs an empty location.
76 : stk(0), stkTop(&stkBottom
), stkDepth(0), etcetera(false)
82 Constructs a location with (fileName, 1, 1) on its file
85 Location::Location(const QString
& fileName
)
86 : stk(0), stkTop(&stkBottom
), stkDepth(0), etcetera(false)
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)
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) {
115 stk
= new QStack
<StackEntry
>(*other
.stk
);
116 stkTop
= &stk
->top();
118 stkDepth
= other
.stkDepth
;
119 etcetera
= other
.etcetera
;
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) {
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')) {
149 stkTop
->columnNo
= 1;
151 else if (ch
== QLatin1Char('\t')) {
153 1 + tabSize
* (stkTop
->columnNo
+ tabSize
-1) / tabSize
;
161 Pushes \a filePath onto the file position stack. The current
162 file position becomes (\a filePath, 1, 1).
166 void Location::push(const QString
& filePath
)
168 if (stkDepth
++ >= 1) {
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.
188 if (--stkDepth
== 0) {
189 stkBottom
= StackEntry();
193 if (stk
->isEmpty()) {
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
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
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
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");
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
);
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
;
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());
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"
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
))
338 QString result
= message
;
339 if (!details
.isEmpty())
340 result
+= "\n[" + details
+ "]";
341 result
.replace("\n", "\n ");
343 result
.prepend(tr("error: "));
344 result
.prepend(toString());
345 fprintf(stderr
, "%s\n", result
.toLatin1().data());
350 Converts the location to a string to be prepended to error
353 QString
Location::toString() const
361 Location loc2
= *this;
364 if (!loc2
.isEmpty()) {
365 QString blah
= tr("In file included from ");
373 str
+= QLatin1Char('\n');
377 str
+= QLatin1Char('\n');
381 str
+= QLatin1String(": ");
385 QString
Location::top() const
387 QString str
= filePath();
389 str
+= QLatin1Char(':');
390 str
+= QString::number(lineNo());
393 str
+= ":" + QString::number(columnNo());
397 str
+= QLatin1String(" (etc.)");