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