diff options
author | Chad MILLER <chad@mysql.com> | 2009-04-10 10:18:57 -0400 |
---|---|---|
committer | Chad MILLER <chad@mysql.com> | 2009-04-10 10:18:57 -0400 |
commit | ebd4f43e442473b980508a14b0bbb43ca138b3bd (patch) | |
tree | 70253e0b69b42f895704ede0847f56388999b264 /sql | |
parent | bb08984f07bd52690471cd9159192e74ab20ebb5 (diff) | |
parent | 8c828507e4f79ca3e2e12b6aeccc18a7a441fcf9 (diff) | |
download | mariadb-git-ebd4f43e442473b980508a14b0bbb43ca138b3bd.tar.gz |
Merge fix for bug 39559 and bugteam trunk.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/sql_lex.cc | 91 | ||||
-rw-r--r-- | sql/sql_lex.h | 14 |
2 files changed, 83 insertions, 22 deletions
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 69b8c486d5f..b96ac91679b 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -713,6 +713,53 @@ static inline uint int_token(const char *str,uint length) return ((uchar) str[-1] <= (uchar) cmp[-1]) ? smaller : bigger; } + +/** + Given a stream that is advanced to the first contained character in + an open comment, consume the comment. Optionally, if we are allowed, + recurse so that we understand comments within this current comment. + + At this level, we do not support version-condition comments. We might + have been called with having just passed one in the stream, though. In + that case, we probably want to tolerate mundane comments inside. Thus, + the case for recursion. + + @retval Whether EOF reached before comment is closed. +*/ +bool consume_comment(Lex_input_stream *lip, int remaining_recursions_permitted) +{ + reg1 uchar c; + while (! lip->eof()) + { + c= lip->yyGet(); + + if (remaining_recursions_permitted > 0) + { + if ((c == '/') && (lip->yyPeek() == '*')) + { + lip->yySkip(); /* Eat asterisk */ + consume_comment(lip, remaining_recursions_permitted-1); + continue; + } + } + + if (c == '*') + { + if (lip->yyPeek() == '/') + { + lip->yySkip(); /* Eat slash */ + return FALSE; + } + } + + if (c == '\n') + lip->yylineno++; + } + + return TRUE; +} + + /* MYSQLlex remember the following states from the following MYSQLlex() @@ -1205,6 +1252,8 @@ int MYSQLlex(void *arg, void *yythd) /* Reject '/' '*', since we might need to turn off the echo */ lip->yyUnget(); + lip->save_in_comment_state(); + if (lip->yyPeekn(2) == '!') { lip->in_comment= DISCARD_COMMENT; @@ -1247,11 +1296,17 @@ int MYSQLlex(void *arg, void *yythd) /* Expand the content of the special comment as real code */ lip->set_echo(TRUE); state=MY_LEX_START; - break; + break; /* Do not treat contents as a comment. */ + } + else + { + comment_closed= ! consume_comment(lip, 1); + /* version allowed to have one level of comment inside. */ } } else { + /* Not a version comment. */ state=MY_LEX_START; lip->set_echo(TRUE); break; @@ -1262,38 +1317,30 @@ int MYSQLlex(void *arg, void *yythd) lip->in_comment= PRESERVE_COMMENT; lip->yySkip(); // Accept / lip->yySkip(); // Accept * + comment_closed= ! consume_comment(lip, 0); + /* regular comments can have zero comments inside. */ } /* Discard: - regular '/' '*' comments, - special comments '/' '*' '!' for a future version, by scanning until we find a closing '*' '/' marker. - Note: There is no such thing as nesting comments, - the first '*' '/' sequence seen will mark the end. + + Nesting regular comments isn't allowed. The first + '*' '/' returns the parser to the previous state. + + /#!VERSI oned containing /# regular #/ is allowed #/ + + Inside one versioned comment, another versioned comment + is treated as a regular discardable comment. It gets + no special parsing. */ - comment_closed= FALSE; - while (! lip->eof()) - { - c= lip->yyGet(); - if (c == '*') - { - if (lip->yyPeek() == '/') - { - lip->yySkip(); - comment_closed= TRUE; - state = MY_LEX_START; - break; - } - } - else if (c == '\n') - lip->yylineno++; - } + /* Unbalanced comments with a missing '*' '/' are a syntax error */ if (! comment_closed) return (ABORT_SYM); state = MY_LEX_START; // Try again - lip->in_comment= NO_COMMENT; - lip->set_echo(TRUE); + lip->restore_in_comment_state(); break; case MY_LEX_END_LONG_COMMENT: if ((lip->in_comment != NO_COMMENT) && lip->yyPeek() == '/') diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 172940cf9d7..62106a2500b 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1160,6 +1160,18 @@ public: m_echo= echo; } + void save_in_comment_state() + { + m_echo_saved= m_echo; + in_comment_saved= in_comment; + } + + void restore_in_comment_state() + { + m_echo= m_echo_saved; + in_comment= in_comment_saved; + } + /** Skip binary from the input stream. @param n number of bytes to accept. @@ -1417,6 +1429,7 @@ private: /** Echo the parsed stream to the pre-processed buffer. */ bool m_echo; + bool m_echo_saved; /** Pre-processed buffer. */ char *m_cpp_buf; @@ -1479,6 +1492,7 @@ public: /** State of the lexical analyser for comments. */ enum_comment_state in_comment; + enum_comment_state in_comment_saved; /** Starting position of the TEXT_STRING or IDENT in the pre-processed |