Introduce __attribute__((unused)) (#defined to UNUSED_ATTR) to mark possibly unused...
[kugel-rb.git] / apps / plugins / searchengine / parser.c
blob1a5f156649822ab3a5cfe2202df472e2879aa14b
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005 by Michiel van der Kolk
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include "searchengine.h"
22 #include "token.h"
23 #include "dbinterface.h"
24 #include "parser.h"
26 struct token *currentToken, curtoken;
27 unsigned char *filter[20],*nofilter=0;
28 int currentlevel=0;
29 int syntaxerror;
30 int parse_fd;
31 char errormsg[250];
33 unsigned char *parse(int fd) {
34 unsigned char *ret=0;
35 int i;
36 syntaxerror=0;
37 parse_fd=fd;
38 currentlevel=0;
39 if(nofilter==0) {
40 nofilter=my_malloc(sizeof(unsigned char)*rb->tagdbheader->filecount);
41 rb->memset(nofilter,1,rb->tagdbheader->filecount);
43 for(i=0;i<20;i++)
44 filter[i]=nofilter;
45 database_init();
46 parser_acceptIt();
47 currentToken=&curtoken;
48 PUTS("parse");
49 ret=parseMExpr();
50 if(syntaxerror) {
51 PUTS("Syntaxerror");
52 rb->splash(HZ*3,errormsg);
54 parser_accept(TOKEN_EOF);
55 return ret;
58 void parser_acceptIt(void) {
59 if(syntaxerror) return;
60 rb->read(parse_fd,&curtoken,sizeof(struct token));
63 int parser_accept(unsigned char kind) {
64 if(currentToken->kind!=kind) {
65 syntaxerror=1;
66 rb->snprintf(errormsg,250,"'%d' found where '%d' expected\n",currentToken->kind,kind);
67 return 0;
69 else {
70 parser_acceptIt();
71 return 1;
75 unsigned char *parseCompareNum() {
76 struct token number1,number2;
77 unsigned char *ret;
78 int i,n1=-1,n2=-1;
79 int op;
80 if(syntaxerror) return 0;
81 PUTS("parseCompareNum");
82 if(currentToken->kind==TOKEN_NUM ||
83 currentToken->kind==TOKEN_NUMIDENTIFIER) {
84 rb->memcpy(&number1,currentToken,sizeof(struct token));
85 parser_acceptIt();
87 else {
88 syntaxerror=1;
89 rb->snprintf(errormsg,250,"'%d' found where NUM/NUMID expected\n",currentToken->kind);
90 return 0;
92 if(currentToken->kind>=TOKEN_GT && currentToken->kind <= TOKEN_NE) {
93 op=currentToken->kind;
94 parser_acceptIt();
96 else {
97 syntaxerror=1;
98 rb->snprintf(errormsg,250,"'%d' found where NUMOP expected\n",currentToken->kind);
99 return 0;
101 if(currentToken->kind==TOKEN_NUM ||
102 currentToken->kind==TOKEN_NUMIDENTIFIER) {
103 rb->memcpy(&number2,currentToken,sizeof(struct token));
104 parser_acceptIt();
106 else {
107 syntaxerror=1;
108 rb->snprintf(errormsg,250,"'%d' found where NUM/NUMID expected\n",currentToken->kind);
109 return 0;
111 ret=my_malloc(sizeof(unsigned char)*rb->tagdbheader->filecount);
112 if(number1.kind==TOKEN_NUM)
113 n1=getvalue(&number1);
114 if(number2.kind==TOKEN_NUM)
115 n2=getvalue(&number2);
116 for(i=0;i<rb->tagdbheader->filecount;i++)
117 if(filter[currentlevel][i]) {
118 loadentry(i);
119 if(number1.kind==TOKEN_NUMIDENTIFIER)
120 n1=getvalue(&number1);
121 if(number2.kind==TOKEN_NUMIDENTIFIER)
122 n2=getvalue(&number2);
123 switch(op) {
124 case TOKEN_GT:
125 ret[i]=n1 > n2;
126 break;
127 case TOKEN_GTE:
128 ret[i]=n1 >= n2;
129 break;
130 case TOKEN_LT:
131 ret[i]=n1 < n2;
132 break;
133 case TOKEN_LTE:
134 ret[i]=n1 <= n2;
135 break;
136 case TOKEN_EQ:
137 ret[i]=n1 == n2;
138 break;
139 case TOKEN_NE:
140 ret[i]=n1 != n2;
141 break;
144 return ret;
147 unsigned char *parseCompareString() {
148 struct token string1,string2;
149 unsigned char *ret;
150 char *s1=NULL,*s2=NULL;
151 int i,i2;
152 int op;
153 if(syntaxerror) return 0;
154 PUTS("parseCompareString");
155 if(currentToken->kind==TOKEN_STRING ||
156 currentToken->kind==TOKEN_STRINGIDENTIFIER) {
157 rb->memcpy(&string1,currentToken,sizeof(struct token));
158 parser_acceptIt();
160 else {
161 syntaxerror=1;
162 rb->snprintf(errormsg,250,"'%d' found where STRING/STRINGID expected\n",currentToken->kind);
163 return 0;
165 op=currentToken->kind;
166 if(op>=TOKEN_CONTAINS&&op<=TOKEN_ENDSWITH) {
167 parser_acceptIt();
168 } else {
169 syntaxerror=1;
170 rb->snprintf(errormsg,250,"'%d' found where STROP expected\n",op);
171 return 0;
173 if(currentToken->kind==TOKEN_STRING ||
174 currentToken->kind==TOKEN_STRINGIDENTIFIER) {
175 rb->memcpy(&string2,currentToken,sizeof(struct token));
176 parser_acceptIt();
178 else {
179 syntaxerror=1;
180 rb->snprintf(errormsg,250,"'%d' found where STRING/STRINGID expected\n",currentToken->kind);
181 return 0;
183 ret=my_malloc(sizeof(unsigned char)*rb->tagdbheader->filecount);
184 if(string1.kind==TOKEN_STRING)
185 s1=getstring(&string1);
186 if(string2.kind==TOKEN_STRING)
187 s2=getstring(&string2);
188 for(i=0;i<rb->tagdbheader->filecount;i++)
189 if(filter[currentlevel][i]) {
190 loadentry(i);
191 if(string1.kind==TOKEN_STRINGIDENTIFIER)
192 s1=getstring(&string1);
193 if(string2.kind==TOKEN_STRINGIDENTIFIER)
194 s2=getstring(&string2);
195 switch(op) {
196 case TOKEN_CONTAINS:
197 ret[i]=rb->strcasestr(s1,s2)!=0;
198 break;
199 case TOKEN_EQUALS:
200 ret[i]=rb->strcasecmp(s1,s2)==0;
201 break;
202 case TOKEN_STARTSWITH:
203 ret[i]=rb->strncasecmp(s1,s2,rb->strlen(s2))==0;
204 break;
205 case TOKEN_ENDSWITH:
206 i2=rb->strlen(s2);
207 ret[i]=rb->strncasecmp(s1+rb->strlen(s1)-i2,s2,i2)==0;
208 break;
211 return ret;
214 unsigned char *parseExpr() {
215 unsigned char *ret;
216 int i;
217 if(syntaxerror) return 0;
218 PUTS("parseExpr");
219 switch(currentToken->kind) {
220 case TOKEN_NOT:
221 parser_accept(TOKEN_NOT);
222 PUTS("parseNot");
223 ret = parseExpr();
224 if(ret==NULL) return 0;
225 for(i=0;i<rb->tagdbheader->filecount;i++)
226 if(filter[currentlevel][i])
227 ret[i]=!ret[i];
228 break;
229 case TOKEN_LPAREN:
230 parser_accept(TOKEN_LPAREN);
231 currentlevel++;
232 ret = parseMExpr();
233 currentlevel--;
234 if(ret==NULL) return 0;
235 parser_accept(TOKEN_RPAREN);
236 break;
237 case TOKEN_NUM:
238 case TOKEN_NUMIDENTIFIER:
239 ret = parseCompareNum();
240 if(ret==NULL) return 0;
241 break;
242 case TOKEN_STRING:
243 case TOKEN_STRINGIDENTIFIER:
244 ret = parseCompareString();
245 if(ret==NULL) return 0;
246 break;
247 default:
248 // error, unexpected symbol
249 syntaxerror=1;
250 rb->snprintf(errormsg,250,"unexpected '%d' found at parseExpr\n",currentToken->kind);
251 ret=0;
252 break;
254 return ret;
257 unsigned char *parseMExpr() {
258 unsigned char *ret,*ret2;
259 int i;
260 if(syntaxerror) return 0;
261 PUTS("parseMExpr");
262 ret=parseLExpr();
263 while(currentToken->kind==TOKEN_OR) {
264 parser_accept(TOKEN_OR);
265 PUTS("parseOr");
266 ret2 = parseLExpr();
267 if(ret2==NULL) return 0;
268 for(i=0;i<rb->tagdbheader->filecount;i++)
269 if(filter[currentlevel][i]) // this should always be true
270 ret[i]=ret[i] || ret2[i];
271 else
272 rb->splash(HZ*2,"An or is having a filter, bad.");
274 return ret;
277 unsigned char *parseLExpr() {
278 unsigned char *ret,*ret2;
279 int i;
280 if(syntaxerror) return 0;
281 PUTS("parseLExpr");
282 filter[currentlevel]=nofilter;
283 ret=parseExpr();
284 filter[currentlevel]=ret;
285 while(currentToken->kind==TOKEN_AND) {
286 parser_accept(TOKEN_AND);
287 PUTS("parseAnd");
288 ret2 = parseExpr();
289 if(ret2==NULL) return 0;
290 for(i=0;i<rb->tagdbheader->filecount;i++)
291 ret[i]=ret[i] && ret2[i];
293 filter[currentlevel]=nofilter;
294 return ret;