Rev 8303 | Rev 11104 | 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 | */ |
||
8880 | bpr | 17 | |
8185 | bpr | 18 | #include "wims.h" |
10 | reyssat | 19 | |
20 | char *relation_type[]={ |
||
21 | "sametext","samecase", |
||
22 | "in", "wordof","itemof","lineof","varof","variableof" |
||
23 | }; |
||
24 | #define total_relations (sizeof(relation_type)/sizeof(relation_type[0])) |
||
25 | |||
7673 | bpr | 26 | /* Compares two string. Returns 1 if yes, 0 if no, -1 if error. |
27 | * In fact, -1 will occur only if module_error() is modified to |
||
8155 | bpr | 28 | * return instead of abort. |
29 | */ |
||
7673 | bpr | 30 | /* TODO: quoted string. */ |
10 | reyssat | 31 | int compare(char *p, int numeric, int lvl) |
32 | { |
||
33 | char *p1, *p2, *pp, *pt; |
||
34 | char *r1, *r2; |
||
35 | int i, l, k, r, neg, gotl; |
||
7673 | bpr | 36 | |
37 | /* Check global pairs of parentheses */ |
||
10 | reyssat | 38 | p2=strip_trailing_spaces(p); |
39 | p1=find_word_start(p); |
||
40 | if(lvl==0 && p2-p1>=MAX_LINELEN-1) module_error("parm_too_long"); |
||
41 | while(*p1=='(' && *p2==')' && p2==parend(p1)) { |
||
7673 | bpr | 42 | lvl=0; p1=find_word_start(++p1); |
43 | do p2--; while(p2>=p1 && myisspace(*p2)); |
||
44 | p2[1]=0; |
||
10 | reyssat | 45 | } |
46 | gotl=100; r1=r2=p1; r=-1; neg=0; |
||
47 | for(pp=p1; *pp; pp++) { |
||
7673 | bpr | 48 | if(*pp==')') {badpar: module_error("unmatched_parentheses"); return -1;} |
49 | if(*pp=='(') { |
||
50 | pp=parend(pp); if(pp==NULL) goto badpar; |
||
51 | continue; |
||
52 | } |
||
53 | if(gotl>3) { |
||
54 | switch(*pp) { |
||
55 | case '<': { |
||
56 | gotl=3; r1=pp; r2=r1+1; r=102; neg=0; |
||
57 | if(*r2=='=') {r2++; r=103; neg=1;} |
||
58 | if(*r2=='>') { |
||
59 | r2++; neg=1; |
||
60 | if(numeric) r=101; else r=0; |
||
61 | } |
||
62 | break; |
||
63 | } |
||
64 | case '>': { |
||
65 | gotl=3; r1=pp; r2=r1+1; r=103; neg=0; |
||
66 | if(*r2=='=') {r2++; r=102; neg=1;} |
||
67 | break; |
||
68 | } |
||
69 | case '=': { |
||
70 | gotl=3; neg=0; r1=pp; r2=r1+1; if(*r2=='=') r2++; |
||
71 | if(numeric) r=101; else r=0; |
||
72 | break; |
||
73 | } |
||
74 | case '!': { |
||
75 | if(pp[1]=='=') { |
||
76 | gotl=3; r1=pp; r2=pp+2; neg=1; |
||
77 | if(numeric) r=101; else r=0; |
||
78 | } |
||
79 | break; |
||
80 | } |
||
81 | } |
||
82 | if(r2>p1) { |
||
83 | if(lvl==2) break; |
||
84 | pp=r2-1; continue; |
||
85 | } |
||
86 | } |
||
87 | if(!myisspace(*pp)) continue; |
||
88 | pp=find_word_start(pp); |
||
89 | if(gotl>3) { |
||
90 | if(pp[0]=='i' && pp[1]=='s') {k=2; neg=0; goto isnot;} |
||
91 | if(pp[0]=='n' && pp[1]=='o' && pp[2]=='t') {k=3; neg=1; goto isnot;} |
||
92 | goto rel; |
||
93 | isnot: |
||
94 | if(strchr("siwlv",pp[k])==NULL) goto rel; |
||
95 | pt=pp; pp+=k; l=0; |
||
96 | for(i=0;i<total_relations;i++) { |
||
97 | l=strlen(relation_type[i]); |
||
98 | if(strncmp(pp, relation_type[i], l)==0 && |
||
99 | ((!myisalnum(pp[l]) && pp[l]!='_') || pp[l]==0)) break; |
||
100 | } |
||
101 | if(i>=total_relations) {pp--; continue;} |
||
102 | gotl=3; r=i+1; pp+=l; r1=pt; r2=pp; |
||
103 | if(lvl==2) break; else {pp--; continue;} |
||
104 | } |
||
105 | rel: |
||
106 | if(*pp!='|' && *pp!='&' && *pp!='a' && *pp!='o') |
||
107 | {pp--; continue;} |
||
108 | if(gotl>2 && |
||
109 | ((myisspace(pp[3]) && strncmp(pp,"and",3)==0) || |
||
110 | (myisspace(pp[2]) && strncmp(pp,"&&",2)==0))) { |
||
111 | gotl=2; r1=pp; pp=r2=find_word_end(r1); |
||
112 | if(lvl==1) break; else {pp--;continue;} |
||
113 | } |
||
114 | if(gotl>1 && myisspace(pp[2]) && |
||
115 | (strncmp(pp,"or",2)==0 || strncmp(pp,"||",2)==0)) { |
||
116 | gotl=1; r1=pp; r2=pp=r1+2; break; |
||
117 | } |
||
10 | reyssat | 118 | } |
119 | if(gotl>20) { |
||
7673 | bpr | 120 | setvar(error_data_string,"relation not defined"); |
121 | module_error("comp_syntax"); return -1; |
||
10 | reyssat | 122 | } |
7673 | bpr | 123 | |
10 | reyssat | 124 | switch(gotl) { |
7673 | bpr | 125 | case 1: { /* or */ |
126 | *r1=0; i=compare(p1,numeric,1); if(i) return i; |
||
127 | else return compare(r2,numeric,0); |
||
128 | } |
||
129 | case 2: { /* and */ |
||
130 | *r1=0; i=compare(p1,numeric,2); if(i<=0) return i; |
||
131 | else return compare(r2,numeric,1); |
||
132 | } |
||
133 | case 3: { /* atomic comparison */ |
||
134 | if(r<100) { /* textual comparison */ |
||
8283 | bpr | 135 | static char buf1[MAX_LINELEN+1], buf2[MAX_LINELEN+1]; |
7673 | bpr | 136 | while(r1>p1 && myisspace(r1[-1])) r1--; |
137 | memmove(buf1,p1,r1-p1); buf1[r1-p1]=0; |
||
138 | r2=find_word_start(r2); |
||
139 | while(p2>=r2 && myisspace(*p2)) p2--; |
||
140 | memmove(buf2,r2,p2+1-r2); buf2[p2+1-r2]=0; |
||
141 | substitute(buf1); substitute(buf2); |
||
142 | switch(r) { |
||
143 | case 0: { /* equal */ |
||
144 | if(strcmp(buf1,buf2)==0) return 1^neg; else return neg; |
||
145 | } |
||
146 | case 1: { /* sametext */ |
||
147 | deaccent(buf1); deaccent(buf2); |
||
148 | if(strcasecmp(bufprep(buf1),bufprep(buf2))==0) |
||
149 | return 1^neg; |
||
150 | else return neg; |
||
151 | } |
||
152 | case 2: { /* samecase */ |
||
153 | if(strcmp(bufprep(buf1),bufprep(buf2))==0) |
||
154 | return 1^neg; |
||
155 | else return neg; |
||
156 | } |
||
157 | case 3: { /* in */ |
||
158 | if(strstr(buf2,buf1)!=NULL) return 1^neg; else return neg; |
||
159 | } |
||
160 | case 4: { /* wordof */ |
||
161 | if(wordchr(buf2,buf1)!=NULL) return 1^neg; else return neg; |
||
162 | } |
||
163 | case 5: { /* itemof */ |
||
164 | if(itemchr(buf2,buf1)!=NULL) return 1^neg; else return neg; |
||
165 | } |
||
166 | case 6: { /* lineof */ |
||
167 | if(linechr(buf2,buf1)!=NULL) return 1^neg; else return neg; |
||
168 | } |
||
169 | case 7: |
||
170 | case 8: { /* varof */ |
||
171 | if(varchr(buf2,buf1)!=NULL) return 1^neg; else return neg; |
||
172 | } |
||
173 | } |
||
174 | } |
||
175 | else { /* numerical comparison */ |
||
176 | double d1, d2, sum, diff, prec; |
||
177 | *r1=0; |
||
178 | d1=evalue(p1); d2=evalue(r2); |
||
179 | sum=d1+d2; if(sum<0) sum=-sum; |
||
180 | diff=d1-d2; if(diff<0) diff=-diff; |
||
181 | prec=evalue(getvar("wims_compare_precision")); /* Move string name to header! */ |
||
182 | diff=diff*prec; |
||
183 | if(prec>0 && prec<1E10) sum=sum+1/prec; |
||
184 | switch(r) { |
||
185 | case 101: { /* = */ |
||
186 | if(sum>=diff) return 1^neg; else return neg; |
||
187 | } |
||
188 | case 102: { /* < */ |
||
189 | if(d1<d2) return 1^neg; else return neg; |
||
190 | } |
||
191 | case 103: { /* > */ |
||
192 | if(d1>d2) return 1^neg; else return neg; |
||
193 | } |
||
194 | default: break; /* should never occur */ |
||
195 | } |
||
196 | } |
||
197 | } |
||
10 | reyssat | 198 | } |
8303 | bpr | 199 | internal_error("compare(): this should never happen."); |
10 | reyssat | 200 | return -1; |
201 | } |
||
202 |