1 /**
2 Copyright (C) 1995, 1996 by Ke Jin <kejin@visigenic.com>
3 Enhanced for unixODBC (1999) by Peter Harvey <pharvey@codebydesign.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 **/
15 #include <config.h>
16 #include <nnconfig.h>
17
18 #include <yyenv.h>
19 #include <yystmt.h>
20 #include <yylex.h>
21 #include <yyparse.tab.h>
22
23 #include "yylex.ci"
24
25 # define YYERRCODE 256
26
27 #include <stdio.h>
28 #include <ctype.h>
29
getcmpopidxbyname(char * name)30 static int getcmpopidxbyname(char* name)
31 {
32 int i, size;
33
34 size = sizeof(cmpop_tab)/sizeof(cmpop_tab[0]);
35
36 for(i=0; i<size; i++)
37 {
38 if(STREQ(name, cmpop_tab[i].name))
39 return cmpop_tab[i].idx;
40 }
41
42 return YYERRCODE;
43 }
44
getkeywdidxbyname(char * name)45 static int getkeywdidxbyname(char* name)
46 {
47 int i, size;
48
49 size = sizeof(keywd_tab)/sizeof(keywd_tab[0]);
50
51 for(i=0; i<size; i++)
52 {
53 if(upper_strneq(name, keywd_tab[i].name, 12))
54 return keywd_tab[i].idx;
55 }
56
57 return YYERRCODE;
58 }
59
getxkeywdidxbyname(char * name)60 static int getxkeywdidxbyname(char* name)
61 {
62 int i, size;
63
64 size = sizeof(xkeywd_tab)/sizeof(xkeywd_tab[0]);
65
66 for(i=0; i<size; i++)
67 {
68 if(upper_strneq(name, xkeywd_tab[i].name, 6))
69 return xkeywd_tab[i].idx;
70 }
71
72 return YYERRCODE;
73 }
74
popc(yyenv_t * penv)75 static char popc(yyenv_t* penv)
76 {
77 char c;
78
79 c = (penv->pstmt->sqlexpr)[(penv->scanpos)];
80 (penv->errpos) = (penv->scanpos);
81 (penv->scanpos) ++;
82
83 return c;
84 }
85
unputc(char c,yyenv_t * penv)86 static void unputc(char c, yyenv_t* penv)
87 {
88 (penv->errpos) = (--(penv->scanpos));
89
90 if( (penv->pstmt->sqlexpr)[(penv->scanpos)] != c )
91 (penv->pstmt->sqlexpr)[(penv->scanpos)] = c;
92 }
93
getnum(yyenv_t * penv)94 static long getnum(yyenv_t* penv)
95 {
96 long a;
97 char c;
98 int i, errpos = (penv->scanpos);
99
100 a = atol((penv->pstmt->sqlexpr) + (penv->scanpos));
101
102 for(i=0;;i++)
103 {
104 c = popc(penv);
105
106 if( ! isdigit(c) )
107 {
108 unputc(c, penv);
109 break;
110 }
111 }
112
113 (penv->errpos) = errpos;
114 return a;
115 }
116
getqstring(char * buf,int len,yyenv_t * penv,char term)117 static int getqstring(char* buf, int len, yyenv_t* penv, char term)
118 {
119 char c, c1;
120 int i, errpos = (penv->scanpos);
121
122 for(i=0; len == -1 || i<len; i++)
123 {
124 buf[i] = c = popc(penv);
125
126 if( c == term )
127 {
128 c1 = popc(penv);
129
130 if( c1 == term )
131 continue;
132
133 unputc(c1, penv);
134 break;
135 }
136
137 if( !c || c == '\n' )
138 return YYERRCODE;
139 }
140
141 buf[i] = 0;
142 (penv->errpos) = errpos;
143
144 return i;
145 }
146
getname(char * buf,int len,yyenv_t * penv)147 static int getname(char* buf, int len, yyenv_t* penv)
148 {
149 int i = 0;
150 char c;
151 int errpos = (penv->scanpos);
152
153 for(i=0; len == -1 || i<len; i++)
154 {
155 buf[i] = c = popc(penv);
156
157 if( isalpha(c) || (i && isdigit(c)) )
158 continue;
159 else if( i )
160 {
161 char c1;
162
163 c1 = popc(penv);
164
165 unputc(c1, penv);
166
167 switch(c)
168 {
169 case '+': /* a group name may use '+'
170 such as comp.lang.c++ */
171 case '-': /* a group name may use '-'
172 such as comp.client-server */
173 /* However, the best way is
174 using double quato '"' for
175 such kind of group name */
176 case '_':
177 continue;
178
179 case '.':
180 if(isalpha(c1))
181 continue;
182 break;
183
184 default:
185 break;
186 }
187 }
188
189 break;
190 }
191
192 buf[i] = 0;
193 unputc(c, penv);
194 (penv->errpos) = errpos;
195
196 return i;
197 }
198
getcmpop(yyenv_t * penv)199 static int getcmpop(yyenv_t* penv)
200 {
201 char opname[3];
202 char c, c1;
203 int errpos = (penv->scanpos);
204
205 opname[0] = c = popc(penv);
206 opname[1] = c1= popc(penv);
207 opname[2] = 0;
208
209 if( c1 != '=' && c1 != '>' && c1 != '<' )
210 {
211 opname[1] = 0;
212 unputc(c1, penv);
213 }
214
215 (penv->errpos) = errpos;
216
217 return getcmpopidxbyname(opname);
218 }
219
nnsql_yylex(YYSTYPE * pyylval,yyenv_t * penv)220 int nnsql_yylex(YYSTYPE* pyylval, yyenv_t* penv)
221 {
222 int len, cmpop;
223 char c;
224
225 do
226 { c = popc(penv); }
227 while( c == ' ' || c == '\t' || c == '\n' );
228
229 if( isalpha(c) )
230 {
231 int keywdidx;
232
233 unputc(c, penv);
234
235 len = getname(penv->texts_bufptr, -1, penv);
236
237 if( len == YYERRCODE )
238 return len;
239
240 if( penv->extlevel )
241 keywdidx = getxkeywdidxbyname( penv->texts_bufptr );
242 else
243 keywdidx = YYERRCODE;
244
245 if( keywdidx == YYERRCODE )
246 keywdidx = getkeywdidxbyname( penv->texts_bufptr);
247
248 if( keywdidx != YYERRCODE )
249 return keywdidx;
250
251 pyylval->name = penv->texts_bufptr;
252 (penv->texts_bufptr) += (len + 1);
253
254 return NAME;
255 }
256
257 if( isdigit(c) )
258 {
259 unputc(c, penv);
260
261 pyylval->number = getnum(penv);
262
263 return NUM;
264 }
265
266 switch( c )
267 {
268 case ';':
269 case '\0':
270 return ';';
271
272
273 case '\'':
274 case '"':
275 len = getqstring(penv->texts_bufptr, -1, penv, c);
276
277 if( len == YYERRCODE )
278 return len;
279
280 if( c == '\'' )
281 {
282 pyylval->qstring = penv->texts_bufptr;
283 penv->texts_bufptr += (len + 1);
284 return QSTRING;
285 }
286
287 pyylval->name = penv->texts_bufptr;
288 (penv->texts_bufptr) += (len + 1);
289 return NAME;
290
291 case '=':
292 case '<':
293 case '>':
294 case '!':
295 unputc(c, penv);
296 cmpop = getcmpop( penv );
297 if(cmpop == YYERRCODE )
298 return cmpop;
299 pyylval->cmpop = cmpop;
300 return CMPOP;
301
302 case '?':
303 pyylval->ipar = (++(penv->dummy_npar));
304 return PARAM;
305
306 case '{':
307 penv->extlevel ++;
308 break;
309
310 case '}':
311 penv->extlevel --;
312 break;
313
314 default:
315 break;
316 }
317
318 return c;
319 }
320
nnsql_yyinit(yyenv_t * penv,yystmt_t * yystmt)321 void nnsql_yyinit(yyenv_t* penv, yystmt_t* yystmt)
322 {
323 penv->extlevel = 0;
324 penv->dummy_npar = penv->errpos = penv->scanpos = 0;
325 penv->pstmt = yystmt;
326 penv->texts_bufptr = yystmt->texts_buf;
327 }
328