~ubuntu-branches/debian/sid/kdevelop/sid

« back to all changes in this revision

Viewing changes to languages/cpp/parser/rpp/pp-stream.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jeremy Lainé
  • Date: 2010-05-05 07:21:55 UTC
  • mfrom: (1.2.3 upstream) (5.1.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100505072155-h78lx19pu04sbhtn
Tags: 4:4.0.0-2
* Upload to unstable (Closes: #579947, #481832).
* Acknowledge obsolete NMU fixes (Closes: #562410, #546961).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  Copyright 2006 Hamish Rodda <rodda@kde.org>
 
3
  Copyright 2008-2009 David Nolden <david.nolden.kdevelop@art-master.de>
 
4
 
 
5
  Permission to use, copy, modify, distribute, and sell this software and its
 
6
  documentation for any purpose is hereby granted without fee, provided that
 
7
  the above copyright notice appear in all copies and that both that
 
8
  copyright notice and this permission notice appear in supporting
 
9
  documentation.
 
10
 
 
11
  The above copyright notice and this permission notice shall be included in
 
12
  all copies or substantial portions of the Software.
 
13
 
 
14
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
15
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
16
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 
17
  KDEVELOP TEAM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 
18
  AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
19
  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
20
*/
 
21
 
 
22
#include "pp-stream.h"
 
23
 
 
24
///@todo Better splitting of input and output functionality
 
25
 
 
26
#include <kdebug.h>
 
27
 
 
28
#include "pp-location.h"
 
29
#include "chartools.h"
 
30
#include <language/duchain/indexedstring.h>
 
31
 
 
32
using namespace rpp;
 
33
 
 
34
const unsigned int Stream::newline(indexFromCharacter('\n'));
 
35
static unsigned int nullItem(0);
 
36
const unsigned int deepLine(indexFromCharacter('_'));
 
37
 
 
38
// bool shouldMergeTo(uint previous) {
 
39
//   return !isCharacter(previous) || previous == deepLine || isLetter(previous);
 
40
// }
 
41
// 
 
42
// bool shouldMerge(uint follower) {
 
43
//   return !isCharacter(follower) || follower == deepLine || isLetterOrNumber(follower);
 
44
// }
 
45
 
 
46
Stream::Stream()
 
47
  : m_string(new PreprocessedContents())
 
48
  , m_isNull(true)
 
49
  , m_skippedToEnd(false)
 
50
  , m_inputPositionLocked(false)
 
51
  , m_onwsString(true)
 
52
  , m_macroExpansion(KDevelop::SimpleCursor::invalid())
 
53
  , m_pos(0)
 
54
  , m_inputLine(0)
 
55
  , m_inputLineStartedAt(0)
 
56
  , m_locationTable(0L)
 
57
  , m_originalInputPosition(KDevelop::SimpleCursor::invalid())
 
58
{
 
59
  end = 0;
 
60
}
 
61
 
 
62
Stream::Stream( PreprocessedContents * string, const Anchor& offset, LocationTable* table )
 
63
  : m_string(string)
 
64
  , m_isNull(false)
 
65
  , m_skippedToEnd(false)
 
66
  , m_inputPositionLocked(false)
 
67
  , m_onwsString(false)
 
68
  , m_macroExpansion(KDevelop::SimpleCursor::invalid())
 
69
  , m_pos(0)
 
70
  , m_inputLine(offset.line)
 
71
  , m_inputLineStartedAt(-offset.column)
 
72
  , m_locationTable(table)
 
73
  , m_originalInputPosition(KDevelop::SimpleCursor::invalid())
 
74
{
 
75
  if(offset.collapsed)
 
76
    m_inputPositionLocked = true;
 
77
  c = m_string->constData();
 
78
  end = m_string->constData() + m_string->size();
 
79
}
 
80
 
 
81
Stream::Stream( const uint * string, uint stringSize, const Anchor& offset, LocationTable* table )
 
82
  : m_string(new PreprocessedContents(stringSize))
 
83
  , m_isNull(false)
 
84
  , m_skippedToEnd(false)
 
85
  , m_inputPositionLocked(false)
 
86
  , m_onwsString(true)
 
87
  , m_macroExpansion(KDevelop::SimpleCursor::invalid())
 
88
  , m_pos(0)
 
89
  , m_inputLine(offset.line)
 
90
  , m_inputLineStartedAt(-offset.column)
 
91
  , m_locationTable(table)
 
92
  , m_originalInputPosition(KDevelop::SimpleCursor::invalid())
 
93
{
 
94
  memcpy(m_string->data(), string, stringSize * sizeof(uint));
 
95
  if(offset.collapsed)
 
96
    m_inputPositionLocked = true;
 
97
  c = m_string->constData();
 
98
  end = m_string->constData() + m_string->size();
 
99
}
 
100
 
 
101
Stream::Stream( PreprocessedContents * string, LocationTable* table )
 
102
  : m_string(string)
 
103
  , m_isNull(false)
 
104
  , m_skippedToEnd(false)
 
105
  , m_inputPositionLocked(false)
 
106
  , m_onwsString(false)
 
107
  , m_macroExpansion(KDevelop::SimpleCursor::invalid())
 
108
  , m_pos(0)
 
109
  , m_inputLine(0)
 
110
  , m_inputLineStartedAt(0)
 
111
  , m_locationTable(table)
 
112
  , m_originalInputPosition(KDevelop::SimpleCursor::invalid())
 
113
{
 
114
  c = m_string->constData();
 
115
  end = m_string->constData() + m_string->size();
 
116
}
 
117
 
 
118
Stream::~Stream()
 
119
{
 
120
  if (m_onwsString)
 
121
    delete m_string;
 
122
}
 
123
 
 
124
Stream& Stream::operator--()
 
125
{
 
126
  if (c == m_string->constData())
 
127
    return *this;
 
128
 
 
129
  --c;
 
130
  --m_pos;
 
131
 
 
132
  if(m_inputPositionLocked)
 
133
    --m_inputLineStartedAt;
 
134
  else
 
135
    m_inputLineStartedAt -= (1-KDevelop::IndexedString::lengthFromIndex(*c));
 
136
 
 
137
 
 
138
  return *this;
 
139
}
 
140
 
 
141
bool Stream::atEnd() const
 
142
{
 
143
  return c == end;
 
144
}
 
145
 
 
146
void Stream::toEnd()
 
147
{
 
148
  m_skippedToEnd = true;
 
149
  c = end;
 
150
}
 
151
 
 
152
bool Stream::skippedToEnd() const
 
153
{
 
154
  return m_skippedToEnd;
 
155
}
 
156
 
 
157
const uint& Stream::peek(uint offset) const
 
158
{
 
159
  if (c + offset >= end)
 
160
    return nullItem;
 
161
 
 
162
  return *(c + offset);
 
163
}
 
164
 
 
165
int Stream::offset( ) const
 
166
{
 
167
  return m_pos;
 
168
}
 
169
 
 
170
void Stream::seek(int offset)
 
171
{
 
172
  if(m_inputPositionLocked){
 
173
    m_inputLineStartedAt = offset + (m_inputLineStartedAt - m_pos);
 
174
  }else{
 
175
    if(offset < m_pos) {
 
176
      for(int a = offset; a < m_pos; ++a)
 
177
        m_inputLineStartedAt -= (1-KDevelop::IndexedString::lengthFromIndex(m_string->at(a)));
 
178
    }else{
 
179
      for(int a = m_pos; a < offset; ++a)
 
180
        m_inputLineStartedAt += (1-KDevelop::IndexedString::lengthFromIndex(m_string->at(a)));
 
181
    }
 
182
  }
 
183
  
 
184
  c = m_string->constData() + offset;
 
185
  m_pos = offset;
 
186
  if (c > end) {
 
187
    c = end;
 
188
    m_pos = m_string->size();
 
189
  }
 
190
}
 
191
 
 
192
Stream & Stream::operator<< ( const unsigned int& c )
 
193
{
 
194
  // Keep in sync with below
 
195
  if (!m_isNull) {
 
196
    
 
197
/*    if(m_pos > 0) {
 
198
      unsigned int& previous( (*m_string)[m_pos-1] );
 
199
      if(shouldMergeTo(previous)) {
 
200
        if(shouldMerge(c)) {
 
201
          //We have to merge with the previous character, so we get a correct tokenization. This should not happen too often.
 
202
          previous = KDevelop::IndexedString(KDevelop::IndexedString(previous).byteArray() + KDevelop::IndexedString(c).byteArray()).index();
 
203
          kDebug() << "merging" << KDevelop::IndexedString(previous).str() << "and" << KDevelop::IndexedString(c).str();
 
204
          return *this;
 
205
        }
 
206
      }
 
207
    }*/
 
208
    
 
209
    ++m_pos;
 
210
 
 
211
    if (c == newline) {
 
212
      ++m_inputLine;
 
213
      m_inputLineStartedAt = m_pos; ///@todo remove
 
214
    }
 
215
 
 
216
    m_string->append(c);
 
217
  }
 
218
  return *this;
 
219
}
 
220
 
 
221
unsigned int rpp::Stream::popLastOutput() {
 
222
  unsigned int ret = m_string->last();
 
223
  m_string->pop_back();
 
224
  --m_pos;
 
225
  return ret;
 
226
}
 
227
 
 
228
unsigned int rpp::Stream::peekLastOutput(uint backOffset) const {
 
229
  if(m_pos - backOffset > 0)
 
230
    return m_string->at(m_pos - backOffset - 1);
 
231
  return 0;
 
232
}
 
233
 
 
234
Stream& Stream::operator<< ( const Stream& input )
 
235
{
 
236
  const uint c = input;
 
237
 
 
238
  // Keep in sync with above
 
239
  if (!m_isNull) {
 
240
    
 
241
/*    if(m_pos > 0) {
 
242
      unsigned int& previous( (*m_string)[m_pos-1] );
 
243
      if(shouldMergeTo(previous)) {
 
244
        if(shouldMerge(c)) {
 
245
          //We have to merge with the previous character, so we get a correct tokenization. This should not happen too often.
 
246
          previous = KDevelop::IndexedString(KDevelop::IndexedString(previous).byteArray() + KDevelop::IndexedString(c).byteArray()).index();
 
247
          kDebug() << "merging" << KDevelop::IndexedString(previous).str() << "and" << KDevelop::IndexedString(c).str();
 
248
          return *this;
 
249
        }
 
250
      }
 
251
    }*/
 
252
    
 
253
    ++m_pos;
 
254
 
 
255
    m_string->append(c);
 
256
    
 
257
    if (c == newline) {
 
258
      Anchor inputPosition = input.inputPosition();
 
259
      ++m_inputLine;
 
260
      m_inputLineStartedAt = m_pos; ///@todo remove
 
261
      if(!inputPosition.collapsed)
 
262
        mark(Anchor(inputPosition.line + 1, 0, false, m_macroExpansion));
 
263
    }
 
264
  }
 
265
  return *this;
 
266
}
 
267
 
 
268
Stream& Stream::appendString( const Anchor& inputPosition, const PreprocessedContents & string )
 
269
{
 
270
  if (!isNull()) {
 
271
    
 
272
//     uint offset = 0;
 
273
    
 
274
/*    if(m_pos > 0 && string.size()) {
 
275
      //Eventually merge the tokens. This shouldn't happen too often
 
276
      int size = string.size();
 
277
      unsigned int& previous( (*m_string)[m_pos-1] );
 
278
      for(int a = 0; a < size; ++a) {
 
279
        if(shouldMergeTo(previous)) {
 
280
          if(shouldMerge(string[a])) {
 
281
            //We have to merge with the previous character, so we get a correct tokenization. This should not happen too often.
 
282
            previous = KDevelop::IndexedString(KDevelop::IndexedString(previous).byteArray() + KDevelop::IndexedString(string[a]).byteArray()).index();
 
283
            ++offset;
 
284
            kDebug() << "merging" << KDevelop::IndexedString(previous).str() << "and" << KDevelop::IndexedString(string[a]).str();
 
285
            continue;
 
286
          }
 
287
        }
 
288
        break;
 
289
      }
 
290
    }*/
 
291
    
 
292
   // if(!offset) ///@todo think about his. We lose the input position, but on the other hand the merging should only happen when ## was used
 
293
      mark(inputPosition);
 
294
    
 
295
    *m_string+= string;
 
296
 
 
297
    int extraLines = 0;
 
298
    for (int i = 0; i < string.size(); ++i) {
 
299
      
 
300
      if (string.at(i) == newline) {
 
301
        m_pos += i + 1; //Move the current offset to that position, so the marker is set correctly
 
302
        if(!inputPosition.collapsed)
 
303
          mark(Anchor(inputPosition.line + ++extraLines, 0, false, m_macroExpansion));
 
304
        m_pos -= i + 1;
 
305
      }
 
306
    }
 
307
 
 
308
    m_pos += string.size();
 
309
 
 
310
    // TODO check correctness Probably remove
 
311
    m_inputLineStartedAt = m_pos - (string.size() - string.lastIndexOf(newline)); ///@todo remove
 
312
  }
 
313
  return *this;
 
314
}
 
315
 
 
316
Stream& Stream::appendString( const Anchor& inputPosition, KDevelop::IndexedString string )
 
317
{
 
318
 
 
319
  if (!isNull()) {
 
320
    
 
321
/*    if(m_pos > 0) {
 
322
      //Eventually merge
 
323
      unsigned int& previous( (*m_string)[m_pos-1] );
 
324
      if(shouldMergeTo(previous)) {
 
325
        if(shouldMerge(string.index())) {
 
326
          //We have to merge with the previous character, so we get a correct tokenization. This should not happen too often.
 
327
          previous = KDevelop::IndexedString(KDevelop::IndexedString(previous).byteArray() + string.byteArray()).index();
 
328
          kDebug() << "merging" << KDevelop::IndexedString(previous).str() << "and" << string.str();
 
329
          return *this; ///We lose the input-position, but on the other hand we would lose it anyway on another level
 
330
        }
 
331
      }
 
332
    }*/
 
333
    
 
334
    mark(inputPosition);
 
335
    m_string->append(string.index());
 
336
 
 
337
    int extraLines = 0;
 
338
    if (string.index() == newline) {
 
339
      m_pos += 1; //Move the current offset to that position, so the marker is set correctly
 
340
      if(!inputPosition.collapsed)
 
341
        mark(Anchor(inputPosition.line + ++extraLines, 0, false, m_macroExpansion));
 
342
      m_pos -= 1;
 
343
    }
 
344
 
 
345
    m_pos += 1;
 
346
 
 
347
    // TODO check correctness Probably remove
 
348
    m_inputLineStartedAt = m_pos; ///@todo remove
 
349
  }
 
350
  return *this;
 
351
}
 
352
 
 
353
bool Stream::isNull() const
 
354
{
 
355
  return m_isNull;
 
356
}
 
357
 
 
358
Anchor Stream::inputPosition() const
 
359
{
 
360
  return Anchor(m_inputLine, m_pos - m_inputLineStartedAt, m_inputPositionLocked, m_macroExpansion);
 
361
}
 
362
 
 
363
void Stream::setInputPosition(const Anchor& position)
 
364
{
 
365
  m_inputLine = position.line;
 
366
  m_inputLineStartedAt = m_pos - position.column;
 
367
  m_inputPositionLocked = position.collapsed;
 
368
}
 
369
 
 
370
void Stream::setMacroExpansion(const KDevelop::SimpleCursor& expansion)
 
371
{
 
372
  m_macroExpansion = expansion;
 
373
}
 
374
 
 
375
KDevelop::SimpleCursor Stream::macroExpansion() const
 
376
{
 
377
  return m_macroExpansion;
 
378
}
 
379
 
 
380
rpp::Anchor rpp::Stream::currentOutputAnchor() const {
 
381
  if(m_locationTable)
 
382
    return m_locationTable->positionAt(m_pos, *m_string).first;
 
383
  return rpp::Anchor();
 
384
}
 
385
 
 
386
void Stream::mark(const Anchor& position)
 
387
{
 
388
  Q_ASSERT(m_pos <= m_string->size());
 
389
  if (m_locationTable) {
 
390
    if(m_macroExpansion.isValid()) {
 
391
      Anchor a(position);
 
392
      a.macroExpansion = m_macroExpansion;
 
393
      m_locationTable->anchor(m_pos, a, m_string);
 
394
    }else{
 
395
      m_locationTable->anchor(m_pos, position, m_string);
 
396
    }
 
397
  }
 
398
}
 
399
 
 
400
void Stream::reset( )
 
401
{
 
402
  c = m_string->constData();
 
403
  m_inputLineStartedAt = m_inputLine = m_pos = 0;
 
404
  m_inputPositionLocked = false;
 
405
}
 
406
 
 
407
QByteArray rpp::Stream::stringFrom(int offset) const
 
408
{
 
409
  QByteArray ret;
 
410
  for(int a = offset; a < m_pos; ++a)
 
411
    ret += KDevelop::IndexedString::fromIndex((*m_string)[a]).byteArray();
 
412
  
 
413
  return ret;
 
414
}
 
415
 
 
416
KDevelop::SimpleCursor rpp::Stream::originalInputPosition() const
 
417
{
 
418
  if (m_originalInputPosition.isValid())
 
419
    return m_originalInputPosition;
 
420
 
 
421
  return inputPosition();
 
422
}
 
423
 
 
424
void rpp::Stream::setOriginalInputPosition(const KDevelop::SimpleCursor & position)
 
425
{
 
426
  m_originalInputPosition = position;
 
427
}