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 #include <base/strings.h>
28 #include "state.h"
29 #include "wqlyacc.h"
30
31 extern void* wqlmalloc(size_t size);
32 extern MI_Char* wqlstrdup(const MI_Char* str);
33
34 int wqllex()
35 {
36 const MI_Char* p = wqlstate.ptr;
37
38 /* Skip whitespace */
39 while (*p && isspace(*p))
40 p++;
41
42 /* Return on end-of-file */
43 mike 1.1 if (*p == '\0')
44 {
45 wqlstate.ptr = p;
46 return 0;
47 }
48
49 /* Recognize identifier */
50 if (isalpha(*p) || *p == '_')
51 {
52 const MI_Char* start = p++;
53 size_t n;
54
55 while (isalnum(*p) || *p == '_')
56 p++;
57
58 wqlstate.ptr = p;
59
60 if (Zncasecmp(start, MI_T("select"), 6) == 0)
61 return WQL_SELECT;
62 else if (Zncasecmp(start, MI_T("from"), 4) == 0)
63 return WQL_FROM;
64 mike 1.1 else if (Zncasecmp(start, MI_T("where"), 5) == 0)
65 return WQL_WHERE;
66 else if (Zncasecmp(start, MI_T("not"), 3) == 0)
67 return WQL_NOT;
68 else if (Zncasecmp(start, MI_T("and"), 3) == 0)
69 return WQL_AND;
70 else if (Zncasecmp(start, MI_T("or"), 2) == 0)
71 return WQL_OR;
72 else if (Zncasecmp(start, MI_T("null"), 2) == 0)
73 return WQL_NULL;
74 else if (Zncasecmp(start, MI_T("true"), 4) == 0)
75 {
76 wqllval.boolean = 1;
77 return WQL_BOOLEAN;
78 }
79 else if (Zncasecmp(start, MI_T("false"), 5) == 0)
80 {
81 wqllval.boolean = 0;
82 return WQL_BOOLEAN;
83 }
84
85 mike 1.1 n = p - start;
86 wqllval.string = (MI_Char*)wqlmalloc(n + 1);
87
88 if (!wqllval.string)
89 return -1;
90
91 memcpy(wqllval.string, start, n);
92 wqllval.string[n] = '\0';
93
94 return WQL_IDENTIFIER;
95 }
96
97 /* Recognize number (integer or double) */
98 if (*p == '+' || *p == '-' || isdigit(*p))
99 {
100 const MI_Char* start = p++;
101
102 while (isdigit(*p))
103 p++;
104
105 if (*p == '.')
106 mike 1.1 {
107 MI_Char* end;
108 wqllval.real = Ztod(start, &end);
109 p = end;
110 wqlstate.ptr = p;
111 return WQL_REAL;
112 }
113 else
114 {
115 MI_Char* end;
116 wqllval.integer = Ztoll(start, &end, 10);
117 p = end;
118 wqlstate.ptr = p;
119 return WQL_INTEGER;
120 }
121 }
122
123 /* Recognize string literal */
124 if (*p == '"')
125 {
126 const MI_Char* start = ++p;
127 mike 1.1 size_t n = 0;
128 MI_Char* q;
129
130 /* Determine the length of the string */
131 while (*p && *p != '"')
132 {
133 if (*p == '\\')
134 {
135 if (*++p == '\0')
136 return -1;
137 }
138
139 p++;
140 n++;
141 }
142
143 /* Allocate new string */
144 {
145 q = wqlmalloc(n + 1);
146
147 if (!q)
148 mike 1.1 return -1;
149
150 wqllval.string = q;
151 }
152
153 /* Convert string */
154 for (p = start; *p && *p != '"'; )
155 {
156 if (*p == '\\')
157 {
158 p++;
159 switch (*p)
160 {
161 case '\0':
162 return -1;
163 case 'n':
164 *q++ = '\n';
165 break;
166 case 'r':
167 *q++ = '\r';
168 break;
169 mike 1.1 case 'f':
170 *q++ = '\r';
171 break;
172 case '"':
173 *q++ = '"';
174 break;
175 case '\\':
176 *q++ = '\\';
177 break;
178 default:
179 *q++ = *p;
180 }
181 p++;
182 }
183 else
184 *q++ = *p++;
185 }
186
187 /* String literal must be terminated */
188 if (*p++ != '"')
189 return -1;
190 mike 1.1
191 /* Null terminate string */
192 *q = '\0';
193 wqlstate.ptr = p;
194 return WQL_STRING;
195 }
196
197 /* WQL_EQ */
198 if (p[0] == '=')
199 {
200 wqlstate.ptr = p + 1;
201 return WQL_EQ;
202 }
203
204 /* WQL_NE */
205 if ((p[0] == '<' && p[1] == '>') || (p[0] == '!' && p[1] == '='))
206 {
207 wqlstate.ptr = p + 2;
208 return WQL_NE;
209 }
210
211 mike 1.1 /* WQL_LE */
212 if (p[0] == '<' && p[1] == '=')
213 {
214 wqlstate.ptr = p + 2;
215 return WQL_LE;
216 }
217
218 /* WQL_LT */
219 if (p[0] == '<')
220 {
221 wqlstate.ptr = p + 1;
222 return WQL_LT;
223 }
224
225 /* WQL_GE */
226 if (p[0] == '>' && p[1] == '=')
227 {
228 wqlstate.ptr = p + 2;
229 return WQL_GE;
230 }
231
232 mike 1.1 /* WQL_GT */
233 if (p[0] == '>')
234 {
235 wqlstate.ptr = p + 1;
236 return WQL_GT;
237 }
238
239 /* Match single characters */
240 if (*p == '*' || *p == '(' || *p == ')' || *p == ',')
241 {
242 wqlstate.ptr = p + 1;
243 return *p;
244 }
245
246 /* Unrecognized tokens */
247 return WQL_ERROR;
248 }
|