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