1 /*
2 Copyright (c) 2015, 2021, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 Without limiting anything contained in the foregoing, this file,
16 which is part of C Driver for MySQL (Connector/C), is also subject to the
17 Universal FOSS Exception, version 1.0, a copy of which can be found at
18 http://oss.oracle.com/licenses/universal-foss-exception.
19
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License, version 2.0, for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
28
29 #include "sql_chars.h"
30 #include "m_ctype.h"
31 #include "my_sys.h"
32
33 static
hint_lex_init_maps(charset_info_st * cs,enum hint_lex_char_classes * hint_map)34 void hint_lex_init_maps(charset_info_st *cs,
35 enum hint_lex_char_classes *hint_map)
36 {
37 size_t i;
38 for (i= 0; i < 256 ; i++)
39 {
40 if (my_ismb1st(cs, i))
41 hint_map[i]= HINT_CHR_MB;
42 else if (my_isalpha(cs, i))
43 hint_map[i]= HINT_CHR_IDENT;
44 else if (my_isdigit(cs, i))
45 hint_map[i]= HINT_CHR_DIGIT;
46 else if (my_isspace(cs, i))
47 {
48 assert(!my_ismb1st(cs, i));
49 hint_map[i]= HINT_CHR_SPACE;
50 }
51 else
52 hint_map[i]= HINT_CHR_CHAR;
53 }
54 hint_map[(uchar) '*']= HINT_CHR_ASTERISK;
55 hint_map[(uchar) '@']= HINT_CHR_AT;
56 hint_map[(uchar) '`']= HINT_CHR_BACKQUOTE;
57 hint_map[(uchar) '"']= HINT_CHR_DOUBLEQUOTE;
58 hint_map[(uchar) '_']= HINT_CHR_IDENT;
59 hint_map[(uchar) '$']= HINT_CHR_IDENT;
60 hint_map[(uchar) '/']= HINT_CHR_SLASH;
61 hint_map[(uchar) '\n']= HINT_CHR_NL;
62 }
63
64
init_state_maps(charset_info_st * cs)65 my_bool init_state_maps(charset_info_st *cs)
66 {
67 uint i;
68 uchar *ident_map;
69 enum my_lex_states *state_map= NULL;
70
71 lex_state_maps_st *lex_state_maps=
72 (lex_state_maps_st *) my_once_alloc(sizeof(lex_state_maps_st), MYF(MY_WME));
73
74 if (lex_state_maps == NULL)
75 return TRUE; // OOM
76
77 cs->state_maps= lex_state_maps;
78 state_map= lex_state_maps->main_map;
79
80 if (!(cs->ident_map= ident_map= (uchar*) my_once_alloc(256, MYF(MY_WME))))
81 return TRUE; // OOM
82
83 hint_lex_init_maps(cs, lex_state_maps->hint_map);
84
85 /* Fill state_map with states to get a faster parser */
86 for (i=0; i < 256 ; i++)
87 {
88 if (my_isalpha(cs,i))
89 state_map[i]= MY_LEX_IDENT;
90 else if (my_isdigit(cs,i))
91 state_map[i]= MY_LEX_NUMBER_IDENT;
92 else if (my_ismb1st(cs, i))
93 /* To get whether it's a possible leading byte for a charset. */
94 state_map[i]= MY_LEX_IDENT;
95 else if (my_isspace(cs,i))
96 state_map[i]= MY_LEX_SKIP;
97 else
98 state_map[i]= MY_LEX_CHAR;
99 }
100 state_map[(uchar)'_']=state_map[(uchar)'$']= MY_LEX_IDENT;
101 state_map[(uchar)'\'']= MY_LEX_STRING;
102 state_map[(uchar)'.']= MY_LEX_REAL_OR_POINT;
103 state_map[(uchar)'>']=state_map[(uchar)'=']=state_map[(uchar)'!']= MY_LEX_CMP_OP;
104 state_map[(uchar)'<']= MY_LEX_LONG_CMP_OP;
105 state_map[(uchar)'&']=state_map[(uchar)'|']= MY_LEX_BOOL;
106 state_map[(uchar)'#']= MY_LEX_COMMENT;
107 state_map[(uchar)';']= MY_LEX_SEMICOLON;
108 state_map[(uchar)':']= MY_LEX_SET_VAR;
109 state_map[0]= MY_LEX_EOL;
110 state_map[(uchar)'\\']= MY_LEX_ESCAPE;
111 state_map[(uchar)'/']= MY_LEX_LONG_COMMENT;
112 state_map[(uchar)'*']= MY_LEX_END_LONG_COMMENT;
113 state_map[(uchar)'@']= MY_LEX_USER_END;
114 state_map[(uchar) '`']= MY_LEX_USER_VARIABLE_DELIMITER;
115 state_map[(uchar)'"']= MY_LEX_STRING_OR_DELIMITER;
116
117 /*
118 Create a second map to make it faster to find identifiers
119 */
120 for (i=0; i < 256 ; i++)
121 {
122 ident_map[i]= (uchar) (state_map[i] == MY_LEX_IDENT ||
123 state_map[i] == MY_LEX_NUMBER_IDENT);
124 }
125
126 /* Special handling of hex and binary strings */
127 state_map[(uchar)'x']= state_map[(uchar)'X']= MY_LEX_IDENT_OR_HEX;
128 state_map[(uchar)'b']= state_map[(uchar)'B']= MY_LEX_IDENT_OR_BIN;
129 state_map[(uchar)'n']= state_map[(uchar)'N']= MY_LEX_IDENT_OR_NCHAR;
130
131 return FALSE;
132 }
133