Subversion Repositories wimsdev

Rev

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
}