Rev 8302 | Rev 8880 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
10 | reyssat | 1 | /* Copyright (C) 1998-2003 XIAO, Gang of Universite de Nice - Sophia Antipolis |
2 | * |
||
3 | * This program is free software; you can redistribute it and/or modify |
||
4 | * it under the terms of the GNU General Public License as published by |
||
5 | * the Free Software Foundation; either version 2 of the License, or |
||
6 | * (at your option) any later version. |
||
7 | * |
||
8 | * This program is distributed in the hope that it will be useful, |
||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
11 | * GNU General Public License for more details. |
||
12 | * |
||
13 | * You should have received a copy of the GNU General Public License |
||
14 | * along with this program; if not, write to the Free Software |
||
15 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
||
16 | */ |
||
8185 | bpr | 17 | #include "wims.h" |
10 | reyssat | 18 | |
19 | char *bufprep(char *p) |
||
20 | { |
||
21 | /* singlespace(p); strip_trailing_spaces(p); return find_word_start(p); */ |
||
22 | nospace(p); return p; |
||
23 | } |
||
24 | |||
25 | char *parend(char *p) |
||
26 | { |
||
27 | char *pp; int t; |
||
28 | t=0; for(pp=p;*pp;pp++) { |
||
7673 | bpr | 29 | if(*pp=='(') t++; |
30 | if(*pp==')') {t--; if(t==0) return pp; if(t<0) return NULL;} |
||
10 | reyssat | 31 | } |
32 | return NULL; |
||
33 | } |
||
34 | |||
35 | char *relation_type[]={ |
||
36 | "sametext","samecase", |
||
37 | "in", "wordof","itemof","lineof","varof","variableof" |
||
38 | }; |
||
39 | #define total_relations (sizeof(relation_type)/sizeof(relation_type[0])) |
||
40 | |||
7673 | bpr | 41 | /* Compares two string. Returns 1 if yes, 0 if no, -1 if error. |
42 | * In fact, -1 will occur only if module_error() is modified to |
||
8155 | bpr | 43 | * return instead of abort. |
44 | */ |
||
7673 | bpr | 45 | /* TODO: quoted string. */ |
10 | reyssat | 46 | int compare(char *p, int numeric, int lvl) |
47 | { |
||
48 | char *p1, *p2, *pp, *pt; |
||
49 | char *r1, *r2; |
||
50 | int i, l, k, r, neg, gotl; |
||
7673 | bpr | 51 | |
52 | /* Check global pairs of parentheses */ |
||
10 | reyssat | 53 | p2=strip_trailing_spaces(p); |
54 | p1=find_word_start(p); |
||
55 | if(lvl==0 && p2-p1>=MAX_LINELEN-1) module_error("parm_too_long"); |
||
56 | while(*p1=='(' && *p2==')' && p2==parend(p1)) { |
||
7673 | bpr | 57 | lvl=0; p1=find_word_start(++p1); |
58 | do p2--; while(p2>=p1 && myisspace(*p2)); |
||
59 | p2[1]=0; |
||
10 | reyssat | 60 | } |
61 | gotl=100; r1=r2=p1; r=-1; neg=0; |
||
62 | for(pp=p1; *pp; pp++) { |
||
7673 | bpr | 63 | if(*pp==')') {badpar: module_error("unmatched_parentheses"); return -1;} |
64 | if(*pp=='(') { |
||
65 | pp=parend(pp); if(pp==NULL) goto badpar; |
||
66 | continue; |
||
67 | } |
||
68 | if(gotl>3) { |
||
69 | switch(*pp) { |
||
70 | case '<': { |
||
71 | gotl=3; r1=pp; r2=r1+1; r=102; neg=0; |
||
72 | if(*r2=='=') {r2++; r=103; neg=1;} |
||
73 | if(*r2=='>') { |
||
74 | r2++; neg=1; |
||
75 | if(numeric) r=101; else r=0; |
||
76 | } |
||
77 | break; |
||
78 | } |
||
79 | case '>': { |
||
80 | gotl=3; r1=pp; r2=r1+1; r=103; neg=0; |
||
81 | if(*r2=='=') {r2++; r=102; neg=1;} |
||
82 | break; |
||
83 | } |
||
84 | case '=': { |
||
85 | gotl=3; neg=0; r1=pp; r2=r1+1; if(*r2=='=') r2++; |
||
86 | if(numeric) r=101; else r=0; |
||
87 | break; |
||
88 | } |
||
89 | case '!': { |
||
90 | if(pp[1]=='=') { |
||
91 | gotl=3; r1=pp; r2=pp+2; neg=1; |
||
92 | if(numeric) r=101; else r=0; |
||
93 | } |
||
94 | break; |
||
95 | } |
||
96 | } |
||
97 | if(r2>p1) { |
||
98 | if(lvl==2) break; |
||
99 | pp=r2-1; continue; |
||
100 | } |
||
101 | } |
||
102 | if(!myisspace(*pp)) continue; |
||
103 | pp=find_word_start(pp); |
||
104 | if(gotl>3) { |
||
105 | if(pp[0]=='i' && pp[1]=='s') {k=2; neg=0; goto isnot;} |
||
106 | if(pp[0]=='n' && pp[1]=='o' && pp[2]=='t') {k=3; neg=1; goto isnot;} |
||
107 | goto rel; |
||
108 | isnot: |
||
109 | if(strchr("siwlv",pp[k])==NULL) goto rel; |
||
110 | pt=pp; pp+=k; l=0; |
||
111 | for(i=0;i<total_relations;i++) { |
||
112 | l=strlen(relation_type[i]); |
||
113 | if(strncmp(pp, relation_type[i], l)==0 && |
||
114 | ((!myisalnum(pp[l]) && pp[l]!='_') || pp[l]==0)) break; |
||
115 | } |
||
116 | if(i>=total_relations) {pp--; continue;} |
||
117 | gotl=3; r=i+1; pp+=l; r1=pt; r2=pp; |
||
118 | if(lvl==2) break; else {pp--; continue;} |
||
119 | } |
||
120 | rel: |
||
121 | if(*pp!='|' && *pp!='&' && *pp!='a' && *pp!='o') |
||
122 | {pp--; continue;} |
||
123 | if(gotl>2 && |
||
124 | ((myisspace(pp[3]) && strncmp(pp,"and",3)==0) || |
||
125 | (myisspace(pp[2]) && strncmp(pp,"&&",2)==0))) { |
||
126 | gotl=2; r1=pp; pp=r2=find_word_end(r1); |
||
127 | if(lvl==1) break; else {pp--;continue;} |
||
128 | } |
||
129 | if(gotl>1 && myisspace(pp[2]) && |
||
130 | (strncmp(pp,"or",2)==0 || strncmp(pp,"||",2)==0)) { |
||
131 | gotl=1; r1=pp; r2=pp=r1+2; break; |
||
132 | } |
||
10 | reyssat | 133 | } |
134 | if(gotl>20) { |
||
7673 | bpr | 135 | setvar(error_data_string,"relation not defined"); |
136 | module_error("comp_syntax"); return -1; |
||
10 | reyssat | 137 | } |
7673 | bpr | 138 | |
10 | reyssat | 139 | switch(gotl) { |
7673 | bpr | 140 | case 1: { /* or */ |
141 | *r1=0; i=compare(p1,numeric,1); if(i) return i; |
||
142 | else return compare(r2,numeric,0); |
||
143 | } |
||
144 | case 2: { /* and */ |
||
145 | *r1=0; i=compare(p1,numeric,2); if(i<=0) return i; |
||
146 | else return compare(r2,numeric,1); |
||
147 | } |
||
148 | case 3: { /* atomic comparison */ |
||
149 | if(r<100) { /* textual comparison */ |
||
8283 | bpr | 150 | static char buf1[MAX_LINELEN+1], buf2[MAX_LINELEN+1]; |
7673 | bpr | 151 | while(r1>p1 && myisspace(r1[-1])) r1--; |
152 | memmove(buf1,p1,r1-p1); buf1[r1-p1]=0; |
||
153 | r2=find_word_start(r2); |
||
154 | while(p2>=r2 && myisspace(*p2)) p2--; |
||
155 | memmove(buf2,r2,p2+1-r2); buf2[p2+1-r2]=0; |
||
156 | substitute(buf1); substitute(buf2); |
||
157 | switch(r) { |
||
158 | case 0: { /* equal */ |
||
159 | if(strcmp(buf1,buf2)==0) return 1^neg; else return neg; |
||
160 | } |
||
161 | case 1: { /* sametext */ |
||
162 | deaccent(buf1); deaccent(buf2); |
||
163 | if(strcasecmp(bufprep(buf1),bufprep(buf2))==0) |
||
164 | return 1^neg; |
||
165 | else return neg; |
||
166 | } |
||
167 | case 2: { /* samecase */ |
||
168 | if(strcmp(bufprep(buf1),bufprep(buf2))==0) |
||
169 | return 1^neg; |
||
170 | else return neg; |
||
171 | } |
||
172 | case 3: { /* in */ |
||
173 | if(strstr(buf2,buf1)!=NULL) return 1^neg; else return neg; |
||
174 | } |
||
175 | case 4: { /* wordof */ |
||
176 | if(wordchr(buf2,buf1)!=NULL) return 1^neg; else return neg; |
||
177 | } |
||
178 | case 5: { /* itemof */ |
||
179 | if(itemchr(buf2,buf1)!=NULL) return 1^neg; else return neg; |
||
180 | } |
||
181 | case 6: { /* lineof */ |
||
182 | if(linechr(buf2,buf1)!=NULL) return 1^neg; else return neg; |
||
183 | } |
||
184 | case 7: |
||
185 | case 8: { /* varof */ |
||
186 | if(varchr(buf2,buf1)!=NULL) return 1^neg; else return neg; |
||
187 | } |
||
188 | } |
||
189 | } |
||
190 | else { /* numerical comparison */ |
||
191 | double d1, d2, sum, diff, prec; |
||
192 | *r1=0; |
||
193 | d1=evalue(p1); d2=evalue(r2); |
||
194 | sum=d1+d2; if(sum<0) sum=-sum; |
||
195 | diff=d1-d2; if(diff<0) diff=-diff; |
||
196 | prec=evalue(getvar("wims_compare_precision")); /* Move string name to header! */ |
||
197 | diff=diff*prec; |
||
198 | if(prec>0 && prec<1E10) sum=sum+1/prec; |
||
199 | switch(r) { |
||
200 | case 101: { /* = */ |
||
201 | if(sum>=diff) return 1^neg; else return neg; |
||
202 | } |
||
203 | case 102: { /* < */ |
||
204 | if(d1<d2) return 1^neg; else return neg; |
||
205 | } |
||
206 | case 103: { /* > */ |
||
207 | if(d1>d2) return 1^neg; else return neg; |
||
208 | } |
||
209 | default: break; /* should never occur */ |
||
210 | } |
||
211 | } |
||
212 | } |
||
10 | reyssat | 213 | } |
8303 | bpr | 214 | internal_error("compare(): this should never happen."); |
10 | reyssat | 215 | return -1; |
216 | } |
||
217 |