Преглед на файлове

ENH: Improve handling of escaped characters

Andy Cedilnik преди 20 години
родител
ревизия
1bbccc5bef

+ 19 - 10
Source/cmCommandArgumentLexer.cxx

@@ -341,8 +341,8 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
   *yy_cp = '\0'; \
   yyg->yy_c_buf_p = yy_cp;
 
-#define YY_NUM_RULES 11
-#define YY_END_OF_BUFFER 12
+#define YY_NUM_RULES 12
+#define YY_END_OF_BUFFER 13
 /* This struct is not used in this scanner,
    but its presence is necessary. */
 struct yy_trans_info
@@ -352,8 +352,8 @@ struct yy_trans_info
   };
 static yyconst flex_int16_t yy_accept[20] =
     {   0,
-        0,    0,   12,    7,    8,    6,    5,   10,    9,    4,
-        7,    0,    3,    6,    0,    7,    1,    2,    0
+        0,    0,   13,    8,    9,    6,    5,   11,   10,    4,
+        8,    0,    3,    6,    0,    7,    1,    2,    0
     } ;
 
 static yyconst flex_int32_t yy_ec[256] =
@@ -859,7 +859,17 @@ YY_RULE_SETUP
   return cal_NAME; 
 }
 case 7:
-/* rule 7 can match eol */
+YY_RULE_SETUP
+
+{
+  if ( !yyextra->HandleEscapeSymbol(yylvalp, *(yytext+1)) )
+    {
+    return cal_ERROR;
+    }
+  return cal_SYMBOL; 
+}
+case 8:
+/* rule 8 can match eol */
 YY_RULE_SETUP
 
 { 
@@ -867,7 +877,7 @@ YY_RULE_SETUP
   yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext)); 
   return cal_SYMBOL; 
 }
-case 8:
+case 9:
 YY_RULE_SETUP
 
 {
@@ -875,7 +885,7 @@ YY_RULE_SETUP
   yylvalp->str = yyextra->m_DOLLARVariable;
   return cal_DOLLAR; 
 }
-case 9:
+case 10:
 YY_RULE_SETUP
 
 {
@@ -883,7 +893,7 @@ YY_RULE_SETUP
   yylvalp->str = yyextra->m_LCURLYVariable;
   return cal_LCURLY; 
 }
-case 10:
+case 11:
 YY_RULE_SETUP
 
 {
@@ -891,7 +901,7 @@ YY_RULE_SETUP
   yylvalp->str = yyextra->m_BSLASHVariable;
   return cal_BSLASH; 
 }
-case 11:
+case 12:
 YY_RULE_SETUP
 
 ECHO;
@@ -1220,7 +1230,6 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
   return yy_is_jam ? 0 : yy_current_state;
 }
 
-
 #ifndef YY_NO_INPUT
 #ifdef __cplusplus
     static int yyinput (yyscan_t yyscanner)

+ 9 - 1
Source/cmCommandArgumentLexer.in.l

@@ -124,7 +124,15 @@ Modify cmCommandArgumentLexer.h:
   return cal_NAME; 
 }
 
-[^\${}\\@]+|\\. { 
+\\. {
+  if ( !yyextra->HandleEscapeSymbol(yylvalp, *(yytext+1)) )
+    {
+    return cal_ERROR;
+    }
+  return cal_SYMBOL; 
+}
+
+[^\${}\\@]+ { 
   //std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl;
   yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext)); 
   return cal_SYMBOL; 

+ 50 - 1
Source/cmCommandArgumentParserHelper.cxx

@@ -22,7 +22,7 @@
 #include "cmMakefile.h"
 
 int cmCommandArgument_yyparse( yyscan_t yyscanner );
-
+//
 cmCommandArgumentParserHelper::cmCommandArgumentParserHelper()
 {
   m_FileLine = -1;
@@ -35,6 +35,8 @@ cmCommandArgumentParserHelper::cmCommandArgumentParserHelper()
   strcpy(m_DOLLARVariable, "$");
   strcpy(m_LCURLYVariable, "{");
   strcpy(m_BSLASHVariable, "\\");
+
+  m_NoEscapeMode = false;
 }
 
 
@@ -145,6 +147,53 @@ void cmCommandArgumentParserHelper::AllocateParserType(cmCommandArgumentParserHe
   // std::cout << (void*) pt->str << " " << pt->str << " JPAllocateParserType" << std::endl;
 }
 
+bool cmCommandArgumentParserHelper::HandleEscapeSymbol(cmCommandArgumentParserHelper::ParserType* pt, char symbol)
+{
+  if ( m_NoEscapeMode )
+    {
+    char buffer[3];
+    buffer[0] = '\\';
+    buffer[1] = symbol;
+    buffer[2] = 0;
+    this->AllocateParserType(pt, buffer, 2);
+    return true;
+    }
+  switch ( symbol )
+    {
+  case '\\':
+  case '"':
+  case ' ':
+  case '#':
+  case '(':
+  case ')':
+  case '$':
+  case '^':
+  case ';':
+    this->AllocateParserType(pt, &symbol, 1);
+    break;
+  case 't':
+    this->AllocateParserType(pt, "\t", 1);
+    break;
+  case 'n':
+    this->AllocateParserType(pt, "\n", 1);
+    break;
+  case 'r':
+    this->AllocateParserType(pt, "\r", 1);
+    break;
+  case '0':
+    this->AllocateParserType(pt, "\0", 1);
+    break;
+  default:
+    char buffer[2];
+    buffer[0] = symbol;
+    buffer[1] = 0;
+    cmSystemTools::Error("Invalid escape sequence \\", buffer);
+    abort();
+    return false;
+    }
+  return true;
+}
+
 int cmCommandArgumentParserHelper::ParseString(const char* str, int verb)
 {
   if ( !str)

+ 3 - 0
Source/cmCommandArgumentParserHelper.h

@@ -47,6 +47,7 @@ public:
   // For the lexer:
   void AllocateParserType(cmCommandArgumentParserHelper::ParserType* pt, 
     const char* str, int len = 0);
+  bool HandleEscapeSymbol(cmCommandArgumentParserHelper::ParserType* pt, char symbol);
 
   int LexInput(char* buf, int maxlen);
   void Error(const char* str);
@@ -64,6 +65,7 @@ public:
 
   void SetLineFile(long line, const char* file);
   void SetEscapeQuotes(bool b) { m_EscapeQuotes = b; }
+  void SetNoEscapeMode(bool b) { m_NoEscapeMode = b; }
 
   const char* GetError() { return m_Error.c_str(); }
 
@@ -97,6 +99,7 @@ private:
   long m_FileLine;
   bool m_EscapeQuotes;
   std::string m_Error;
+  bool m_NoEscapeMode;
 };
 
 #endif

+ 2 - 2
Source/cmListFileCache.cxx

@@ -247,13 +247,13 @@ bool cmListFileCacheParseFunction(cmListFileLexer* lexer,
     else if(token->type == cmListFileLexer_Token_Identifier ||
             token->type == cmListFileLexer_Token_ArgumentUnquoted)
       {
-      cmListFileArgument a(cmSystemTools::RemoveEscapes(token->text),
+      cmListFileArgument a(token->text,
                            false, filename, token->line);
       function.m_Arguments.push_back(a);
       }
     else if(token->type == cmListFileLexer_Token_ArgumentQuoted)
       {
-      cmListFileArgument a(cmSystemTools::RemoveEscapes(token->text),
+      cmListFileArgument a(token->text,
                            true, filename, token->line);
       function.m_Arguments.push_back(a);
       }

+ 6 - 4
Source/cmMakefile.cxx

@@ -1361,17 +1361,18 @@ std::vector<std::string> cmMakefile::GetDefinitions(int cacheonly /* = 0 */) con
 
 const char *cmMakefile::ExpandVariablesInString(std::string& source) const
 {
-  return this->ExpandVariablesInString(source, false);
+  return this->ExpandVariablesInString(source, false, false);
 }
 
 const char *cmMakefile::ExpandVariablesInString(std::string& source,
                                                 bool escapeQuotes,
+                                                bool noEscapes,
                                                 bool atOnly,
                                                 const char* filename,
                                                 long line,
                                                 bool removeEmpty) const
 {
-  if ( source.empty() || source.find_first_of("$@") == source.npos)
+  if ( source.empty() || source.find_first_of("$@\\") == source.npos)
     {
     return source.c_str();
     }
@@ -1387,6 +1388,7 @@ const char *cmMakefile::ExpandVariablesInString(std::string& source,
     parser.SetMakefile(this);
     parser.SetLineFile(line, filename);
     parser.SetEscapeQuotes(escapeQuotes);
+    parser.SetNoEscapeMode(noEscapes);
     int res = parser.ParseString(source.c_str(), 0);
     if ( res )
       {
@@ -1703,7 +1705,7 @@ void cmMakefile::ExpandArguments(
     {
     // Expand the variables in the argument.
     value = i->Value;
-    this->ExpandVariablesInString(value, false, false, i->FilePath, i->Line);
+    this->ExpandVariablesInString(value, false, false, false, i->FilePath, i->Line);
 
     // If the argument is quoted, it should be one argument.
     // Otherwise, it may be a list of arguments.
@@ -2353,7 +2355,7 @@ void cmMakefile::ConfigureString(const std::string& input,
     }
 
   // Perform variable replacements.
-  this->ExpandVariablesInString(output, escapeQuotes, atOnly, 0, -1, true);
+  this->ExpandVariablesInString(output, escapeQuotes, true, atOnly, 0, -1, true);
 //  this->RemoveVariablesInString(output, atOnly);
 }
 

+ 1 - 0
Source/cmMakefile.h

@@ -543,6 +543,7 @@ public:
    */
   const char *ExpandVariablesInString(std::string& source) const;
   const char *ExpandVariablesInString(std::string& source, bool escapeQuotes,
+                                      bool noEscapes,
                                       bool atOnly = false,
                                       const char* filename = 0,
                                       long line = -1,