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