Subversion Repositories wimsdev

Rev

Rev 8161 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  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. #include "symtext.h"
  19. /* Block parsing routines
  20.  * Return value:
  21.  * 0 if no match.
  22.  * 1 if match.
  23.  * -1 if error.
  24.  */
  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) {
  37.       snprintf(outptr,OUTSIZE-(outptr-outbuf)-1,"%s=_EMPTY_ ",tit);
  38.       goto outend;
  39.     }
  40.     if(*find_word_end(val)==0) {
  41.       snprintf(outptr,OUTSIZE-(outptr-outbuf)-1,"%s=%s ",tit,val);
  42.     }
  43.     else {
  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);
  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) {
  69.       memset(tag,0,pl->len*sizeof(listtype));
  70.     }
  71.     else for(i=0; i<len; i++) {
  72.       if(tag[i]>=level) tag[i]=0;
  73.     }
  74. }
  75.  
  76. struct poolstruct *getpool(struct block *blk)
  77. {
  78.     struct poolstruct *pl;
  79.  
  80.     if(nextpool>=MAX_POOLS) sym_error("pool_overflow");
  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--;
  93.     if(nextpool!=pl-poolbuf) sym_error("internal_error pool leaking");
  94.     blockbuf[pl->block].pool=pl->lastpool;
  95. }
  96.  
  97. int mt_this(struct block *blk, char *start, int level)
  98. {
  99.     int r;
  100.     if(level > MAX_LEVELS) sym_error("level_overflow %.20s",start);
  101.     start=find_word_start(start);
  102.     if(debug>=2) fprintf(stderr,"lvl=%d. Checking against block %d for %.10s.\n",level,(int)(blk-blockbuf),start);
  103.     r = blk->fn(blk,start,level);
  104.     if(debug) fprintf(stderr,"lvl=%d. Tested %d block %d for %.10s.\n",level,r,(int)(blk-blockbuf),start);
  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) {
  114.       do {
  115.           next=npool[currnpool].nextblock; currnpool=npool[currnpool].last;
  116.       }
  117.       while (next==-2 && currnpool>0);
  118.       if(next==-2) sym_error("internal_error npool disorder");
  119.       if(debug>=3) fprintf(stderr,"Calling macro %d: next=%d.\n",
  120.                        (int)(blk-blockbuf),next);
  121.     }
  122.     if(next<0) {
  123.       if(*start) return 0; else return 1;
  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) {
  135.       if(memcmp(blk->string,start,blk->len)!=0) return 0;
  136.       p=start+blk->len; if(*p && !myisspace(*p)) return 0;
  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;
  149.  
  150.     i=blk->lind1;
  151.     t=search_dic(entry+dic[i].start,dic[i].len,sizeof(entry[0]),start);
  152.     if(t>=0) {
  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);
  157.     }
  158.     switch(dic[i].unknown_type) {
  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;
  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;
  178.  
  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:
  185.     if(i>=blk->len) {            /* optional match */
  186.       i-=blk->len;
  187.       r=mt_next(blk,start,level);
  188.       if(r) goto end;
  189.     }
  190.     if(i>=0) {
  191.       r=mt_this(blockbuf+blk->sublock+i,start,level);
  192.       goto end;
  193.     }
  194.     r=0;
  195.     switch(i) {
  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.       }
  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;
  301.  
  302.     newpool=n=0;
  303.     pl=poolbuf+blk->pool;
  304.     if(pl==poolbuf || pl->dirty>0) {
  305.       pl=getpool(blk); newpool=1;
  306.       n=pl->len=blk->len;
  307.       if(nexttag + n >= MAX_BLOCKS) sym_error("tag_overflow");
  308.       pl->tag=tagbuf+nexttag; nexttag+=n;
  309.     }
  310.     if(pl->ind1==0 && pl->ind2==0) {
  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;
  320.     }
  321.     if(pl->ind2>=blk->listlen[pl->ind1]) {
  322.       return mt_next(blk,start,level);
  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;
  331.  
  332.     newpool=0;
  333.     pl=poolbuf+blk->pool;
  334.     if(pl==poolbuf || pl->dirty>0) {
  335.       pl=getpool(blk); newpool=1;
  336.     }
  337.     if(pl->ind2) return 1;
  338.     pl->ind2=1;
  339.     r=mt_this(blockbuf+blk->sublock,start,level+1);
  340.     pl->ind2=0;      if(newpool) putpool(pl);
  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. {
  353.     if(nextnpool>=MAX_POOLS) sym_error("npool_overflow");
  354.     npool[nextnpool].nextblock=b;
  355.     npool[nextnpool].last=currnpool;
  356.     currnpool=nextnpool;
  357.     nextnpool++;
  358. }
  359.  
  360. void putnpool(void)
  361. {
  362.     if(nextnpool<=0) sym_error("npool_underflow");
  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;
  370.  
  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++) {
  378.       if(poolbuf[i].block>=b && poolbuf[i].block<e) poolbuf[i].dirty++;
  379.     }
  380.     if(debug>=3) fprintf(stderr, "Entering macro %d npool=%d, next=%d.\n",
  381.                    b, currnpool, npool[currnpool].nextblock);
  382.     r = mt_this(blockbuf+b,start,level+1);
  383.     if(pl>0) for(i=pl-1;i<nextpool;i++) {
  384.       if(poolbuf[i].block>=b && poolbuf[i].block<e && poolbuf[i].dirty>0) poolbuf[i].dirty--;
  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",
  389.                    b, r, nextnpool, npool[nextnpool].nextblock);
  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;
  398.  
  399.     newpool=0;
  400.     pl=poolbuf+blk->pool;
  401.     if(pl==poolbuf || pl->dirty>0) {
  402.       pl=getpool(blk); newpool=1;
  403.     }
  404.     if(pl->ind2) {
  405.       pl->string=start;
  406.       return mt_next(blk,start,level+1);
  407.     }
  408.     pl->ind2++;
  409.     r=mt_this(blockbuf+blk->sublock,start,level+1);
  410.     pl->ind2=0;      if(newpool) putpool(pl);
  411.     if(r) {
  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.       }
  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))) {
  441.       if(*p==0) return 0;
  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))) {
  446.       r=mt_next(blk,p,level+1);
  447.       if(r) return r;
  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. }
  461.