Subversion Repositories wimsdev

Rev

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