blob: 1a5f156649822ab3a5cfe2202df472e2879aa14b [file] [log] [blame]
Michiel Van Der Kolk4350eec2005-04-28 14:06:20 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 by Michiel van der Kolk
11 *
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000012 * 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.
Michiel Van Der Kolk4350eec2005-04-28 14:06:20 +000016 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
Michiel Van Der Kolk9369d482005-04-28 12:33:38 +000021#include "searchengine.h"
22#include "token.h"
23#include "dbinterface.h"
24#include "parser.h"
25
Michiel Van Der Kolk29909a32005-04-28 14:48:12 +000026struct token *currentToken, curtoken;
Michiel Van Der Kolk388d9ff2005-04-28 21:28:42 +000027unsigned char *filter[20],*nofilter=0;
28int currentlevel=0;
Michiel Van Der Kolk9369d482005-04-28 12:33:38 +000029int syntaxerror;
Michiel Van Der Kolk29909a32005-04-28 14:48:12 +000030int parse_fd;
Michiel Van Der Kolk9369d482005-04-28 12:33:38 +000031char errormsg[250];
32
Michiel Van Der Kolk29909a32005-04-28 14:48:12 +000033unsigned char *parse(int fd) {
Michiel Van Der Kolkec407a82005-04-29 21:02:17 +000034 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);
42 }
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");
Jens Arnold4d6374c2007-03-16 21:56:08 +000052 rb->splash(HZ*3,errormsg);
Michiel Van Der Kolkec407a82005-04-29 21:02:17 +000053 }
54 parser_accept(TOKEN_EOF);
55 return ret;
Michiel Van Der Kolk9369d482005-04-28 12:33:38 +000056}
57
58void parser_acceptIt(void) {
Michiel Van Der Kolkec407a82005-04-29 21:02:17 +000059 if(syntaxerror) return;
60 rb->read(parse_fd,&curtoken,sizeof(struct token));
Michiel Van Der Kolk9369d482005-04-28 12:33:38 +000061}
62
63int parser_accept(unsigned char kind) {
Michiel Van Der Kolkec407a82005-04-29 21:02:17 +000064 if(currentToken->kind!=kind) {
65 syntaxerror=1;
66 rb->snprintf(errormsg,250,"'%d' found where '%d' expected\n",currentToken->kind,kind);
67 return 0;
68 }
69 else {
70 parser_acceptIt();
71 return 1;
72 }
Michiel Van Der Kolk9369d482005-04-28 12:33:38 +000073}
74
75unsigned char *parseCompareNum() {
Michiel Van Der Kolkec407a82005-04-29 21:02:17 +000076 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();
86 }
87 else {
88 syntaxerror=1;
89 rb->snprintf(errormsg,250,"'%d' found where NUM/NUMID expected\n",currentToken->kind);
90 return 0;
91 }
92 if(currentToken->kind>=TOKEN_GT && currentToken->kind <= TOKEN_NE) {
93 op=currentToken->kind;
94 parser_acceptIt();
95 }
96 else {
97 syntaxerror=1;
98 rb->snprintf(errormsg,250,"'%d' found where NUMOP expected\n",currentToken->kind);
99 return 0;
100 }
101 if(currentToken->kind==TOKEN_NUM ||
102 currentToken->kind==TOKEN_NUMIDENTIFIER) {
103 rb->memcpy(&number2,currentToken,sizeof(struct token));
104 parser_acceptIt();
105 }
106 else {
107 syntaxerror=1;
108 rb->snprintf(errormsg,250,"'%d' found where NUM/NUMID expected\n",currentToken->kind);
109 return 0;
110 }
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;
142 }
Michiel Van Der Kolk9369d482005-04-28 12:33:38 +0000143 }
Michiel Van Der Kolkec407a82005-04-29 21:02:17 +0000144 return ret;
Michiel Van Der Kolk9369d482005-04-28 12:33:38 +0000145}
146
147unsigned char *parseCompareString() {
Michiel Van Der Kolkec407a82005-04-29 21:02:17 +0000148 struct token string1,string2;
149 unsigned char *ret;
150 char *s1=NULL,*s2=NULL;
Michiel Van Der Kolkf5eae082005-05-10 23:44:22 +0000151 int i,i2;
152 int op;
Michiel Van Der Kolkec407a82005-04-29 21:02:17 +0000153 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();
159 }
160 else {
161 syntaxerror=1;
162 rb->snprintf(errormsg,250,"'%d' found where STRING/STRINGID expected\n",currentToken->kind);
163 return 0;
164 }
Michiel Van Der Kolkf5eae082005-05-10 23:44:22 +0000165 op=currentToken->kind;
166 if(op>=TOKEN_CONTAINS&&op<=TOKEN_ENDSWITH) {
Michiel Van Der Kolkec407a82005-04-29 21:02:17 +0000167 parser_acceptIt();
168 } else {
169 syntaxerror=1;
Michiel Van Der Kolkf5eae082005-05-10 23:44:22 +0000170 rb->snprintf(errormsg,250,"'%d' found where STROP expected\n",op);
Michiel Van Der Kolkec407a82005-04-29 21:02:17 +0000171 return 0;
172 }
173 if(currentToken->kind==TOKEN_STRING ||
174 currentToken->kind==TOKEN_STRINGIDENTIFIER) {
175 rb->memcpy(&string2,currentToken,sizeof(struct token));
176 parser_acceptIt();
177 }
178 else {
179 syntaxerror=1;
180 rb->snprintf(errormsg,250,"'%d' found where STRING/STRINGID expected\n",currentToken->kind);
181 return 0;
182 }
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);
Michiel Van Der Kolkf5eae082005-05-10 23:44:22 +0000195 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;
209 }
Michiel Van Der Kolk9369d482005-04-28 12:33:38 +0000210 }
Michiel Van Der Kolkec407a82005-04-29 21:02:17 +0000211 return ret;
Michiel Van Der Kolk9369d482005-04-28 12:33:38 +0000212}
213
214unsigned char *parseExpr() {
Michiel Van Der Kolkec407a82005-04-29 21:02:17 +0000215 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;
253 }
254 return ret;
Michiel Van Der Kolk9369d482005-04-28 12:33:38 +0000255}
256
257unsigned char *parseMExpr() {
Michiel Van Der Kolkec407a82005-04-29 21:02:17 +0000258 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
Jens Arnold4d6374c2007-03-16 21:56:08 +0000272 rb->splash(HZ*2,"An or is having a filter, bad.");
Michiel Van Der Kolkec407a82005-04-29 21:02:17 +0000273 }
274 return ret;
Michiel Van Der Kolk9369d482005-04-28 12:33:38 +0000275}
Michiel Van Der Kolk388d9ff2005-04-28 21:28:42 +0000276
277unsigned char *parseLExpr() {
Michiel Van Der Kolkec407a82005-04-29 21:02:17 +0000278 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];
292 }
293 filter[currentlevel]=nofilter;
294 return ret;
Michiel Van Der Kolk388d9ff2005-04-28 21:28:42 +0000295}