mirror of
https://github.com/Kitware/CMake.git
synced 2025-10-14 02:08:27 +08:00
cmCommandArgumentParserHelper: rework input handling
Old implementation uses involved Flex input management technique that requires usage of obsolete YY_INPUT macro. This causes a lot of useless allocations and byte-by-byte scanning. New implementation avoids those hacks, it uses yy_scan_string() API to setup Flex input. Also it fixes reporting of syntax error position and corresponding tests.
This commit is contained in:
@@ -653,7 +653,7 @@ This file must be translated to C++ and modified to build everywhere.
|
|||||||
|
|
||||||
Run flex >= 2.6 like this:
|
Run flex >= 2.6 like this:
|
||||||
|
|
||||||
flex --nounistd -DFLEXINT_H --noline --header-file=cmCommandArgumentLexer.h -ocmCommandArgumentLexer.cxx cmCommandArgumentLexer.in.l
|
flex --nounistd --never-interactive --batch -DFLEXINT_H --noline --header-file=cmCommandArgumentLexer.h -ocmCommandArgumentLexer.cxx cmCommandArgumentLexer.in.l
|
||||||
|
|
||||||
Modify cmCommandArgumentLexer.cxx:
|
Modify cmCommandArgumentLexer.cxx:
|
||||||
- remove trailing whitespace: sed -i 's/\s*$//' cmCommandArgumentLexer.h cmCommandArgumentLexer.cxx
|
- remove trailing whitespace: sed -i 's/\s*$//' cmCommandArgumentLexer.h cmCommandArgumentLexer.cxx
|
||||||
@@ -668,10 +668,7 @@ Modify cmCommandArgumentLexer.cxx:
|
|||||||
|
|
||||||
#include "cmCommandArgumentParserHelper.h"
|
#include "cmCommandArgumentParserHelper.h"
|
||||||
|
|
||||||
/* Replace the lexer input function. */
|
#define YY_USER_ACTION yyextra->UpdateInputPosition(yyleng);
|
||||||
#undef YY_INPUT
|
|
||||||
#define YY_INPUT(buf, result, max_size) \
|
|
||||||
do { result = yyextra->LexInput(buf, max_size); } while (0)
|
|
||||||
|
|
||||||
/* Include the set of tokens from the parser. */
|
/* Include the set of tokens from the parser. */
|
||||||
#include "cmCommandArgumentParserTokens.h"
|
#include "cmCommandArgumentParserTokens.h"
|
||||||
@@ -967,16 +964,12 @@ yy_match:
|
|||||||
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
|
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
|
||||||
++yy_cp;
|
++yy_cp;
|
||||||
}
|
}
|
||||||
while ( yy_base[yy_current_state] != 41 );
|
while ( yy_current_state != 29 );
|
||||||
|
yy_cp = yyg->yy_last_accepting_cpos;
|
||||||
|
yy_current_state = yyg->yy_last_accepting_state;
|
||||||
|
|
||||||
yy_find_action:
|
yy_find_action:
|
||||||
yy_act = yy_accept[yy_current_state];
|
yy_act = yy_accept[yy_current_state];
|
||||||
if ( yy_act == 0 )
|
|
||||||
{ /* have to back up */
|
|
||||||
yy_cp = yyg->yy_last_accepting_cpos;
|
|
||||||
yy_current_state = yyg->yy_last_accepting_state;
|
|
||||||
yy_act = yy_accept[yy_current_state];
|
|
||||||
}
|
|
||||||
|
|
||||||
YY_DO_BEFORE_ACTION;
|
YY_DO_BEFORE_ACTION;
|
||||||
|
|
||||||
@@ -1173,7 +1166,8 @@ case YY_STATE_EOF(NOESCAPES):
|
|||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
yy_cp = yyg->yy_c_buf_p;
|
yy_cp = yyg->yy_last_accepting_cpos;
|
||||||
|
yy_current_state = yyg->yy_last_accepting_state;
|
||||||
goto yy_find_action;
|
goto yy_find_action;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1661,7 +1655,7 @@ static void yy_load_buffer_state (yyscan_t yyscanner)
|
|||||||
b->yy_bs_column = 0;
|
b->yy_bs_column = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
|
b->yy_is_interactive = 0;
|
||||||
|
|
||||||
errno = oerrno;
|
errno = oerrno;
|
||||||
}
|
}
|
||||||
|
@@ -7,7 +7,7 @@ This file must be translated to C++ and modified to build everywhere.
|
|||||||
|
|
||||||
Run flex >= 2.6 like this:
|
Run flex >= 2.6 like this:
|
||||||
|
|
||||||
flex --nounistd -DFLEXINT_H --noline --header-file=cmCommandArgumentLexer.h -ocmCommandArgumentLexer.cxx cmCommandArgumentLexer.in.l
|
flex --nounistd --never-interactive --batch -DFLEXINT_H --noline --header-file=cmCommandArgumentLexer.h -ocmCommandArgumentLexer.cxx cmCommandArgumentLexer.in.l
|
||||||
|
|
||||||
Modify cmCommandArgumentLexer.cxx:
|
Modify cmCommandArgumentLexer.cxx:
|
||||||
- remove trailing whitespace: sed -i 's/\s*$//' cmCommandArgumentLexer.h cmCommandArgumentLexer.cxx
|
- remove trailing whitespace: sed -i 's/\s*$//' cmCommandArgumentLexer.h cmCommandArgumentLexer.cxx
|
||||||
@@ -22,10 +22,7 @@ Modify cmCommandArgumentLexer.cxx:
|
|||||||
|
|
||||||
#include "cmCommandArgumentParserHelper.h"
|
#include "cmCommandArgumentParserHelper.h"
|
||||||
|
|
||||||
/* Replace the lexer input function. */
|
#define YY_USER_ACTION yyextra->UpdateInputPosition(yyleng);
|
||||||
#undef YY_INPUT
|
|
||||||
#define YY_INPUT(buf, result, max_size) \
|
|
||||||
do { result = yyextra->LexInput(buf, max_size); } while (0)
|
|
||||||
|
|
||||||
/* Include the set of tokens from the parser. */
|
/* Include the set of tokens from the parser. */
|
||||||
#include "cmCommandArgumentParserTokens.h"
|
#include "cmCommandArgumentParserTokens.h"
|
||||||
|
@@ -205,23 +205,24 @@ bool cmCommandArgumentParserHelper::HandleEscapeSymbol(
|
|||||||
|
|
||||||
void cmCommandArgument_SetupEscapes(yyscan_t yyscanner, bool noEscapes);
|
void cmCommandArgument_SetupEscapes(yyscan_t yyscanner, bool noEscapes);
|
||||||
|
|
||||||
int cmCommandArgumentParserHelper::ParseString(const char* str, int verb)
|
int cmCommandArgumentParserHelper::ParseString(std::string const& str,
|
||||||
|
int verb)
|
||||||
{
|
{
|
||||||
if (!str) {
|
if (str.empty()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
this->InputSize = str.size();
|
||||||
this->Verbose = verb;
|
this->Verbose = verb;
|
||||||
this->InputBuffer = str;
|
|
||||||
this->InputBufferPos = 0;
|
|
||||||
this->CurrentLine = 0;
|
|
||||||
|
|
||||||
this->Result.clear();
|
this->Result.clear();
|
||||||
|
|
||||||
yyscan_t yyscanner;
|
yyscan_t yyscanner;
|
||||||
cmCommandArgument_yylex_init(&yyscanner);
|
cmCommandArgument_yylex_init(&yyscanner);
|
||||||
|
auto scanBuf = cmCommandArgument_yy_scan_string(str.c_str(), yyscanner);
|
||||||
cmCommandArgument_yyset_extra(this, yyscanner);
|
cmCommandArgument_yyset_extra(this, yyscanner);
|
||||||
cmCommandArgument_SetupEscapes(yyscanner, this->NoEscapeMode);
|
cmCommandArgument_SetupEscapes(yyscanner, this->NoEscapeMode);
|
||||||
int res = cmCommandArgument_yyparse(yyscanner);
|
int res = cmCommandArgument_yyparse(yyscanner);
|
||||||
|
cmCommandArgument_yy_delete_buffer(scanBuf, yyscanner);
|
||||||
cmCommandArgument_yylex_destroy(yyscanner);
|
cmCommandArgument_yylex_destroy(yyscanner);
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -241,25 +242,14 @@ void cmCommandArgumentParserHelper::CleanupParser()
|
|||||||
this->Variables.clear();
|
this->Variables.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
int cmCommandArgumentParserHelper::LexInput(char* buf, int maxlen)
|
|
||||||
{
|
|
||||||
if (maxlen < 1) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (this->InputBufferPos < this->InputBuffer.size()) {
|
|
||||||
buf[0] = this->InputBuffer[this->InputBufferPos++];
|
|
||||||
if (buf[0] == '\n') {
|
|
||||||
this->CurrentLine++;
|
|
||||||
}
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
buf[0] = '\n';
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cmCommandArgumentParserHelper::Error(const char* str)
|
void cmCommandArgumentParserHelper::Error(const char* str)
|
||||||
{
|
{
|
||||||
unsigned long pos = static_cast<unsigned long>(this->InputBufferPos);
|
auto pos = this->InputBufferPos;
|
||||||
|
auto const isEof = (this->InputSize < this->InputBufferPos);
|
||||||
|
if (!isEof) {
|
||||||
|
pos -= this->LastTokenLength;
|
||||||
|
}
|
||||||
|
|
||||||
std::ostringstream ostr;
|
std::ostringstream ostr;
|
||||||
ostr << str << " (" << pos << ")";
|
ostr << str << " (" << pos << ")";
|
||||||
this->SetError(ostr.str());
|
this->SetError(ostr.str());
|
||||||
@@ -286,3 +276,9 @@ void cmCommandArgumentParserHelper::SetError(std::string const& msg)
|
|||||||
this->ErrorString = msg;
|
this->ErrorString = msg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cmCommandArgumentParserHelper::UpdateInputPosition(int const tokenLength)
|
||||||
|
{
|
||||||
|
this->InputBufferPos += tokenLength;
|
||||||
|
this->LastTokenLength = tokenLength;
|
||||||
|
}
|
||||||
|
@@ -25,7 +25,7 @@ public:
|
|||||||
cmCommandArgumentParserHelper& operator=(
|
cmCommandArgumentParserHelper& operator=(
|
||||||
cmCommandArgumentParserHelper const&) = delete;
|
cmCommandArgumentParserHelper const&) = delete;
|
||||||
|
|
||||||
int ParseString(const char* str, int verb);
|
int ParseString(std::string const& str, int verb);
|
||||||
|
|
||||||
// For the lexer:
|
// For the lexer:
|
||||||
void AllocateParserType(cmCommandArgumentParserHelper::ParserType* pt,
|
void AllocateParserType(cmCommandArgumentParserHelper::ParserType* pt,
|
||||||
@@ -33,7 +33,6 @@ public:
|
|||||||
bool HandleEscapeSymbol(cmCommandArgumentParserHelper::ParserType* pt,
|
bool HandleEscapeSymbol(cmCommandArgumentParserHelper::ParserType* pt,
|
||||||
char symbol);
|
char symbol);
|
||||||
|
|
||||||
int LexInput(char* buf, int maxlen);
|
|
||||||
void Error(const char* str);
|
void Error(const char* str);
|
||||||
|
|
||||||
// For yacc
|
// For yacc
|
||||||
@@ -46,6 +45,8 @@ public:
|
|||||||
|
|
||||||
void SetMakefile(const cmMakefile* mf);
|
void SetMakefile(const cmMakefile* mf);
|
||||||
|
|
||||||
|
void UpdateInputPosition(int tokenLength);
|
||||||
|
|
||||||
std::string& GetResult() { return this->Result; }
|
std::string& GetResult() { return this->Result; }
|
||||||
|
|
||||||
void SetLineFile(long line, const char* file);
|
void SetLineFile(long line, const char* file);
|
||||||
@@ -57,8 +58,9 @@ public:
|
|||||||
const char* GetError() { return this->ErrorString.c_str(); }
|
const char* GetError() { return this->ErrorString.c_str(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string::size_type InputBufferPos;
|
std::string::size_type InputBufferPos{ 1 };
|
||||||
std::string InputBuffer;
|
std::string::size_type LastTokenLength{};
|
||||||
|
std::string::size_type InputSize{};
|
||||||
std::vector<char> OutputBuffer;
|
std::vector<char> OutputBuffer;
|
||||||
|
|
||||||
void Print(const char* place, const char* str);
|
void Print(const char* place, const char* str);
|
||||||
@@ -75,7 +77,6 @@ private:
|
|||||||
std::string ErrorString;
|
std::string ErrorString;
|
||||||
const char* FileName;
|
const char* FileName;
|
||||||
long FileLine;
|
long FileLine;
|
||||||
int CurrentLine;
|
|
||||||
int Verbose;
|
int Verbose;
|
||||||
bool EscapeQuotes;
|
bool EscapeQuotes;
|
||||||
bool NoEscapeMode;
|
bool NoEscapeMode;
|
||||||
|
@@ -2898,7 +2898,7 @@ MessageType cmMakefile::ExpandVariablesInStringOld(
|
|||||||
parser.SetNoEscapeMode(noEscapes);
|
parser.SetNoEscapeMode(noEscapes);
|
||||||
parser.SetReplaceAtSyntax(replaceAt);
|
parser.SetReplaceAtSyntax(replaceAt);
|
||||||
parser.SetRemoveEmpty(removeEmpty);
|
parser.SetRemoveEmpty(removeEmpty);
|
||||||
int res = parser.ParseString(source.c_str(), 0);
|
int res = parser.ParseString(source, 0);
|
||||||
const char* emsg = parser.GetError();
|
const char* emsg = parser.GetError();
|
||||||
MessageType mtype = MessageType::LOG;
|
MessageType mtype = MessageType::LOG;
|
||||||
if (res && !emsg[0]) {
|
if (res && !emsg[0]) {
|
||||||
|
@@ -19,6 +19,6 @@ CMake Error at CMP0053-Dollar-OLD.cmake:6 \(message\):
|
|||||||
|
|
||||||
-->\${\$}<--
|
-->\${\$}<--
|
||||||
|
|
||||||
syntax error, unexpected \$, expecting } \(7\)
|
syntax error, unexpected \$, expecting } \(6\)
|
||||||
Call Stack \(most recent call first\):
|
Call Stack \(most recent call first\):
|
||||||
CMakeLists.txt:3 \(include\)$
|
CMakeLists.txt:3 \(include\)$
|
||||||
|
@@ -7,6 +7,6 @@
|
|||||||
|
|
||||||
\${var\\rwith\\rcarriagereturn}
|
\${var\\rwith\\rcarriagereturn}
|
||||||
|
|
||||||
syntax error, unexpected cal_SYMBOL, expecting } \(7\)
|
syntax error, unexpected cal_SYMBOL, expecting } \(6\)
|
||||||
Call Stack \(most recent call first\):
|
Call Stack \(most recent call first\):
|
||||||
CMakeLists.txt:3 \(include\)$
|
CMakeLists.txt:3 \(include\)$
|
||||||
|
@@ -7,6 +7,6 @@
|
|||||||
|
|
||||||
\${var\\rwith\\rcarriagereturn}
|
\${var\\rwith\\rcarriagereturn}
|
||||||
|
|
||||||
syntax error, unexpected cal_SYMBOL, expecting } \(7\)
|
syntax error, unexpected cal_SYMBOL, expecting } \(6\)
|
||||||
Call Stack \(most recent call first\):
|
Call Stack \(most recent call first\):
|
||||||
CMakeLists.txt:3 \(include\)$
|
CMakeLists.txt:3 \(include\)$
|
||||||
|
@@ -7,6 +7,6 @@
|
|||||||
|
|
||||||
\${var\\ with\\ escaped\\ space}
|
\${var\\ with\\ escaped\\ space}
|
||||||
|
|
||||||
syntax error, unexpected cal_SYMBOL, expecting } \(7\)
|
syntax error, unexpected cal_SYMBOL, expecting } \(6\)
|
||||||
Call Stack \(most recent call first\):
|
Call Stack \(most recent call first\):
|
||||||
CMakeLists.txt:3 \(include\)$
|
CMakeLists.txt:3 \(include\)$
|
||||||
|
@@ -7,6 +7,6 @@
|
|||||||
|
|
||||||
\${var\\ with\\ escaped\\ space}
|
\${var\\ with\\ escaped\\ space}
|
||||||
|
|
||||||
syntax error, unexpected cal_SYMBOL, expecting } \(7\)
|
syntax error, unexpected cal_SYMBOL, expecting } \(6\)
|
||||||
Call Stack \(most recent call first\):
|
Call Stack \(most recent call first\):
|
||||||
CMakeLists.txt:3 \(include\)$
|
CMakeLists.txt:3 \(include\)$
|
||||||
|
@@ -7,6 +7,6 @@
|
|||||||
|
|
||||||
\${var\\nwith\\nnewline}
|
\${var\\nwith\\nnewline}
|
||||||
|
|
||||||
syntax error, unexpected cal_SYMBOL, expecting } \(7\)
|
syntax error, unexpected cal_SYMBOL, expecting } \(6\)
|
||||||
Call Stack \(most recent call first\):
|
Call Stack \(most recent call first\):
|
||||||
CMakeLists.txt:3 \(include\)$
|
CMakeLists.txt:3 \(include\)$
|
||||||
|
@@ -7,6 +7,6 @@
|
|||||||
|
|
||||||
\${var\\nwith\\nnewline}
|
\${var\\nwith\\nnewline}
|
||||||
|
|
||||||
syntax error, unexpected cal_SYMBOL, expecting } \(7\)
|
syntax error, unexpected cal_SYMBOL, expecting } \(6\)
|
||||||
Call Stack \(most recent call first\):
|
Call Stack \(most recent call first\):
|
||||||
CMakeLists.txt:3 \(include\)$
|
CMakeLists.txt:3 \(include\)$
|
||||||
|
@@ -7,6 +7,6 @@
|
|||||||
|
|
||||||
\${var
|
\${var
|
||||||
|
|
||||||
syntax error, unexpected \$end, expecting } \(5\)
|
syntax error, unexpected \$end, expecting } \(6\)
|
||||||
Call Stack \(most recent call first\):
|
Call Stack \(most recent call first\):
|
||||||
CMakeLists.txt:3 \(include\)$
|
CMakeLists.txt:3 \(include\)$
|
||||||
|
@@ -7,6 +7,6 @@
|
|||||||
|
|
||||||
\${var with space}
|
\${var with space}
|
||||||
|
|
||||||
syntax error, unexpected cal_SYMBOL, expecting } \(17\)
|
syntax error, unexpected cal_SYMBOL, expecting } \(3\)
|
||||||
Call Stack \(most recent call first\):
|
Call Stack \(most recent call first\):
|
||||||
CMakeLists.txt:3 \(include\)$
|
CMakeLists.txt:3 \(include\)$
|
||||||
|
@@ -7,6 +7,6 @@
|
|||||||
|
|
||||||
\${var
|
\${var
|
||||||
|
|
||||||
syntax error, unexpected \$end, expecting } \(5\)
|
syntax error, unexpected \$end, expecting } \(6\)
|
||||||
Call Stack \(most recent call first\):
|
Call Stack \(most recent call first\):
|
||||||
CMakeLists.txt:3 \(include\)$
|
CMakeLists.txt:3 \(include\)$
|
||||||
|
@@ -7,6 +7,6 @@
|
|||||||
|
|
||||||
\${var with tab}
|
\${var with tab}
|
||||||
|
|
||||||
syntax error, unexpected cal_SYMBOL, expecting } \(15\)
|
syntax error, unexpected cal_SYMBOL, expecting } \(3\)
|
||||||
Call Stack \(most recent call first\):
|
Call Stack \(most recent call first\):
|
||||||
CMakeLists.txt:3 \(include\)$
|
CMakeLists.txt:3 \(include\)$
|
||||||
|
@@ -15,6 +15,6 @@ CMake Error at ParenInENV.cmake:2 \(message\):
|
|||||||
|
|
||||||
-->\$ENV{e
|
-->\$ENV{e
|
||||||
|
|
||||||
syntax error, unexpected \$end, expecting } \(9\)
|
syntax error, unexpected \$end, expecting } \(10\)
|
||||||
Call Stack \(most recent call first\):
|
Call Stack \(most recent call first\):
|
||||||
CMakeLists.txt:3 \(include\)
|
CMakeLists.txt:3 \(include\)
|
||||||
|
@@ -7,6 +7,6 @@ CMake Error at ParenInVarName1.cmake:4 \(message\):
|
|||||||
|
|
||||||
-->\${e\(x\)}<--
|
-->\${e\(x\)}<--
|
||||||
|
|
||||||
syntax error, unexpected cal_SYMBOL, expecting } \(10\)
|
syntax error, unexpected cal_SYMBOL, expecting } \(6\)
|
||||||
Call Stack \(most recent call first\):
|
Call Stack \(most recent call first\):
|
||||||
CMakeLists.txt:3 \(include\)
|
CMakeLists.txt:3 \(include\)
|
||||||
|
@@ -7,6 +7,6 @@ CMake Error at UnterminatedBrace0.cmake:2 \(set\):
|
|||||||
|
|
||||||
\${
|
\${
|
||||||
|
|
||||||
syntax error, unexpected \$end, expecting } \(2\)
|
syntax error, unexpected \$end, expecting } \(3\)
|
||||||
Call Stack \(most recent call first\):
|
Call Stack \(most recent call first\):
|
||||||
CMakeLists.txt:3 \(include\)
|
CMakeLists.txt:3 \(include\)
|
||||||
|
@@ -7,7 +7,7 @@ CMake Warning \(dev\) at UnterminatedBrace1.cmake:3 \(set\):
|
|||||||
|
|
||||||
\${
|
\${
|
||||||
|
|
||||||
syntax error, unexpected \$end, expecting } \(2\)
|
syntax error, unexpected \$end, expecting } \(3\)
|
||||||
Call Stack \(most recent call first\):
|
Call Stack \(most recent call first\):
|
||||||
CMakeLists.txt:3 \(include\)
|
CMakeLists.txt:3 \(include\)
|
||||||
This warning is for project developers. Use -Wno-dev to suppress it.
|
This warning is for project developers. Use -Wno-dev to suppress it.
|
||||||
|
Reference in New Issue
Block a user