blob: 073d671eedacf3f9d3ecb270a1690651b55965f0 [file] [log] [blame]
alokp@chromium.org4e4b8072011-08-07 05:36:04 +00001//
2// Copyright (c) 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
Corentin Wallez054f7ed2016-09-20 17:15:59 -04007#include "compiler/preprocessor/Input.h"
alokp@chromium.org4e4b8072011-08-07 05:36:04 +00008
alokp@chromium.org98eec912012-05-01 10:04:08 +00009#include <algorithm>
alokp@chromium.org99b5c0c2012-05-17 20:44:52 +000010#include <cstring>
alokp@chromium.org98eec912012-05-01 10:04:08 +000011
Corentin Wallez054f7ed2016-09-20 17:15:59 -040012#include "common/debug.h"
13
Geoff Lang197d5292018-04-25 14:29:00 -040014namespace angle
15{
16
alokp@chromium.org4e4b8072011-08-07 05:36:04 +000017namespace pp
18{
19
alokp@chromium.org30a487c2012-05-02 17:30:46 +000020Input::Input() : mCount(0), mString(0)
alokp@chromium.org4e4b8072011-08-07 05:36:04 +000021{
alokp@chromium.org4e4b8072011-08-07 05:36:04 +000022}
23
Jamie Madillacf2f3a2017-11-21 19:22:44 -050024Input::~Input()
25{
26}
27
Jamie Madillf832c9d2016-12-12 17:38:48 -050028Input::Input(size_t count, const char *const string[], const int length[])
29 : mCount(count), mString(string)
alokp@chromium.org98eec912012-05-01 10:04:08 +000030{
alokp@chromium.org30a487c2012-05-02 17:30:46 +000031 mLength.reserve(mCount);
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +000032 for (size_t i = 0; i < mCount; ++i)
alokp@chromium.org98eec912012-05-01 10:04:08 +000033 {
alokp@chromium.org30a487c2012-05-02 17:30:46 +000034 int len = length ? length[i] : -1;
daniel@transgaming.coma16a55f2012-12-20 20:51:54 +000035 mLength.push_back(len < 0 ? std::strlen(mString[i]) : len);
alokp@chromium.org98eec912012-05-01 10:04:08 +000036 }
37}
38
Olli Etuaho26e355b2015-08-14 14:16:19 +030039const char *Input::skipChar()
40{
41 // This function should only be called when there is a character to skip.
Corentin Wallez054f7ed2016-09-20 17:15:59 -040042 ASSERT(mReadLoc.cIndex < mLength[mReadLoc.sIndex]);
Olli Etuaho26e355b2015-08-14 14:16:19 +030043 ++mReadLoc.cIndex;
44 if (mReadLoc.cIndex == mLength[mReadLoc.sIndex])
45 {
46 ++mReadLoc.sIndex;
47 mReadLoc.cIndex = 0;
48 }
49 if (mReadLoc.sIndex >= mCount)
50 {
51 return nullptr;
52 }
53 return mString[mReadLoc.sIndex] + mReadLoc.cIndex;
54}
55
56size_t Input::read(char *buf, size_t maxSize, int *lineNo)
alokp@chromium.org98eec912012-05-01 10:04:08 +000057{
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +000058 size_t nRead = 0;
Olli Etuaho26e355b2015-08-14 14:16:19 +030059 // The previous call to read might have stopped copying the string when encountering a line
60 // continuation. Check for this possibility first.
61 if (mReadLoc.sIndex < mCount && maxSize > 0)
62 {
63 const char *c = mString[mReadLoc.sIndex] + mReadLoc.cIndex;
64 if ((*c) == '\\')
65 {
66 c = skipChar();
67 if (c != nullptr && (*c) == '\n')
68 {
69 // Line continuation of backslash + newline.
70 skipChar();
Corentin Wallezd78e33a2017-10-30 12:33:52 -040071 // Fake an EOF if the line number would overflow.
72 if (*lineNo == INT_MAX)
73 {
74 return 0;
75 }
Olli Etuaho26e355b2015-08-14 14:16:19 +030076 ++(*lineNo);
77 }
78 else if (c != nullptr && (*c) == '\r')
79 {
80 // Line continuation. Could be backslash + '\r\n' or just backslash + '\r'.
81 c = skipChar();
82 if (c != nullptr && (*c) == '\n')
83 {
84 skipChar();
85 }
Corentin Wallezd78e33a2017-10-30 12:33:52 -040086 // Fake an EOF if the line number would overflow.
87 if (*lineNo == INT_MAX)
88 {
89 return 0;
90 }
Olli Etuaho26e355b2015-08-14 14:16:19 +030091 ++(*lineNo);
92 }
93 else
94 {
95 // Not line continuation, so write the skipped backslash to buf.
96 *buf = '\\';
97 ++nRead;
98 }
99 }
100 }
101
102 size_t maxRead = maxSize;
103 while ((nRead < maxRead) && (mReadLoc.sIndex < mCount))
alokp@chromium.org98eec912012-05-01 10:04:08 +0000104 {
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +0000105 size_t size = mLength[mReadLoc.sIndex] - mReadLoc.cIndex;
Jamie Madillf832c9d2016-12-12 17:38:48 -0500106 size = std::min(size, maxSize);
Olli Etuaho26e355b2015-08-14 14:16:19 +0300107 for (size_t i = 0; i < size; ++i)
108 {
109 // Stop if a possible line continuation is encountered.
110 // It will be processed on the next call on input, which skips it
111 // and increments line number if necessary.
112 if (*(mString[mReadLoc.sIndex] + mReadLoc.cIndex + i) == '\\')
113 {
Jamie Madillf832c9d2016-12-12 17:38:48 -0500114 size = i;
Olli Etuaho26e355b2015-08-14 14:16:19 +0300115 maxRead = nRead + size; // Stop reading right before the backslash.
116 }
117 }
daniel@transgaming.coma16a55f2012-12-20 20:51:54 +0000118 std::memcpy(buf + nRead, mString[mReadLoc.sIndex] + mReadLoc.cIndex, size);
alokp@chromium.org98eec912012-05-01 10:04:08 +0000119 nRead += size;
120 mReadLoc.cIndex += size;
121
122 // Advance string if we reached the end of current string.
123 if (mReadLoc.cIndex == mLength[mReadLoc.sIndex])
124 {
125 ++mReadLoc.sIndex;
126 mReadLoc.cIndex = 0;
127 }
128 }
129 return nRead;
130}
131
alokp@chromium.org4e4b8072011-08-07 05:36:04 +0000132} // namespace pp
Geoff Lang197d5292018-04-25 14:29:00 -0400133
134} // namespace angle