Skip to content

Commit a5e8ee6

Browse files
committed
Re-enable version-dependent handlng of backslashes in file name literals.
1 parent af7e2a8 commit a5e8ee6

File tree

5 files changed

+211
-117
lines changed

5 files changed

+211
-117
lines changed

source/parser/parser_strings.cpp

Lines changed: 100 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -106,100 +106,119 @@ UCS2 *Parser::Parse_String(bool pathname, bool require)
106106
{
107107
UCS2 *New = nullptr;
108108
int len = 0;
109-
bool useRawText;
110-
UCS2String temp;
111-
const UCS2String* pS;
109+
const UCS2String* pString;
110+
const StringValue* stringValue = nullptr;
112111

113-
try
114-
{
112+
EXPECT
113+
CASE(STRING_LITERAL_TOKEN)
114+
/// @todo Add back support for non-ASCII string encodings.
115+
stringValue = dynamic_cast<const StringValue*>(mToken.raw.value.get());
116+
POV_PARSER_ASSERT(stringValue != nullptr);
115117

116-
EXPECT
117-
CASE(STRING_LITERAL_TOKEN)
118-
/// @todo Add back support for non-ASCII string encodings.
119-
POV_PARSER_ASSERT(dynamic_pointer_cast<const StringValue>(mToken.raw.value) != nullptr);
120-
len = dynamic_pointer_cast<const StringValue>(mToken.raw.value)->data.size() + 1;
121-
New = reinterpret_cast<UCS2 *>(POV_MALLOC(len * sizeof(UCS2), "UCS2 String"));
122-
POV_MEMCPY(reinterpret_cast<void *>(New),
123-
reinterpret_cast<const void *>(dynamic_pointer_cast<const StringValue>(mToken.raw.value)->data.c_str()),
124-
len * sizeof(UCS2));
125-
EXIT
126-
END_CASE
118+
if (pathname)
119+
{
120+
// Historically, escape sequences were ignored when parsing for a filename.
121+
// As of POV-Ray v3.8, this has been changed.
127122

128-
CASE(STR_TOKEN)
129-
New = Parse_Str(pathname);
130-
EXIT
131-
END_CASE
123+
if (sceneData->EffectiveLanguageVersion() >= 380)
124+
{
125+
if (stringValue->IsAmbiguous())
126+
{
127+
#if POV_BACKSLASH_IS_PATH_SEPARATOR
128+
Warning("Backslash encountered while parsing for a filename."
129+
" As of POV-Ray v3.8, this is interpreted as an escape sequence just like in any other string literal."
130+
" If this is supposed to be a path separator, use a forward slash instead.");
131+
#endif
132132

133-
CASE(VSTR_TOKEN)
134-
New = Parse_VStr(pathname);
135-
EXIT
136-
END_CASE
133+
}
134+
pString = &stringValue->GetData();
135+
}
136+
else
137+
{
138+
if (stringValue->IsAmbiguous())
139+
{
140+
#if POV_BACKSLASH_IS_PATH_SEPARATOR
141+
Warning("Backslash encountered while parsing for a filename."
142+
" In legacy (pre-3.8) scenes, this is NOT interpreted as the start of an escape sequence."
143+
" However, for future compatibility it is recommended to use a forward slash as path separator instead.");
144+
#else
145+
Warning("Backslash encountered while parsing for a filename."
146+
" In legacy (pre-3.8) scenes, this is NOT interpreted as the start of an escape sequence.");
147+
#endif
148+
}
149+
pString = &stringValue->GetFileName();
150+
}
151+
}
152+
else
153+
{
154+
pString = &stringValue->GetData();
155+
}
137156

138-
CASE(CONCAT_TOKEN)
139-
New = Parse_Concat(pathname);
140-
EXIT
141-
END_CASE
157+
len = pString->size() + 1;
158+
New = reinterpret_cast<UCS2 *>(POV_MALLOC(len * sizeof(UCS2), "UCS2 String"));
159+
POV_MEMCPY(reinterpret_cast<void *>(New),
160+
reinterpret_cast<const void *>(pString->c_str()),
161+
len * sizeof(UCS2));
162+
EXIT
163+
END_CASE
142164

143-
CASE(CHR_TOKEN)
144-
New = Parse_Chr(pathname);
145-
EXIT
146-
END_CASE
165+
CASE(STR_TOKEN)
166+
New = Parse_Str(pathname);
167+
EXIT
168+
END_CASE
147169

148-
CASE(DATETIME_TOKEN)
149-
New = Parse_Datetime(pathname);
150-
EXIT
151-
END_CASE
170+
CASE(VSTR_TOKEN)
171+
New = Parse_VStr(pathname);
172+
EXIT
173+
END_CASE
152174

153-
CASE(SUBSTR_TOKEN)
154-
New = Parse_Substr(pathname);
155-
EXIT
156-
END_CASE
175+
CASE(CONCAT_TOKEN)
176+
New = Parse_Concat(pathname);
177+
EXIT
178+
END_CASE
157179

158-
CASE(STRUPR_TOKEN)
159-
New = Parse_Strupr(pathname);
160-
EXIT
161-
END_CASE
180+
CASE(CHR_TOKEN)
181+
New = Parse_Chr(pathname);
182+
EXIT
183+
END_CASE
162184

163-
CASE(STRLWR_TOKEN)
164-
New = Parse_Strlwr(pathname);
165-
EXIT
166-
END_CASE
185+
CASE(DATETIME_TOKEN)
186+
New = Parse_Datetime(pathname);
187+
EXIT
188+
END_CASE
167189

168-
CASE(STRING_ID_TOKEN)
169-
len = UCS2_strlen(reinterpret_cast<UCS2 *>(mToken.Data)) + 1;
170-
New = reinterpret_cast<UCS2 *>(POV_MALLOC(len * sizeof(UCS2), "UCS2 String"));
171-
POV_MEMCPY(reinterpret_cast<void *>(New), reinterpret_cast<void *>(mToken.Data), len * sizeof(UCS2));
172-
EXIT
173-
END_CASE
190+
CASE(SUBSTR_TOKEN)
191+
New = Parse_Substr(pathname);
192+
EXIT
193+
END_CASE
174194

175-
OTHERWISE
176-
if(require)
177-
Expectation_Error("string expression");
178-
else
179-
{
180-
UNGET
181-
EXIT
182-
}
183-
END_CASE
184-
END_EXPECT
195+
CASE(STRUPR_TOKEN)
196+
New = Parse_Strupr(pathname);
197+
EXIT
198+
END_CASE
185199

186-
}
187-
catch (const InvalidEscapeSequenceException& e)
188-
{
189-
if (pathname)
190-
{
191-
Error(e, "Illegal escape sequence '%s' in string literal while parsing for a filename."
192-
" If this backslash is supposed to be a path separator, use a forward slash"
193-
" instead. The use of single backslashes as path separators has never been"
194-
" an officially documented feature, and as of POV-Ray v3.8 is no longer"
195-
" supported.",
196-
e.offendingText.c_str());
197-
}
198-
else
199-
{
200-
Error(e, "Illegal escape sequence '%s' in string literal.", e.offendingText.c_str());
201-
}
202-
}
200+
CASE(STRLWR_TOKEN)
201+
New = Parse_Strlwr(pathname);
202+
EXIT
203+
END_CASE
204+
205+
CASE(STRING_ID_TOKEN)
206+
len = UCS2_strlen(reinterpret_cast<UCS2 *>(mToken.Data)) + 1;
207+
New = reinterpret_cast<UCS2 *>(POV_MALLOC(len * sizeof(UCS2), "UCS2 String"));
208+
POV_MEMCPY(reinterpret_cast<void *>(New), reinterpret_cast<void *>(mToken.Data), len * sizeof(UCS2));
209+
EXIT
210+
END_CASE
211+
212+
OTHERWISE
213+
if(require)
214+
Expectation_Error("string expression");
215+
else
216+
{
217+
UNGET
218+
EXIT
219+
}
220+
END_CASE
221+
END_EXPECT
203222

204223
return New;
205224
}

source/parser/parsertypes.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ TokenizerException::TokenizerException(const ConstSourcePtr & os, const LexemePo
7878
offendingPosition(op)
7979
{}
8080

81-
pov_base::UCS2String TokenizerException::GetFileName() const
81+
UCS2String TokenizerException::GetFileName() const
8282
{
8383
return offendingStreamName;
8484
}
@@ -112,9 +112,16 @@ InvalidCharacterException::InvalidCharacterException(const ConstSourcePtr& os, c
112112
{}
113113

114114
InvalidEscapeSequenceException::InvalidEscapeSequenceException(const ConstSourcePtr& os, const LexemePosition& op,
115-
const pov_base::UTF8String& ot) :
115+
const UTF8String& ot) :
116116
TokenizerException(os, op),
117117
offendingText(ot)
118118
{}
119119

120+
InvalidEscapeSequenceException::InvalidEscapeSequenceException(const ConstSourcePtr& os, const LexemePosition& op,
121+
const UTF8String::const_iterator& otb,
122+
const UTF8String::const_iterator& ote) :
123+
TokenizerException(os, op),
124+
offendingText(otb, ote)
125+
{}
126+
120127
}

source/parser/parsertypes.h

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ class IStream;
5656
namespace pov_parser
5757
{
5858

59+
using namespace pov_base;
60+
5961
enum TokenId : int;
6062

6163
//------------------------------------------------------------------------------
@@ -79,14 +81,14 @@ struct LexemePosition
7981

8082
//------------------------------------------------------------------------------
8183

82-
struct TokenizerException : std::exception, pov_base::MessageContext
84+
struct TokenizerException : std::exception, MessageContext
8385
{
84-
pov_base::UCS2String offendingStreamName;
85-
LexemePosition offendingPosition;
86+
UCS2String offendingStreamName;
87+
LexemePosition offendingPosition;
8688

8789
TokenizerException(const ConstSourcePtr& os, const LexemePosition& op);
8890

89-
virtual pov_base::UCS2String GetFileName() const override;
91+
virtual UCS2String GetFileName() const override;
9092
virtual POV_LONG GetLine() const override;
9193
virtual POV_LONG GetColumn() const override;
9294
virtual POV_OFF_T GetOffset() const override;
@@ -110,8 +112,10 @@ struct InvalidCharacterException : TokenizerException
110112

111113
struct InvalidEscapeSequenceException : TokenizerException
112114
{
113-
pov_base::UTF8String offendingText;
114-
InvalidEscapeSequenceException(const ConstSourcePtr& os, const LexemePosition& op, const pov_base::UTF8String& ot);
115+
UTF8String offendingText;
116+
InvalidEscapeSequenceException(const ConstSourcePtr& os, const LexemePosition& op, const UTF8String& ot);
117+
InvalidEscapeSequenceException(const ConstSourcePtr& os, const LexemePosition& op,
118+
const UTF8String::const_iterator& otb, const UTF8String::const_iterator& ote);
115119
};
116120

117121
}

0 commit comments

Comments
 (0)