(file) Return to lexer.c CVS log (file) (dir) Up to [OMI] / omi / wql

  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              }

ViewCVS 0.9.2