Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
glslang
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
glslang
Commits
b159bd58
Commit
b159bd58
authored
Jul 24, 2015
by
John Kessenich
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #38 from google/preprocessing-line-number
Preprocessing line number handling
parents
62aa5bdf
79f6451b
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
90 additions
and
51 deletions
+90
-51
ShaderLang.cpp
glslang/MachineIndependent/ShaderLang.cpp
+90
-51
No files found.
glslang/MachineIndependent/ShaderLang.cpp
View file @
b159bd58
...
...
@@ -599,6 +599,67 @@ bool ProcessDeferred(
return
success
;
}
// Responsible for keeping track of the most recent source string and line in
// the preprocessor and outputting newlines appropriately if the source string
// or line changes.
class
SourceLineSynchronizer
{
public
:
SourceLineSynchronizer
(
const
std
::
function
<
int
()
>&
lastSourceIndex
,
std
::
stringstream
*
output
)
:
getLastSourceIndex
(
lastSourceIndex
),
output
(
output
)
{}
SourceLineSynchronizer
(
const
SourceLineSynchronizer
&
)
=
delete
;
SourceLineSynchronizer
&
operator
=
(
const
SourceLineSynchronizer
&
)
=
delete
;
// Sets the internally tracked source string index to that of the most
// recently read token. If we switched to a new source string, returns
// true and inserts a newline. Otherwise, returns false and outputs nothing.
bool
syncToMostRecentString
()
{
if
(
getLastSourceIndex
()
!=
lastSource
)
{
// After switching to a new source string, we need to reset lastLine
// because line number resets every time a new source string is
// used. We also need to output a newline to separate the output
// from the previous source string (if there is one).
if
(
lastSource
!=
-
1
||
lastLine
!=
0
)
*
output
<<
std
::
endl
;
lastSource
=
getLastSourceIndex
();
lastLine
=
-
1
;
return
true
;
}
return
false
;
}
// Calls syncToMostRecentString() and then sets the internally tracked line
// number to tokenLine. If we switched to a new line, returns true and inserts
// newlines appropriately. Otherwise, returns false and outputs nothing.
bool
syncToLine
(
int
tokenLine
)
{
syncToMostRecentString
();
const
bool
newLineStarted
=
lastLine
<
tokenLine
;
for
(;
lastLine
<
tokenLine
;
++
lastLine
)
{
if
(
lastLine
>
0
)
*
output
<<
std
::
endl
;
}
return
newLineStarted
;
}
// Sets the internally tracked line number to newLineNum.
void
setLineNum
(
int
newLineNum
)
{
lastLine
=
newLineNum
;
}
private
:
// A function for getting the index of the last valid source string we've
// read tokens from.
const
std
::
function
<
int
()
>
getLastSourceIndex
;
// output stream for newlines.
std
::
stringstream
*
output
;
// lastSource is the source string index (starting from 0) of the last token
// processed. It is tracked in order for newlines to be inserted when a new
// source string starts. -1 means we haven't started processing any source
// string.
int
lastSource
=
-
1
;
// lastLine is the line number (starting from 1) of the last token processed.
// It is tracked in order for newlines to be inserted when a token appears
// on a new line. 0 means we haven't started processing any line in the
// current source string.
int
lastLine
=
0
;
};
// DoPreprocessing is a valid ProcessingContext template argument,
// which only performs the preprocessing step of compilation.
...
...
@@ -615,99 +676,77 @@ struct DoPreprocessing {
static
const
std
::
string
noSpaceBeforeTokens
=
","
;
glslang
::
TPpToken
token
;
std
::
stringstream
outputStream
;
int
lastLine
=
-
1
;
// lastLine is the line number of the last token
// processed. It is tracked in order for new-lines to be inserted when
// a token appears on a new line.
int
lastToken
=
-
1
;
parseContext
.
setScanner
(
&
input
);
ppContext
.
setInput
(
input
,
versionWillBeError
);
// Inserts newlines and incremnets lastLine until
// lastLine >= line.
auto
adjustLine
=
[
&
lastLine
,
&
outputStream
](
int
line
)
{
int
tokenLine
=
line
-
1
;
while
(
lastLine
<
tokenLine
)
{
if
(
lastLine
>=
0
)
{
outputStream
<<
std
::
endl
;
}
++
lastLine
;
}
};
std
::
stringstream
outputStream
;
SourceLineSynchronizer
lineSync
(
std
::
bind
(
&
TInputScanner
::
getLastValidSourceIndex
,
&
input
),
&
outputStream
);
parseContext
.
setExtensionCallback
([
&
adjustLine
,
&
outputStream
](
parseContext
.
setExtensionCallback
([
&
lineSync
,
&
outputStream
](
int
line
,
const
char
*
extension
,
const
char
*
behavior
)
{
adjust
Line
(
line
);
lineSync
.
syncTo
Line
(
line
);
outputStream
<<
"#extension "
<<
extension
<<
" : "
<<
behavior
;
});
parseContext
.
setLineCallback
([
&
adjustLine
,
&
lastLine
,
&
outputStream
,
&
parseContext
](
int
curLineN
o
,
int
newLineNo
,
bool
hasSource
,
int
sourceNum
)
{
parseContext
.
setLineCallback
([
&
lineSync
,
&
outputStream
,
&
parseContext
](
int
curLineN
um
,
int
newLineNum
,
bool
hasSource
,
int
sourceNum
)
{
// SourceNum is the number of the source-string that is being parsed.
adjustLine
(
curLineNo
);
outputStream
<<
"#line "
<<
newLineN
o
;
lineSync
.
syncToLine
(
curLineNum
);
outputStream
<<
"#line "
<<
newLineN
um
;
if
(
hasSource
)
{
outputStream
<<
" "
<<
sourceNum
;
}
if
(
parseContext
.
lineDirectiveShouldSetNextLine
())
{
// newLineN
o
is the new line number for the line following the #line
// newLineN
um
is the new line number for the line following the #line
// directive. So the new line number for the current line is
newLineN
o
-=
1
;
newLineN
um
-=
1
;
}
outputStream
<<
std
::
endl
;
// Line number starts from 1. And we are at the next line of the #line
// directive now. So lastLine (from 0) should be (newLineNo - 1) + 1.
lastLine
=
newLineNo
;
// And we are at the next line of the #line directive now.
lineSync
.
setLineNum
(
newLineNum
+
1
);
});
parseContext
.
setVersionCallback
(
[
&
adjustLine
,
&
outputStream
](
int
line
,
int
version
,
const
char
*
str
)
{
adjust
Line
(
line
);
[
&
lineSync
,
&
outputStream
](
int
line
,
int
version
,
const
char
*
str
)
{
lineSync
.
syncTo
Line
(
line
);
outputStream
<<
"#version "
<<
version
;
if
(
str
)
{
outputStream
<<
" "
<<
str
;
}
});
parseContext
.
setPragmaCallback
([
&
adjustLine
,
&
outputStream
](
parseContext
.
setPragmaCallback
([
&
lineSync
,
&
outputStream
](
int
line
,
const
glslang
::
TVector
<
glslang
::
TString
>&
ops
)
{
adjust
Line
(
line
);
lineSync
.
syncTo
Line
(
line
);
outputStream
<<
"#pragma "
;
for
(
size_t
i
=
0
;
i
<
ops
.
size
();
++
i
)
{
outputStream
<<
ops
[
i
];
}
});
parseContext
.
setErrorCallback
([
&
adjustLine
,
&
outputStream
](
parseContext
.
setErrorCallback
([
&
lineSync
,
&
outputStream
](
int
line
,
const
char
*
errorMessage
)
{
adjust
Line
(
line
);
lineSync
.
syncTo
Line
(
line
);
outputStream
<<
"#error "
<<
errorMessage
;
});
int
lastToken
=
EOF
;
// lastToken records the last token processed.
while
(
const
char
*
tok
=
ppContext
.
tokenize
(
&
token
))
{
int
tokenLine
=
token
.
loc
.
line
-
1
;
// start at 0;
bool
newLine
=
false
;
while
(
lastLine
<
tokenLine
)
{
if
(
lastLine
>
-
1
)
{
outputStream
<<
std
::
endl
;
newLine
=
true
;
}
++
lastLine
;
if
(
lastLine
==
tokenLine
)
{
// Don't emit whitespace onto empty lines.
// Copy any whitespace characters at the start of a line
// from the input to the output.
for
(
int
i
=
0
;
i
<
token
.
loc
.
column
-
1
;
++
i
)
{
outputStream
<<
" "
;
}
}
bool
isNewString
=
lineSync
.
syncToMostRecentString
();
bool
isNewLine
=
lineSync
.
syncToLine
(
token
.
loc
.
line
);
if
(
isNewLine
)
{
// Don't emit whitespace onto empty lines.
// Copy any whitespace characters at the start of a line
// from the input to the output.
outputStream
<<
std
::
string
(
token
.
loc
.
column
-
1
,
' '
);
}
// Output a space in between tokens, but not at the start of a line,
// and also not around special tokens. This helps with readability
// and consistency.
if
(
!
newLine
&&
lastToken
!=
-
1
&&
if
(
!
isNewString
&&
!
isNewLine
&&
lastToken
!=
-
1
&&
(
unNeededSpaceTokens
.
find
((
char
)
token
.
token
)
==
std
::
string
::
npos
)
&&
(
unNeededSpaceTokens
.
find
((
char
)
lastToken
)
==
std
::
string
::
npos
)
&&
(
noSpaceBeforeTokens
.
find
((
char
)
token
.
token
)
==
std
::
string
::
npos
))
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment