Rev 8161 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
10 | reyssat | 1 | /* Copyright (C) 2002-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 | */ |
||
17 | |||
8161 | bpr | 18 | #include "symtext.h" |
19 | /* Block parsing routines |
||
20 | * Return value: |
||
21 | * 0 if no match. |
||
22 | * 1 if match. |
||
23 | * -1 if error. |
||
24 | */ |
||
10 | reyssat | 25 | |
26 | struct npool { |
||
27 | listtype nextblock,last; |
||
28 | } npool[MAX_POOLS]; |
||
29 | int nextnpool, currnpool; |
||
30 | |||
31 | void outval(char *tit, char *val) |
||
32 | { |
||
33 | char *p, l, r; |
||
34 | val=find_word_start(val); |
||
35 | strip_trailing_spaces(val); |
||
36 | if(*val==0) { |
||
8161 | bpr | 37 | snprintf(outptr,OUTSIZE-(outptr-outbuf)-1,"%s=_EMPTY_ ",tit); |
38 | goto outend; |
||
10 | reyssat | 39 | } |
40 | if(*find_word_end(val)==0) { |
||
8161 | bpr | 41 | snprintf(outptr,OUTSIZE-(outptr-outbuf)-1,"%s=%s ",tit,val); |
10 | reyssat | 42 | } |
43 | else { |
||
8161 | bpr | 44 | l='('; r=')'; |
45 | if(strchr(val,l)!=NULL || strchr(val,r)!=NULL) { |
||
46 | l='['; r=']'; |
||
47 | if(strchr(val,l)!=NULL || strchr(val,r)!=NULL) { |
||
48 | l='{'; r='}'; |
||
49 | if(strchr(val,l)!=NULL || strchr(val,r)!=NULL) { |
||
50 | l='"'; r='"'; |
||
51 | if(strchr(val,l)!=NULL || strchr(val,r)!=NULL) { |
||
52 | l=r=' '; |
||
53 | for(p=val;*p;p++) if(*p==' ') *p='_'; |
||
54 | } |
||
55 | } |
||
56 | } |
||
57 | } |
||
58 | snprintf(outptr,OUTSIZE-(outptr-outbuf)-1,"%s=%c%s%c ",tit,l,val,r); |
||
10 | reyssat | 59 | } |
60 | outend: outptr+=strlen(outptr); |
||
61 | } |
||
62 | |||
63 | void cleartag(struct poolstruct *pl) |
||
64 | { |
||
65 | int i, len, level; |
||
66 | listtype *tag; |
||
67 | len=pl->len; tag=pl->tag; level=pl->ind2; |
||
68 | if(level==0) { |
||
8161 | bpr | 69 | memset(tag,0,pl->len*sizeof(listtype)); |
10 | reyssat | 70 | } |
71 | else for(i=0; i<len; i++) { |
||
8161 | bpr | 72 | if(tag[i]>=level) tag[i]=0; |
10 | reyssat | 73 | } |
74 | } |
||
75 | |||
76 | struct poolstruct *getpool(struct block *blk) |
||
77 | { |
||
78 | struct poolstruct *pl; |
||
8161 | bpr | 79 | |
8195 | bpr | 80 | if(nextpool>=MAX_POOLS) sym_error("pool_overflow"); |
10 | reyssat | 81 | pl=poolbuf+nextpool; |
82 | pl->lastpool=blk->pool; |
||
83 | blk->pool=nextpool; nextpool++; |
||
84 | pl->block=blk-blockbuf; |
||
85 | pl->string=NULL; |
||
86 | pl->ind1=pl->ind2=pl->dirty=pl->len=0; |
||
87 | return pl; |
||
88 | } |
||
89 | |||
90 | void putpool(struct poolstruct *pl) |
||
91 | { |
||
92 | nextpool--; |
||
8195 | bpr | 93 | if(nextpool!=pl-poolbuf) sym_error("internal_error pool leaking"); |
10 | reyssat | 94 | blockbuf[pl->block].pool=pl->lastpool; |
95 | } |
||
96 | |||
97 | int mt_this(struct block *blk, char *start, int level) |
||
98 | { |
||
99 | int r; |
||
8195 | bpr | 100 | if(level > MAX_LEVELS) sym_error("level_overflow %.20s",start); |
10 | reyssat | 101 | start=find_word_start(start); |
3813 | kbelabas | 102 | if(debug>=2) fprintf(stderr,"lvl=%d. Checking against block %d for %.10s.\n",level,(int)(blk-blockbuf),start); |
10 | reyssat | 103 | r = blk->fn(blk,start,level); |
3813 | kbelabas | 104 | if(debug) fprintf(stderr,"lvl=%d. Tested %d block %d for %.10s.\n",level,r,(int)(blk-blockbuf),start); |
10 | reyssat | 105 | return r; |
106 | } |
||
107 | |||
108 | int mt_next(struct block *blk, char *start, int level) |
||
109 | { |
||
110 | int r,cp,next; |
||
111 | next=blk->nextblock; |
||
112 | cp=currnpool; |
||
113 | if(next==-2) { |
||
8161 | bpr | 114 | do { |
115 | next=npool[currnpool].nextblock; currnpool=npool[currnpool].last; |
||
116 | } |
||
117 | while (next==-2 && currnpool>0); |
||
8195 | bpr | 118 | if(next==-2) sym_error("internal_error npool disorder"); |
8161 | bpr | 119 | if(debug>=3) fprintf(stderr,"Calling macro %d: next=%d.\n", |
120 | (int)(blk-blockbuf),next); |
||
10 | reyssat | 121 | } |
122 | if(next<0) { |
||
8161 | bpr | 123 | if(*start) return 0; else return 1; |
10 | reyssat | 124 | } |
125 | r=mt_this(blockbuf+next,start,level); |
||
126 | currnpool=cp; |
||
127 | return r; |
||
128 | } |
||
129 | |||
130 | int mt_string(struct block *blk, char *start, int level) |
||
131 | { |
||
132 | char *p; |
||
133 | int r; |
||
134 | if(blk->len>0) { |
||
8161 | bpr | 135 | if(memcmp(blk->string,start,blk->len)!=0) return 0; |
136 | p=start+blk->len; if(*p && !myisspace(*p)) return 0; |
||
10 | reyssat | 137 | } |
138 | else p=start; |
||
139 | r = mt_next(blk,p,level+1); |
||
140 | if(debug) fprintf(stderr,"Strcmp %d %.20s. <-> %.20s.\n",r, blk->string,start); |
||
141 | return r; |
||
142 | } |
||
143 | |||
144 | int mt_dic(struct block *blk, char *start, int level) |
||
145 | { |
||
146 | int i,t; |
||
147 | struct entry *et; |
||
148 | char *p; |
||
8161 | bpr | 149 | |
10 | reyssat | 150 | i=blk->lind1; |
151 | t=search_dic(entry+dic[i].start,dic[i].len,sizeof(entry[0]),start); |
||
152 | if(t>=0) { |
||
8161 | bpr | 153 | et=entry+(dic[i].start+t); |
154 | if(itemchr((char*)et->replace,blk->string)==NULL) return 0; |
||
155 | p=start+et->olen; |
||
156 | return mt_next(blk,p,level+1); |
||
10 | reyssat | 157 | } |
158 | switch(dic[i].unknown_type) { |
||
8161 | bpr | 159 | case unk_leave: { |
160 | if(memcmp(start,blk->string,blk->len)==0 || |
||
161 | (start[blk->len]!=0 && !myisspace(start[blk->len]))) |
||
162 | return 0; |
||
163 | return mt_next(blk,find_word_start(start+blk->len),level+1); |
||
164 | } |
||
165 | case unk_replace: { |
||
166 | if(strcmp(dic[i].unknown,blk->string)!=0) return 0; |
||
167 | return mt_next(blk,start,level+1); |
||
168 | } |
||
169 | case unk_delete: return 0; |
||
10 | reyssat | 170 | } |
171 | return 0; |
||
172 | } |
||
173 | |||
174 | int _permpick1(struct block *blk, char *start, int level) |
||
175 | { |
||
176 | int i, j, k, r, re; |
||
177 | struct poolstruct *pl; |
||
8161 | bpr | 178 | |
10 | reyssat | 179 | level++; |
180 | for(i=blk->pool+1; i<nextpool;i++) poolbuf[i].dirty++; |
||
181 | pl=poolbuf+blk->pool; |
||
182 | i=blk->lists[pl->ind1][pl->ind2]; |
||
183 | pl->ind2++; cleartag(pl); |
||
184 | ppstart: |
||
8161 | bpr | 185 | if(i>=blk->len) { /* optional match */ |
186 | i-=blk->len; |
||
187 | r=mt_next(blk,start,level); |
||
188 | if(r) goto end; |
||
10 | reyssat | 189 | } |
190 | if(i>=0) { |
||
8161 | bpr | 191 | r=mt_this(blockbuf+blk->sublock+i,start,level); |
192 | goto end; |
||
10 | reyssat | 193 | } |
194 | r=0; |
||
195 | switch(i) { |
||
8161 | bpr | 196 | case -1: { /* any */ |
197 | any: |
||
198 | for(k=blk->lstart;k<blk->len;k++) { |
||
199 | pl->tag[k]=pl->ind2; |
||
200 | r=mt_this(blockbuf+blk->sublock+k,start,level); |
||
201 | cleartag(pl); |
||
202 | if(r) break; |
||
203 | } |
||
204 | goto end; |
||
205 | } |
||
206 | case -2: { /* any unused */ |
||
207 | unused: |
||
208 | for(k=blk->lstart;k<blk->len;k++) { |
||
209 | if(pl->tag[k]>0) continue; |
||
210 | pl->tag[k]=pl->ind2; |
||
211 | r=mt_this(blockbuf+blk->sublock+k,start,level); |
||
212 | cleartag(pl); |
||
213 | if(r) break; |
||
214 | } |
||
215 | goto end; |
||
216 | } |
||
217 | case -3: { /* any unused bigger */ |
||
218 | unused_bigger: |
||
219 | for(k=blk->len-1;k>=blk->lstart && pl->tag[k]==0;k--); |
||
220 | for(k++;k<blk->len;k++) { |
||
221 | pl->tag[k]=pl->ind2; |
||
222 | r=mt_this(blockbuf+blk->sublock+k,start,level); |
||
223 | cleartag(pl); |
||
224 | if(r) break; |
||
225 | } |
||
226 | goto end; |
||
227 | } |
||
228 | case -4: { /* any unused smaller; not used */ |
||
229 | unused_smaller: |
||
230 | for(j=0; j<blk->len && pl->tag[j]==0;j++); |
||
231 | for(k=blk->lstart;k<j;k++) { |
||
232 | pl->tag[k]=pl->ind2; |
||
233 | r=mt_this(blockbuf+blk->sublock+k,start,level); |
||
234 | cleartag(pl); |
||
235 | if(r) break; |
||
236 | } |
||
237 | goto end; |
||
238 | } |
||
239 | case -5: { /* repeat */ |
||
240 | re=pl->ind2-1; |
||
241 | if(pl->ind2<2 || pl->string >= start) goto end; |
||
242 | pl->string=start; |
||
243 | r=mt_next(blk,start,level); |
||
244 | if(r) goto end; |
||
245 | pl->ind2=re; |
||
246 | i=blk->lists[pl->ind1][pl->ind2 - 1]; |
||
247 | goto ppstart; |
||
248 | } |
||
249 | case -6: { |
||
250 | r=mt_next(blk,start,level); |
||
251 | if(r) goto end; |
||
252 | goto any; |
||
253 | } |
||
254 | case -7: { |
||
255 | r=mt_next(blk,start,level); |
||
256 | if(r) goto end; |
||
257 | goto unused; |
||
258 | } |
||
259 | case -8: { |
||
260 | r=mt_next(blk,start,level); |
||
261 | if(r) goto end; |
||
262 | goto unused_bigger; |
||
263 | } |
||
264 | case -9: { |
||
265 | r=mt_next(blk,start,level); |
||
266 | if(r) goto end; |
||
267 | goto unused_smaller; |
||
268 | } |
||
269 | case -10: { /* unused. */ |
||
270 | goto end; |
||
271 | } |
||
272 | case -11: { /* unused. */ |
||
273 | goto end; |
||
274 | } |
||
275 | case -12: { /* insertion */ |
||
276 | if(pl->tag[0]==0) { |
||
277 | pl->tag[0]=pl->ind2; |
||
278 | r=mt_this(blockbuf+blk->sublock,start,level); |
||
279 | cleartag(pl); |
||
280 | if(r) goto end; |
||
281 | } |
||
282 | r=_permpick1(blk,start,level+1); |
||
283 | goto end; |
||
284 | } |
||
285 | case -13: { /* insertion end */ |
||
286 | if(pl->tag[0]) r=mt_next(blk,start,level+1); |
||
287 | else r=0; |
||
288 | goto end; |
||
289 | } |
||
10 | reyssat | 290 | } |
291 | end: |
||
292 | if(r==0) pl->ind2--; |
||
293 | for(i=blk->pool+1; i<nextpool;i++) if(poolbuf[i].dirty) poolbuf[i].dirty--; |
||
294 | return r; |
||
295 | } |
||
296 | |||
297 | int mt_permpick(struct block *blk, char *start, int level) |
||
298 | { |
||
299 | int r, n, newpool; |
||
300 | struct poolstruct *pl; |
||
8161 | bpr | 301 | |
10 | reyssat | 302 | newpool=n=0; |
303 | pl=poolbuf+blk->pool; |
||
304 | if(pl==poolbuf || pl->dirty>0) { |
||
8161 | bpr | 305 | pl=getpool(blk); newpool=1; |
306 | n=pl->len=blk->len; |
||
8195 | bpr | 307 | if(nexttag + n >= MAX_BLOCKS) sym_error("tag_overflow"); |
8161 | bpr | 308 | pl->tag=tagbuf+nexttag; nexttag+=n; |
10 | reyssat | 309 | } |
310 | if(pl->ind1==0 && pl->ind2==0) { |
||
8161 | bpr | 311 | for(r=0;pl->ind1<blk->lcnt;pl->ind1++,pl->ind2=0){ |
312 | r=_permpick1(blk,start,level); |
||
313 | if(r) break; |
||
314 | } |
||
315 | pl->ind1=pl->ind2=0; |
||
316 | if(newpool) { |
||
317 | putpool(pl); nexttag-=n; |
||
318 | } |
||
319 | return r; |
||
10 | reyssat | 320 | } |
321 | if(pl->ind2>=blk->listlen[pl->ind1]) { |
||
8161 | bpr | 322 | return mt_next(blk,start,level); |
10 | reyssat | 323 | } |
324 | return _permpick1(blk,start,level); |
||
325 | } |
||
326 | |||
327 | int mt_neg(struct block *blk, char *start, int level) |
||
328 | { |
||
329 | int r, newpool; |
||
330 | struct poolstruct *pl; |
||
8161 | bpr | 331 | |
10 | reyssat | 332 | newpool=0; |
333 | pl=poolbuf+blk->pool; |
||
334 | if(pl==poolbuf || pl->dirty>0) { |
||
8161 | bpr | 335 | pl=getpool(blk); newpool=1; |
10 | reyssat | 336 | } |
337 | if(pl->ind2) return 1; |
||
338 | pl->ind2=1; |
||
339 | r=mt_this(blockbuf+blk->sublock,start,level+1); |
||
8161 | bpr | 340 | pl->ind2=0; if(newpool) putpool(pl); |
10 | reyssat | 341 | if(r==0) return mt_next(blk,start,level+1); |
342 | if(r==1) return 0; |
||
343 | else return r; |
||
344 | } |
||
345 | |||
346 | int mt_nomatch(struct block *blk, char *start, int level) |
||
347 | { |
||
348 | return 0; |
||
349 | } |
||
350 | |||
351 | void getnpool(int b) |
||
352 | { |
||
8195 | bpr | 353 | if(nextnpool>=MAX_POOLS) sym_error("npool_overflow"); |
10 | reyssat | 354 | npool[nextnpool].nextblock=b; |
355 | npool[nextnpool].last=currnpool; |
||
356 | currnpool=nextnpool; |
||
357 | nextnpool++; |
||
358 | } |
||
359 | |||
360 | void putnpool(void) |
||
361 | { |
||
8195 | bpr | 362 | if(nextnpool<=0) sym_error("npool_underflow"); |
10 | reyssat | 363 | nextnpool--; |
364 | } |
||
365 | |||
366 | int mt_m(struct block *blk, char *start, int level) |
||
367 | { |
||
368 | int i,r,pl,b,e,cp; |
||
369 | char *bkstart; |
||
8161 | bpr | 370 | |
10 | reyssat | 371 | if(blk->string>=start) return 0; |
372 | bkstart=blk->string; blk->string=start; |
||
373 | cp=currnpool; |
||
374 | getnpool(blk->nextblock); |
||
375 | b=blk->sublock; pl=blockbuf[b].mpool; blockbuf[b].mpool=nextpool+1; |
||
376 | e=blockbuf[b].mend; |
||
377 | if(pl>0) for(i=pl-1;i<nextpool;i++) { |
||
8161 | bpr | 378 | if(poolbuf[i].block>=b && poolbuf[i].block<e) poolbuf[i].dirty++; |
10 | reyssat | 379 | } |
380 | if(debug>=3) fprintf(stderr, "Entering macro %d npool=%d, next=%d.\n", |
||
8161 | bpr | 381 | b, currnpool, npool[currnpool].nextblock); |
10 | reyssat | 382 | r = mt_this(blockbuf+b,start,level+1); |
383 | if(pl>0) for(i=pl-1;i<nextpool;i++) { |
||
8161 | bpr | 384 | if(poolbuf[i].block>=b && poolbuf[i].block<e && poolbuf[i].dirty>0) poolbuf[i].dirty--; |
10 | reyssat | 385 | } |
386 | blockbuf[b].mpool=pl; |
||
387 | putnpool(); currnpool=cp; blk->string=bkstart; |
||
388 | if(debug>=3) fprintf(stderr, "macro %d returns %d, npool=%d, next=%d.\n", |
||
8161 | bpr | 389 | b, r, nextnpool, npool[nextnpool].nextblock); |
10 | reyssat | 390 | return r; |
391 | } |
||
392 | |||
393 | int mt_out(struct block *blk, char *start, int level) |
||
394 | { |
||
395 | int r, l, newpool; |
||
396 | char buf[MAX_LINELEN+1]; |
||
397 | struct poolstruct *pl; |
||
8161 | bpr | 398 | |
10 | reyssat | 399 | newpool=0; |
400 | pl=poolbuf+blk->pool; |
||
401 | if(pl==poolbuf || pl->dirty>0) { |
||
8161 | bpr | 402 | pl=getpool(blk); newpool=1; |
10 | reyssat | 403 | } |
404 | if(pl->ind2) { |
||
8161 | bpr | 405 | pl->string=start; |
406 | return mt_next(blk,start,level+1); |
||
10 | reyssat | 407 | } |
408 | pl->ind2++; |
||
409 | r=mt_this(blockbuf+blk->sublock,start,level+1); |
||
8161 | bpr | 410 | pl->ind2=0; if(newpool) putpool(pl); |
10 | reyssat | 411 | if(r) { |
8161 | bpr | 412 | l=pl->string - start; |
413 | if(l>=0 && l<MAX_LINELEN) { |
||
414 | memmove(buf,start,l); buf[l]=0; |
||
415 | outval(blk->string, buf); |
||
416 | } |
||
10 | reyssat | 417 | } |
418 | return r; |
||
419 | } |
||
420 | |||
421 | int mt_w(struct block *blk, char *start, int level) |
||
422 | { |
||
423 | char *p1, *p2; |
||
424 | char buf[MAX_NAMELEN+1]; |
||
425 | int l; |
||
426 | p1=find_word_start(start); p2=find_word_end(p1); l=p2-p1; |
||
427 | if(*p2) p2++; |
||
428 | if(l>=MAX_NAMELEN) return 0; |
||
429 | memmove(buf,p1,l); buf[l]=0; |
||
430 | if(wordchr(wbuf,buf)==NULL) return 0; |
||
431 | return mt_next(blk,p2,level+1); |
||
432 | } |
||
433 | |||
434 | int mt_wild(struct block *blk, char *start, int level) |
||
435 | { |
||
436 | char *p; |
||
437 | int i,l,r; |
||
438 | |||
439 | l=blk->lstart; |
||
440 | for(i=0,p=find_word_start(start);i<l;i++,p=find_word_start(find_word_end(p))) { |
||
8161 | bpr | 441 | if(*p==0) return 0; |
10 | reyssat | 442 | } |
443 | l=blk->len; |
||
444 | if(l==0) return mt_next(blk,p,level+1); |
||
445 | for(i=0; i<=l && *p; i++, p=find_word_start(find_word_end(p))) { |
||
8161 | bpr | 446 | r=mt_next(blk,p,level+1); |
447 | if(r) return r; |
||
10 | reyssat | 448 | } |
449 | if(i<=l) return mt_next(blk,p,level+1); |
||
450 | else return 0; |
||
451 | } |
||
452 | |||
453 | int match(char *p) |
||
454 | { |
||
455 | int i; |
||
456 | outptr=outbuf; *outptr=0; nextpool=nextnpool=1; nexttag=0; |
||
457 | currnpool=0; |
||
458 | for(i=0;i<nextblock;i++) blockbuf[i].pool=blockbuf[i].mpool=0; |
||
459 | return mt_this(blockbuf,find_word_start(p),0); |
||
460 | } |