Skip to content

Commit b431bb2

Browse files
committed
Merge branch 'master' into autobuild/alpha_v380
2 parents 32a52ee + a065f44 commit b431bb2

File tree

7 files changed

+83
-21
lines changed

7 files changed

+83
-21
lines changed

changes.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ New Features
105105
and the bit depth.
106106
- Support for blue noise dithering has been added, plus a couple more error
107107
diffusion dithering filters.
108+
- The parser now checks for proper balancing of `#end` directives, braces,
109+
parentheses etc. within each include file, and will report any imbalance
110+
via warnings or, in case of `#end`, outright errors.
108111

109112
Performance Improvements
110113
------------------------

source/base/version.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@
100100
/// where `N` is a serial number starting at 1 in each phase, `TIME` is the number of minutes
101101
/// since 2000-01-01 00:00, and `FEATURE` is an arbitrary alphanumeric moniker for a particular
102102
/// experimental feature.
103-
#define POV_RAY_PRERELEASE "alpha.10008988"
103+
#define POV_RAY_PRERELEASE "alpha.10011104"
104104

105105
#if defined(DOXYGEN) && !defined(POV_RAY_PRERELEASE)
106106
// Work around doxygen being unable to document undefined macros.

source/core/coretypes.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,7 @@ struct SourceInfo : MessageContext
626626
SourcePosition position;
627627
SourceInfo() = default;
628628
SourceInfo(const MessageContext& o) : fileName(o.GetFileName()), position(o.GetLine(), o.GetColumn(), o.GetOffset()) {}
629-
SourceInfo(const UCS2String& fn, SourcePosition& p) : fileName(fn), position(p) {}
629+
SourceInfo(const UCS2String& fn, const SourcePosition& p) : fileName(fn), position(p) {}
630630
virtual UCS2String GetFileName() const override { return fileName; }
631631
virtual POV_LONG GetLine() const override { return position.line; }
632632
virtual POV_LONG GetColumn() const override { return position.column; }

source/parser/parser.cpp

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,8 @@ Parser::~Parser()
176176
/* Parse the file. */
177177
void Parser::Run()
178178
{
179-
int error_line = -1;
180-
int error_col = -1;
181-
UCS2String error_filename(POV_FILENAME_BUFFER_CHARS, 0); // Pre-claim some memory, so we can handle an out-of-memory error.
182-
POV_OFF_T error_pos = -1;
179+
SourceInfo errorInfo(UCS2String(POV_FILENAME_BUFFER_CHARS, 0), // Pre-claim some memory, so we can handle an out-of-memory error.
180+
SourcePosition(-1,-1,-1));
183181

184182
// Outer try/catch block to handle out-of-memory conditions
185183
// occurring during regular error handling.
@@ -301,10 +299,8 @@ void Parser::Run()
301299
{
302300
// take a (local) copy of error location prior to freeing token data
303301
// NB error_filename has been pre-allocated for strings up to POV_FILENAME_BUFFER_CHARS
304-
error_filename = CurrentFileName();
305-
error_line = CurrentFilePosition().line;
306-
error_col = CurrentFilePosition().column;
307-
error_pos = CurrentFilePosition().offset;
302+
errorInfo.fileName = CurrentFileName();
303+
errorInfo.position = CurrentFilePosition();
308304
}
309305

310306
// free up some memory before proceeding with error notification.
@@ -313,8 +309,8 @@ void Parser::Run()
313309
Default_Texture = nullptr;
314310
Destroy_Random_Generators();
315311

316-
if (error_line != -1)
317-
mMessageFactory.ErrorAt(POV_EXCEPTION_CODE(kOutOfMemoryErr), error_filename, error_line, error_col, error_pos, "Out of memory.");
312+
if (errorInfo.position.line != -1)
313+
mMessageFactory.ErrorAt(POV_EXCEPTION_CODE(kOutOfMemoryErr), errorInfo, "Out of memory.");
318314
else
319315
Error("Out of memory.");
320316
}
@@ -769,7 +765,15 @@ void Parser::Parse_End(TokenId openTokenId, TokenId expectTokenId)
769765
{
770766
POV_PARSER_ASSERT(!maBraceStack.empty());
771767
POV_PARSER_ASSERT(openTokenId == maBraceStack.back().openToken);
768+
769+
if (!maIncludeStack.empty() && (maBraceStack.size() <= maIncludeStack.back().braceStackSize))
770+
{
771+
BraceStackEntry& braceStackEntry = maBraceStack.back();
772+
// Include file has closed more braces/parentheses/etc. than it has opened.
773+
Warning("Unbalanced %s in include file", Get_Token_String(CurrentTokenId()));
774+
}
772775
maBraceStack.pop_back();
776+
773777
return;
774778
}
775779

@@ -6518,7 +6522,7 @@ ObjectPtr Parser::Parse_TrueType ()
65186522
if (sceneData->EffectiveLanguageVersion() < 380)
65196523
{
65206524
if (sceneData->legacyCharset == LegacyCharset::kUnspecified)
6521-
sceneData->legacyCharset = LegacyCharset::kASCII;
6525+
legacyCharset = LegacyCharset::kASCII;
65226526
else
65236527
legacyCharset = sceneData->legacyCharset;
65246528

@@ -10611,6 +10615,18 @@ void Parser::Warning(const char *format,...)
1061110615
Warning(kWarningGeneral, localvsbuffer);
1061210616
}
1061310617

10618+
void Parser::Warning(const MessageContext& loc, const char *format, ...)
10619+
{
10620+
va_list marker;
10621+
char localvsbuffer[1024];
10622+
10623+
va_start(marker, format);
10624+
std::vsnprintf(localvsbuffer, sizeof(localvsbuffer), format, marker);
10625+
va_end(marker);
10626+
10627+
Warning(kWarningGeneral, loc, localvsbuffer);
10628+
}
10629+
1061410630
void Parser::Warning(WarningLevel level, const char *format,...)
1061510631
{
1061610632
POV_PARSER_ASSERT(level >= kWarningGeneral);
@@ -10628,6 +10644,20 @@ void Parser::Warning(WarningLevel level, const char *format,...)
1062810644
mMessageFactory.Warning(level, "%s", localvsbuffer);
1062910645
}
1063010646

10647+
void Parser::Warning(WarningLevel level, const MessageContext& loc, const char *format, ...)
10648+
{
10649+
POV_PARSER_ASSERT(level >= kWarningGeneral);
10650+
10651+
va_list marker;
10652+
char localvsbuffer[1024];
10653+
10654+
va_start(marker, format);
10655+
std::vsnprintf(localvsbuffer, sizeof(localvsbuffer), format, marker);
10656+
va_end(marker);
10657+
10658+
mMessageFactory.WarningAt(level, loc, "%s", localvsbuffer);
10659+
}
10660+
1063110661
void Parser::VersionWarning(unsigned int sinceVersion, const char *format,...)
1063210662
{
1063310663
if(sceneData->EffectiveLanguageVersion() >= sinceVersion)

source/parser/parser.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,9 @@ class Parser
421421
void SendFatalError(Exception& e);
422422

423423
void Warning(const char *format,...);
424+
void Warning(const MessageContext& loc, const char *format, ...);
424425
void Warning(WarningLevel level, const char *format,...);
426+
void Warning(WarningLevel level, const MessageContext& loc, const char *format, ...);
425427
void VersionWarning(unsigned int sinceVersion, const char *format,...);
426428
void PossibleError(const char *format,...);
427429
void Error(const char *format,...);
@@ -660,7 +662,17 @@ class Parser
660662
POV_LONG mTokenCount;
661663
int mTokensSinceLastProgressReport;
662664

663-
vector<RawTokenizer::HotBookmark> maIncludeStack;
665+
struct IncludeStackEntry
666+
{
667+
RawTokenizer::HotBookmark returnToBookmark;
668+
int condStackSize;
669+
int braceStackSize;
670+
671+
IncludeStackEntry(const RawTokenizer::HotBookmark& rtb, int css, int bss) :
672+
returnToBookmark(rtb), condStackSize(css), braceStackSize(bss)
673+
{}
674+
};
675+
vector<IncludeStackEntry> maIncludeStack;
664676

665677
struct CS_ENTRY
666678
{

source/parser/parser_tokenizer.cpp

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -294,8 +294,12 @@ void Parser::Get_Token ()
294294

295295
if (!GetRawToken(mToken.raw, fastForwardToDirective))
296296
{
297+
// End of current token stream reached.
298+
297299
if (maIncludeStack.empty())
298300
{
301+
// Not in an include file, i.e. end of main scene file reached.
302+
299303
if (Cond_Stack.size() != 1)
300304
Error("End of file reached but #end expected.");
301305

@@ -305,12 +309,24 @@ void Parser::Get_Token ()
305309
}
306310

307311
// Returning from an include file.
312+
// NB: End of macro is marked by `#end` rather than EOF, so it won't take us here.
308313

309314
Got_EOF=false;
310315

311316
mSymbolStack.PopTable();
312317

313-
GoToBookmark(maIncludeStack.back()); // TODO handle errors
318+
if (Cond_Stack.size() != maIncludeStack.back().condStackSize)
319+
Error("Unbalanced #end directives in include file.");
320+
if (maBraceStack.size() > maIncludeStack.back().braceStackSize)
321+
{
322+
// Include file has opened more braces/parentheses/etc. than it has closed.
323+
for (size_t i = maIncludeStack.back().braceStackSize; i < maBraceStack.size(); ++i)
324+
{
325+
BraceStackEntry& braceStackEntry = maBraceStack[i];
326+
Warning(braceStackEntry, "Unbalanced %s in include file", Get_Token_String(braceStackEntry.openToken));
327+
}
328+
}
329+
GoToBookmark(maIncludeStack.back().returnToBookmark); // TODO handle errors
314330
maIncludeStack.pop_back();
315331

316332
continue;
@@ -1881,9 +1897,9 @@ void Parser::Parse_Version()
18811897

18821898
if (maIncludeStack.empty())
18831899
Error("As of POV-Ray v3.7, the '#version' directive must be the first non-comment "
1884-
"statement in the scene file. To indicate that your scene will dynamically "
1885-
"adapt to whatever POV-Ray version is actually used, start your scene with "
1886-
"'#version version;'.");
1900+
"statement in the scene file. To indicate that your scene will dynamically "
1901+
"adapt to whatever POV-Ray version is actually used, start your scene with "
1902+
"'#version version;'.");
18871903
}
18881904

18891905
// Initialize various defaults depending on language version specified.
@@ -1896,7 +1912,7 @@ void Parser::Parse_Version()
18961912

18971913
if (sceneData->explicitNoiseGenerator == false)
18981914
sceneData->noiseGenerator = (sceneData->EffectiveLanguageVersion() < 350 ?
1899-
kNoiseGen_Original : kNoiseGen_RangeCorrected);
1915+
kNoiseGen_Original : kNoiseGen_RangeCorrected);
19001916
// [CLi] if assumed_gamma is not specified in a pre-v3.7 scene, gammaMode defaults to kPOVList_GammaMode_None;
19011917
// this is enforced later anyway after parsing, but we may need this information /now/ during parsing already
19021918
switch (sceneData->gammaMode)
@@ -1979,7 +1995,7 @@ void Parser::Open_Include()
19791995

19801996
void Parser::Skip_Tokens(COND_TYPE cond)
19811997
{
1982-
int Temp = Cond_Stack.size();
1998+
auto Temp = Cond_Stack.size();
19831999
bool Prev_Skip = Skipping;
19842000

19852001
Skipping = true;
@@ -3267,7 +3283,7 @@ void Parser::IncludeHeader(const UCS2String& formalFileName)
32673283
if (formalFileName.empty())
32683284
return;
32693285

3270-
maIncludeStack.push_back(mTokenizer.GetHotBookmark());
3286+
maIncludeStack.emplace_back(mTokenizer.GetHotBookmark(), int(Cond_Stack.size()), int(maBraceStack.size()));
32713287

32723288
shared_ptr<IStream> is = Locate_File (formalFileName.c_str(),POV_File_Text_INC,actualFileName,true);
32733289
if (is == nullptr)

source/parser/scanner.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,7 @@ bool Scanner::BufferedSource::SetInputStream(StreamPtr pStream, POV_OFF_T pos)
675675
// Just advance/rewind the current buffer position accordingly.
676676
mBuffer.AdvanceTo(pos - mBase);
677677
POV_PARSER_ASSERT(!mBuffer.IsExhausted());
678+
mExhausted = false;
678679
return true;
679680
}
680681
else

0 commit comments

Comments
 (0)