summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorChad MILLER <chad@mysql.com>2009-04-10 10:18:57 -0400
committerChad MILLER <chad@mysql.com>2009-04-10 10:18:57 -0400
commitebd4f43e442473b980508a14b0bbb43ca138b3bd (patch)
tree70253e0b69b42f895704ede0847f56388999b264 /sql
parentbb08984f07bd52690471cd9159192e74ab20ebb5 (diff)
parent8c828507e4f79ca3e2e12b6aeccc18a7a441fcf9 (diff)
downloadmariadb-git-ebd4f43e442473b980508a14b0bbb43ca138b3bd.tar.gz
Merge fix for bug 39559 and bugteam trunk.
Diffstat (limited to 'sql')
-rw-r--r--sql/sql_lex.cc91
-rw-r--r--sql/sql_lex.h14
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