Subversion Repositories wimsdev

Rev

Rev 3808 | Go to most recent revision | 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.         /* 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);
  100.     if(debug>=2) fprintf(stderr,"lvl=%d. Checking against block %d for %.10s.\n",level,blk-blockbuf,start);
  101.     r = blk->fn(blk,start,level);
  102.     if(debug) fprintf(stderr,"lvl=%d. Tested %d block %d for %.10s.\n",level,r,blk-blockbuf,start);
  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");
  117.         if(debug>=3) fprintf(stderr,"Calling macro %d: next=%d.\n",
  118.                              blk-blockbuf,next);
  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);
  152.         if(itemchr(et->replace,blk->string)==NULL) return 0;
  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.  
  460.