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