1 mike 1.1 /*
2 **==============================================================================
3 **
4 ** Open Management Infrastructure (OMI)
5 **
6 ** Copyright (c) Microsoft Corporation
7 **
8 ** Licensed under the Apache License, Version 2.0 (the "License"); you may not
9 ** use this file except in compliance with the License. You may obtain a copy
10 ** of the License at
11 **
12 ** http://www.apache.org/licenses/LICENSE-2.0
13 **
14 ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
16 ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
17 ** MERCHANTABLITY OR NON-INFRINGEMENT.
18 **
19 ** See the Apache 2 License for the specific language governing permissions
20 ** and limitations under the License.
21 **
22 mike 1.1 **==============================================================================
23 */
24
25 #include "wql.h"
26 #include <ctype.h>
|
27 krisbash 1.3
28 #if defined(CONFIG_POSIX)
29 # include <wctype.h>
30 #endif
31
32 #include <pal/strings.h>
33 #include <pal/format.h>
|
34 mike 1.1 #include "state.h"
35 #include "wqlyacc.h"
36
|
37 krisbash 1.3
|
38 mike 1.1 extern void* wqlmalloc(size_t size);
|
39 krisbash 1.3 extern ZChar* wqlstrdup(const ZChar* str);
40
41 MI_INLINE int _MatchToken(
42 const ZChar* str,
43 const ZChar* lcs, /* lower-case-string */
44 size_t n)
45 {
46 #if (MI_CHAR_TYPE == 1)
47 return tolower((int)str[0]) == lcs[0] &&
48 Tcsncasecmp(str, lcs, n) == 0 &&
49 !isalpha((int)str[n]) &&
50 str[n] != '_';
51 #else
52 return towlower(str[0]) == lcs[0] &&
53 Tcsncasecmp(str, lcs, n) == 0 &&
54 !isalpha((int)str[n] &&
55 str[n] != '_';
56 #endif
57 }
|
58 mike 1.1
59 int wqllex()
60 {
|
61 krisbash 1.3 const ZChar* p = wqlstate.ptr;
|
62 mike 1.1
63 /* Skip whitespace */
|
64 krisbash 1.3 while (*p && isspace((int)*p))
|
65 mike 1.1 p++;
66
67 /* Return on end-of-file */
68 if (*p == '\0')
69 {
70 wqlstate.ptr = p;
71 return 0;
72 }
73
74 /* Recognize identifier */
|
75 krisbash 1.3 if (isalpha((int)*p) || *p == '_')
|
76 mike 1.1 {
|
77 krisbash 1.3 const ZChar* start = p++;
|
78 mike 1.1 size_t n;
79
|
80 krisbash 1.3 while (isalnum((int)*p) || *p == '_')
|
81 mike 1.1 p++;
82
83 wqlstate.ptr = p;
|
84 krisbash 1.3 n = p - start;
|
85 mike 1.1
|
86 krisbash 1.3 if (_MatchToken(start, MI_T("select"), 6))
|
87 mike 1.1 return WQL_SELECT;
|
88 krisbash 1.3 else if (_MatchToken(start, MI_T("from"), 4))
|
89 mike 1.1 return WQL_FROM;
|
90 krisbash 1.3 else if (_MatchToken(start, MI_T("where"), 5))
|
91 mike 1.1 return WQL_WHERE;
|
92 krisbash 1.3 else if (_MatchToken(start, MI_T("not"), 3))
|
93 mike 1.1 return WQL_NOT;
|
94 krisbash 1.3 else if (_MatchToken(start, MI_T("and"), 3))
|
95 mike 1.1 return WQL_AND;
|
96 krisbash 1.3 else if (_MatchToken(start, MI_T("or"), 2))
|
97 mike 1.1 return WQL_OR;
|
98 krisbash 1.3 else if (_MatchToken(start, MI_T("null"), 4))
|
99 mike 1.1 return WQL_NULL;
|
100 krisbash 1.3 else if (_MatchToken(start, MI_T("true"), 4))
|
101 mike 1.1 {
102 wqllval.boolean = 1;
103 return WQL_BOOLEAN;
104 }
|
105 krisbash 1.3 else if (_MatchToken(start, MI_T("false"), 5))
|
106 mike 1.1 {
107 wqllval.boolean = 0;
108 return WQL_BOOLEAN;
109 }
|
110 krisbash 1.3 else if (_MatchToken(start, MI_T("like"), 4))
111 return WQL_LIKE;
112 else if (_MatchToken(start, MI_T("isa"), 3))
113 return WQL_ISA;
|
114 mike 1.1
|
115 krisbash 1.3 wqllval.string = (ZChar*)wqlmalloc((n + 1) * sizeof(ZChar));
|
116 mike 1.1
117 if (!wqllval.string)
118 return -1;
119
|
120 krisbash 1.3 memcpy(wqllval.string, start, n * sizeof(ZChar));
|
121 mike 1.1 wqllval.string[n] = '\0';
122
123 return WQL_IDENTIFIER;
124 }
125
126 /* Recognize number (integer or double) */
127 if (*p == '+' || *p == '-' || isdigit(*p))
128 {
|
129 krisbash 1.3 const ZChar* start = p++;
|
130 mike 1.1
131 while (isdigit(*p))
132 p++;
133
134 if (*p == '.')
135 {
|
136 krisbash 1.3 ZChar* end;
137 wqllval.real = Tcstod(start, &end);
|
138 mike 1.1 p = end;
139 wqlstate.ptr = p;
140 return WQL_REAL;
141 }
142 else
143 {
|
144 krisbash 1.3 ZChar* end;
145 wqllval.integer = Tcstoll(start, &end, 10);
|
146 mike 1.1 p = end;
147 wqlstate.ptr = p;
148 return WQL_INTEGER;
149 }
150 }
151
|
152 krisbash 1.3 /* Recognize string literal, starting with full quote or semi quote */
153 if (*p == '"' || *p == '\'')
|
154 mike 1.1 {
|
155 krisbash 1.3 ZChar term = *p;
156 const ZChar* start = ++p;
|
157 mike 1.1 size_t n = 0;
|
158 krisbash 1.3 ZChar* q;
|
159 mike 1.1
160 /* Determine the length of the string */
|
161 krisbash 1.3 while (*p && *p != term)
|
162 mike 1.1 {
163 if (*p == '\\')
164 {
165 if (*++p == '\0')
166 return -1;
167 }
168
169 p++;
170 n++;
171 }
172
173 /* Allocate new string */
174 {
|
175 krisbash 1.3 q = wqlmalloc((n + 1) * sizeof(ZChar));
|
176 mike 1.1
177 if (!q)
178 return -1;
179
180 wqllval.string = q;
181 }
182
183 /* Convert string */
|
184 krisbash 1.3 for (p = start; *p && *p != term; )
|
185 mike 1.1 {
186 if (*p == '\\')
187 {
188 p++;
189 switch (*p)
190 {
191 case '\0':
192 return -1;
193 case 'n':
194 *q++ = '\n';
195 break;
196 case 'r':
197 *q++ = '\r';
198 break;
199 case 'f':
200 *q++ = '\r';
201 break;
202 case '"':
203 *q++ = '"';
204 break;
205 case '\\':
206 mike 1.1 *q++ = '\\';
207 break;
208 default:
209 *q++ = *p;
210 }
211 p++;
212 }
213 else
214 *q++ = *p++;
215 }
216
217 /* String literal must be terminated */
|
218 krisbash 1.3 if (*p++ != term)
|
219 mike 1.1 return -1;
220
221 /* Null terminate string */
222 *q = '\0';
223 wqlstate.ptr = p;
224 return WQL_STRING;
225 }
226
227 /* WQL_EQ */
228 if (p[0] == '=')
229 {
230 wqlstate.ptr = p + 1;
231 return WQL_EQ;
232 }
233
234 /* WQL_NE */
235 if ((p[0] == '<' && p[1] == '>') || (p[0] == '!' && p[1] == '='))
236 {
237 wqlstate.ptr = p + 2;
238 return WQL_NE;
239 }
240 mike 1.1
241 /* WQL_LE */
242 if (p[0] == '<' && p[1] == '=')
243 {
244 wqlstate.ptr = p + 2;
245 return WQL_LE;
246 }
247
248 /* WQL_LT */
249 if (p[0] == '<')
250 {
251 wqlstate.ptr = p + 1;
252 return WQL_LT;
253 }
254
255 /* WQL_GE */
256 if (p[0] == '>' && p[1] == '=')
257 {
258 wqlstate.ptr = p + 2;
259 return WQL_GE;
260 }
261 mike 1.1
262 /* WQL_GT */
263 if (p[0] == '>')
264 {
265 wqlstate.ptr = p + 1;
266 return WQL_GT;
267 }
268
269 /* Match single characters */
270 if (*p == '*' || *p == '(' || *p == ')' || *p == ',')
271 {
272 wqlstate.ptr = p + 1;
273 return *p;
274 }
275
|
276 krisbash 1.3 /* WQL_GT */
277 if (p[0] == '.')
278 {
279 wqlstate.ptr = p + 1;
280 return WQL_DOT;
281 }
282
283 /* WQL_COLON */
284 if (p[0] == ':')
285 {
286 wqlstate.ptr = p + 1;
287 return WQL_COLON;
288 }
289
|
290 mike 1.1 /* Unrecognized tokens */
291 return WQL_ERROR;
292 }
|