Warning: That file was not part of the compilation database. It may have many parsing errors.
1 | /**************************************************************************** |
---|---|
2 | ** |
3 | ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). |
4 | ** Contact: http://www.qt-project.org/legal |
5 | ** |
6 | ** This file is part of the tools applications of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and Digia. For licensing terms and |
14 | ** conditions see http://qt.digia.com/licensing. For further information |
15 | ** use the contact form at http://qt.digia.com/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 2.1 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 2.1 requirements |
23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
24 | ** |
25 | ** In addition, as a special exception, Digia gives you certain additional |
26 | ** rights. These rights are described in the Digia Qt LGPL Exception |
27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
28 | ** |
29 | ** GNU General Public License Usage |
30 | ** Alternatively, this file may be used under the terms of the GNU |
31 | ** General Public License version 3.0 as published by the Free Software |
32 | ** Foundation and appearing in the file LICENSE.GPL included in the |
33 | ** packaging of this file. Please review the following information to |
34 | ** ensure the GNU General Public License version 3.0 requirements will be |
35 | ** met: http://www.gnu.org/copyleft/gpl.html. |
36 | ** |
37 | ** |
38 | ** $QT_END_LICENSE$ |
39 | ** |
40 | ****************************************************************************/ |
41 | |
42 | #include <QtDebug> |
43 | #include "config.h" |
44 | #include "location.h" |
45 | |
46 | #include <qregexp.h> |
47 | #include <qtranslator.h> |
48 | #include <stdlib.h> |
49 | #include <limits.h> |
50 | |
51 | #include <stdio.h> |
52 | |
53 | QT_BEGIN_NAMESPACE |
54 | |
55 | QT_STATIC_CONST_IMPL Location Location::null; |
56 | |
57 | int Location::tabSize; |
58 | QString Location::programName; |
59 | QRegExp *Location::spuriousRegExp = 0; |
60 | |
61 | /*! |
62 | \class Location |
63 | |
64 | \brief The Location class keeps track of where we are in a file. |
65 | |
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. |
70 | */ |
71 | |
72 | /*! |
73 | Constructs an empty location. |
74 | */ |
75 | Location::Location() |
76 | : stk(0), stkTop(&stkBottom), stkDepth(0), etcetera(false) |
77 | { |
78 | // nothing. |
79 | } |
80 | |
81 | /*! |
82 | Constructs a location with (fileName, 1, 1) on its file |
83 | position stack. |
84 | */ |
85 | Location::Location(const QString& fileName) |
86 | : stk(0), stkTop(&stkBottom), stkDepth(0), etcetera(false) |
87 | { |
88 | push(fileName); |
89 | } |
90 | |
91 | /*! |
92 | The copy constructor copies the contents of \a other into |
93 | this Location using the assignment operator. |
94 | */ |
95 | Location::Location(const Location& other) |
96 | : stk(0), stkTop(&stkBottom), stkDepth(0), etcetera(false) |
97 | { |
98 | *this = other; |
99 | } |
100 | |
101 | /*! |
102 | The assignment operator does a deep copy of the entire |
103 | state of \a other into this Location. |
104 | */ |
105 | Location& Location::operator=(const Location& other) |
106 | { |
107 | QStack<StackEntry> *oldStk = stk; |
108 | |
109 | stkBottom = other.stkBottom; |
110 | if (other.stk == 0) { |
111 | stk = 0; |
112 | stkTop = &stkBottom; |
113 | } |
114 | else { |
115 | stk = new QStack<StackEntry>(*other.stk); |
116 | stkTop = &stk->top(); |
117 | } |
118 | stkDepth = other.stkDepth; |
119 | etcetera = other.etcetera; |
120 | delete oldStk; |
121 | return *this; |
122 | } |
123 | |
124 | /*! |
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. |
128 | */ |
129 | void Location::start() |
130 | { |
131 | if (stkTop->lineNo < 1) { |
132 | stkTop->lineNo = 1; |
133 | stkTop->columnNo = 1; |
134 | } |
135 | } |
136 | |
137 | /*! |
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. |
142 | |
143 | The current file position is the one on top of the position stack. |
144 | */ |
145 | void Location::advance(QChar ch) |
146 | { |
147 | if (ch == QLatin1Char( |
148 | stkTop->lineNo++; |
149 | stkTop->columnNo = 1; |
150 | } |
151 | else if (ch == QLatin1Char( |
152 | stkTop->columnNo = |
153 | 1 + tabSize * (stkTop->columnNo + tabSize-1) / tabSize; |
154 | } |
155 | else { |
156 | stkTop->columnNo++; |
157 | } |
158 | } |
159 | |
160 | /*! |
161 | Pushes \a filePath onto the file position stack. The current |
162 | file position becomes (\a filePath, 1, 1). |
163 | |
164 | \sa pop() |
165 | */ |
166 | void Location::push(const QString& filePath) |
167 | { |
168 | if (stkDepth++ >= 1) { |
169 | if (stk == 0) |
170 | stk = new QStack<StackEntry>; |
171 | stk->push(StackEntry()); |
172 | stkTop = &stk->top(); |
173 | } |
174 | |
175 | stkTop->filePath = filePath; |
176 | stkTop->lineNo = INT_MIN; |
177 | stkTop->columnNo = 1; |
178 | } |
179 | |
180 | /*! |
181 | Pops the top of the internal stack. The current file position |
182 | becomes the next one in the new top of stack. |
183 | |
184 | \sa push() |
185 | */ |
186 | void Location::pop() |
187 | { |
188 | if (--stkDepth == 0) { |
189 | stkBottom = StackEntry(); |
190 | } |
191 | else { |
192 | stk->pop(); |
193 | if (stk->isEmpty()) { |
194 | delete stk; |
195 | stk = 0; |
196 | stkTop = &stkBottom; |
197 | } |
198 | else { |
199 | stkTop = &stk->top(); |
200 | } |
201 | } |
202 | } |
203 | |
204 | /*! \fn bool Location::isEmpty() const |
205 | |
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. |
209 | */ |
210 | |
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. |
214 | |
215 | \sa lineNo(), columnNo() |
216 | */ |
217 | |
218 | /*! |
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. |
222 | */ |
223 | QString Location::fileName() const |
224 | { |
225 | QString fp = filePath(); |
226 | return fp.mid(fp.lastIndexOf( |
227 | } |
228 | |
229 | /*! \fn int Location::lineNo() const |
230 | Returns the current line number. |
231 | Must not be called on an empty Location object. |
232 | |
233 | \sa filePath(), columnNo() |
234 | */ |
235 | |
236 | /*! \fn int Location::columnNo() const |
237 | Returns the current column number. |
238 | Must not be called on an empty Location object. |
239 | |
240 | \sa filePath(), lineNo() |
241 | */ |
242 | |
243 | /*! |
244 | Writes \a message and \a detals to stderr as a formatted |
245 | warning message. |
246 | */ |
247 | void Location::warning(const QString& message, const QString& details) const |
248 | { |
249 | emitMessage(Warning, message, details); |
250 | } |
251 | |
252 | /*! |
253 | Writes \a message and \a detals to stderr as a formatted |
254 | error message. |
255 | */ |
256 | void Location::error(const QString& message, const QString& details) const |
257 | { |
258 | emitMessage(Error, message, details); |
259 | } |
260 | |
261 | /*! |
262 | Writes \a message and \a detals to stderr as a formatted |
263 | error message and then exits the program. |
264 | */ |
265 | void Location::fatal(const QString& message, const QString& details) const |
266 | { |
267 | emitMessage(Error, message, details); |
268 | information(message); |
269 | information(details); |
270 | information("Aborting"); |
271 | exit(EXIT_FAILURE); |
272 | } |
273 | |
274 | /*! |
275 | Gets several parameters from the \a config, including |
276 | tab size, program name, and a regular expression that |
277 | appears to be used for matching certain error messages |
278 | so that emitMessage() can avoid printing them. |
279 | */ |
280 | void Location::initialize(const Config& config) |
281 | { |
282 | tabSize = config.getInt(CONFIG_TABSIZE); |
283 | programName = config.programName(); |
284 | |
285 | QRegExp regExp = config.getRegExp(CONFIG_SPURIOUS); |
286 | if (regExp.isValid()) { |
287 | spuriousRegExp = new QRegExp(regExp); |
288 | } |
289 | else { |
290 | config.lastLocation().warning(tr("Invalid regular expression '%1'") |
291 | .arg(regExp.pattern())); |
292 | } |
293 | } |
294 | |
295 | /*! |
296 | Apparently, all this does is delete the regular expression |
297 | used for intercepting certain error messages that should |
298 | not be emitted by emitMessage(). |
299 | */ |
300 | void Location::terminate() |
301 | { |
302 | delete spuriousRegExp; |
303 | spuriousRegExp = 0; |
304 | } |
305 | |
306 | /*! |
307 | Prints \a message to \c stdout followed by a \c{'\n'}. |
308 | */ |
309 | void Location::information(const QString& message) |
310 | { |
311 | printf("%s\n", message.toLatin1().data()); |
312 | fflush(stdout); |
313 | } |
314 | |
315 | /*! |
316 | Report a program bug, including the \a hint. |
317 | */ |
318 | void Location::internalError(const QString& hint) |
319 | { |
320 | Location::null.fatal(tr("Internal error (%1)").arg(hint), |
321 | tr("There is a bug in %1. Seek advice from your local" |
322 | " %2 guru.") |
323 | .arg(programName).arg(programName)); |
324 | } |
325 | |
326 | /*! |
327 | Formats \a message and \a details into a single string |
328 | and outputs that string to \c stderr. \a type specifies |
329 | whether the \a message is an error or a warning. |
330 | */ |
331 | void Location::emitMessage(MessageType type, |
332 | const QString& message, |
333 | const QString& details) const |
334 | { |
335 | if (type == Warning && |
336 | spuriousRegExp != 0 && |
337 | spuriousRegExp->exactMatch(message)) |
338 | return; |
339 | |
340 | QString result = message; |
341 | if (!details.isEmpty()) |
342 | result += "\n["+ details + "]"; |
343 | result.replace("\n", "\n "); |
344 | if (type == Error) |
345 | result.prepend(tr("error: ")); |
346 | result.prepend(toString()); |
347 | fprintf(stderr, "%s\n", result.toLatin1().data()); |
348 | fflush(stderr); |
349 | } |
350 | |
351 | /*! |
352 | Converts the location to a string to be prepended to error |
353 | messages. |
354 | */ |
355 | QString Location::toString() const |
356 | { |
357 | QString str; |
358 | |
359 | if (isEmpty()) { |
360 | str = programName; |
361 | } |
362 | else { |
363 | Location loc2 = *this; |
364 | loc2.setEtc(false); |
365 | loc2.pop(); |
366 | if (!loc2.isEmpty()) { |
367 | QString blah = tr("In file included from "); |
368 | for (;;) { |
369 | str += blah; |
370 | str += loc2.top(); |
371 | loc2.pop(); |
372 | if (loc2.isEmpty()) |
373 | break; |
374 | str += tr(","); |
375 | str += QLatin1Char( |
376 | blah.fill( |
377 | } |
378 | str += tr(":"); |
379 | str += QLatin1Char( |
380 | } |
381 | str += top(); |
382 | } |
383 | str += QLatin1String(": "); |
384 | return str; |
385 | } |
386 | |
387 | QString Location::top() const |
388 | { |
389 | QString str = filePath(); |
390 | if (lineNo() >= 1) { |
391 | str += QLatin1Char( |
392 | str += QString::number(lineNo()); |
393 | } |
394 | if (etc()) |
395 | str += QLatin1String(" (etc.)"); |
396 | return str; |
397 | } |
398 | |
399 | QT_END_NAMESPACE |
400 |
Warning: That file was not part of the compilation database. It may have many parsing errors.