• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2011 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 #include "compiler/preprocessor/Input.h"
8 
9 #include <algorithm>
10 #include <cstring>
11 
12 #include "common/debug.h"
13 
14 namespace angle
15 {
16 
17 namespace pp
18 {
19 
Input()20 Input::Input() : mCount(0), mString(0) {}
21 
~Input()22 Input::~Input() {}
23 
Input(size_t count,const char * const string[],const int length[])24 Input::Input(size_t count, const char *const string[], const int length[])
25     : mCount(count), mString(string)
26 {
27     mLength.reserve(mCount);
28     for (size_t i = 0; i < mCount; ++i)
29     {
30         int len = length ? length[i] : -1;
31         mLength.push_back(len < 0 ? std::strlen(mString[i]) : len);
32     }
33 }
34 
skipChar()35 const char *Input::skipChar()
36 {
37     // This function should only be called when there is a character to skip.
38     ASSERT(mReadLoc.cIndex < mLength[mReadLoc.sIndex]);
39     ++mReadLoc.cIndex;
40     if (mReadLoc.cIndex == mLength[mReadLoc.sIndex])
41     {
42         ++mReadLoc.sIndex;
43         mReadLoc.cIndex = 0;
44     }
45     if (mReadLoc.sIndex >= mCount)
46     {
47         return nullptr;
48     }
49     return mString[mReadLoc.sIndex] + mReadLoc.cIndex;
50 }
51 
read(char * buf,size_t maxSize,int * lineNo)52 size_t Input::read(char *buf, size_t maxSize, int *lineNo)
53 {
54     size_t nRead = 0;
55     // The previous call to read might have stopped copying the string when encountering a line
56     // continuation. Check for this possibility first.
57     if (mReadLoc.sIndex < mCount && maxSize > 0)
58     {
59         const char *c = mString[mReadLoc.sIndex] + mReadLoc.cIndex;
60         if ((*c) == '\\')
61         {
62             c = skipChar();
63             if (c != nullptr && (*c) == '\n')
64             {
65                 // Line continuation of backslash + newline.
66                 skipChar();
67                 // Fake an EOF if the line number would overflow.
68                 if (*lineNo == INT_MAX)
69                 {
70                     return 0;
71                 }
72                 ++(*lineNo);
73             }
74             else if (c != nullptr && (*c) == '\r')
75             {
76                 // Line continuation. Could be backslash + '\r\n' or just backslash + '\r'.
77                 c = skipChar();
78                 if (c != nullptr && (*c) == '\n')
79                 {
80                     skipChar();
81                 }
82                 // Fake an EOF if the line number would overflow.
83                 if (*lineNo == INT_MAX)
84                 {
85                     return 0;
86                 }
87                 ++(*lineNo);
88             }
89             else
90             {
91                 // Not line continuation, so write the skipped backslash to buf.
92                 *buf = '\\';
93                 ++nRead;
94             }
95         }
96     }
97 
98     size_t maxRead = maxSize;
99     while ((nRead < maxRead) && (mReadLoc.sIndex < mCount))
100     {
101         size_t size = mLength[mReadLoc.sIndex] - mReadLoc.cIndex;
102         size        = std::min(size, maxSize);
103         for (size_t i = 0; i < size; ++i)
104         {
105             // Stop if a possible line continuation is encountered.
106             // It will be processed on the next call on input, which skips it
107             // and increments line number if necessary.
108             if (*(mString[mReadLoc.sIndex] + mReadLoc.cIndex + i) == '\\')
109             {
110                 size    = i;
111                 maxRead = nRead + size;  // Stop reading right before the backslash.
112             }
113         }
114         std::memcpy(buf + nRead, mString[mReadLoc.sIndex] + mReadLoc.cIndex, size);
115         nRead += size;
116         mReadLoc.cIndex += size;
117 
118         // Advance string if we reached the end of current string.
119         if (mReadLoc.cIndex == mLength[mReadLoc.sIndex])
120         {
121             ++mReadLoc.sIndex;
122             mReadLoc.cIndex = 0;
123         }
124     }
125     return nRead;
126 }
127 
128 }  // namespace pp
129 
130 }  // namespace angle
131