Subversion Repositories wimsdev

Rev

Rev 3247 | Rev 8068 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*    Copyright (C) 1998-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. char t_buf[4][MAX_LINELEN+1];
  19. char maskbuf[MAX_LINELEN+1];
  20.  
  21.         /* internal routine. */
  22. void _text_cut(char *p, char *w)
  23. {
  24.     char *p1, *p2;
  25.     p1=wordchr(p,w); if(p1==NULL) error2("syntax_error");
  26.     *p1=0; p2=find_word_start(p1+strlen(w));
  27.     ovlstrcpy(t_buf[0],p); ovlstrcpy(t_buf[1],p2);
  28.     strip_trailing_spaces(t_buf[0]);
  29.     substitute(t_buf[0]); substitute(t_buf[1]);
  30. }
  31.  
  32.         /* Extract characters in buf[0] which are identical to
  33.          * corresponding characters in buf[1]. */
  34. void text_common(char *p)
  35. {
  36.     int i,j,n1,n2;
  37.     _text_cut(p,"and");
  38.     n1=strlen(t_buf[0]);n2=strlen(t_buf[1]);
  39.     if(n2<n1) n1=n2;
  40.     for(i=j=0;i<n1;i++) {
  41.         if(t_buf[0][i]==t_buf[1][i] && maskbuf[i]!='0') p[j++]=t_buf[0][i];
  42.     }
  43.     p[j]=0;
  44. }
  45.  
  46.         /* Returns a mask string composed of '0's and '1's, where
  47.          * '0' means corresponding positions of buf[0] and buf[1] are
  48.          * equal. */
  49. void text_compare(char *p)
  50. {
  51.     int min,max, i;
  52.     _text_cut(p,"and");
  53.     min=strlen(t_buf[0]); max=strlen(t_buf[1]);
  54.     if(min>max) {
  55.         i=min; min=max; max=i;
  56.     }
  57.     for(i=0; i<min; i++) {
  58.         if(t_buf[0][i]==t_buf[1][i]) p[i]='0'; else p[i]='1';
  59.     }
  60.     for(; i<max; i++) p[i]='1';
  61.     p[max]=0;
  62. }
  63.  
  64.         /* copy text according to mask. */
  65. void text_copy(char *p)
  66. {
  67.     int i, j, n;
  68.    
  69.     snprintf(t_buf[0],MAX_LINELEN,"%s",p);
  70.     strip_trailing_spaces(t_buf[0]); substitute(t_buf[0]);
  71.     n=strlen(t_buf[0]);
  72.     for(i=j=0;i<n;i++) {
  73.         if(maskbuf[i]!='0') p[j++]=t_buf[0][i];
  74.     }
  75.     p[j]=0;
  76. }
  77.  
  78.         /* returns count of characters in buf[1] which appear in buf[0]. */
  79. void text_count(char *p)
  80. {
  81.     int i, n, c;
  82.     _text_cut(p,"in");
  83.     n=strlen(t_buf[1]);
  84.     for(i=c=0;i<n;i++) {
  85.         if(strchr(t_buf[0],t_buf[1][i])!=NULL && maskbuf[i]!='0') c++;
  86.     }
  87.     snprintf(p,MAX_LINELEN,"%d",c);
  88. }
  89.  
  90.         /* Extract characters in buf[0] which are different than
  91.          * corresponding characters in buf[1]. */
  92. void text_diff(char *p)
  93. {
  94.     int i,j,n1,n2;
  95.     _text_cut(p,"from");
  96.     n1=strlen(t_buf[0]);n2=strlen(t_buf[1]);
  97.     if(n2<n1) n1=n2;
  98.     for(i=j=0;i<n1;i++) {
  99.         if(t_buf[0][i]!=t_buf[1][i] && maskbuf[i]!='0') p[j++]=t_buf[0][i];
  100.     }
  101.     p[j]=0;
  102. }
  103.  
  104.         /* put chars in buf[0] in a new string, into positions
  105.          * corresponding to '1's in the mask buf[1].
  106.          * Positions corresponding to '0's are filled by space.
  107.          * Fill stops at the end of buf[0]. If buf[1] is
  108.          * too short, it is reused from the start. */
  109. void text_expand(char *p)
  110. {
  111.     int i,j,k,n1,n2;
  112.     _text_cut(p,"using");
  113.     n1=strlen(t_buf[0]);n2=strlen(t_buf[1]);
  114.     if(n2==0) {p[0]=0; return;}
  115.     for(i=j=k=0;i<n1 && j<MAX_LINELEN;j++,k=j%n2) {
  116.         if(t_buf[1][k]=='0') p[j]=' ';
  117.         else p[j]=t_buf[0][i++];
  118.     }
  119.     p[j]=0;
  120. }
  121.  
  122.         /* character by character replacement of buf[1] by buf[0],
  123.          * replacing only mask-effective chars.
  124.          * The resulting string is as long as buf[1], and the replacement
  125.          * stops when chars buf[0] has run out. */
  126. void text_insert(char *p)
  127. {
  128.     int i,j,n1,n2;
  129.     _text_cut(p,"into");
  130.     n1=strlen(t_buf[0]);n2=strlen(t_buf[1]);
  131.     for(i=j=0; i<n2 && j<n1; i++) {
  132.         if(maskbuf[i]!='0') t_buf[1][i]=t_buf[0][j++];
  133.     }
  134.     snprintf(p,MAX_LINELEN,"%s",t_buf[1]);
  135. }
  136.  
  137. #define MAX_TLEN 96
  138.  
  139.         /* interact of two strings according to rules
  140.          * defined a table. */
  141. void text_interact(char *p)
  142. {
  143.     char *table, *dline, *tline[MAX_TLEN];
  144.     char *p1, *p2;
  145.     int i,j1,j2,k,l,l2,n;
  146.    
  147.     table=wordchr(p,"table");
  148.     if(table==NULL) error2("syntax_error");
  149.     *table=0; strip_trailing_spaces(p);
  150.     table=find_word_start(table+strlen("table"));
  151.     snprintf(t_buf[2],MAX_LINELEN,"%s",table);
  152.     _text_cut(p,"and");
  153.     strip_trailing_spaces(t_buf[2]); substitute(t_buf[2]);
  154.     n=linenum(t_buf[2])-1;
  155.     if(n>=MAX_TLEN) error2("text_bad_table");
  156.     p2=strchr(t_buf[2],'\n'); if(p2!=NULL) *p2++=0;
  157.     if(strlen(t_buf[2])!=n) error2("text_bad_table");
  158.     dline=t_buf[2];
  159.     for(i=0,p1=p2;i<n;i++,p1=p2) {
  160.         if(p1==NULL) error2("text_bad_table");
  161.         p2=strchr(p1,'\n');
  162.         if(p2!=NULL) *p2++=0;
  163.         if(strlen(p1)!=n) error2("text_bad_table");
  164.         tline[i]=p1;
  165.     }
  166.     l=strlen(t_buf[0]); l2=strlen(t_buf[1]); if(l2<l) l=l2;
  167.     for(i=k=0;i<l;i++) {
  168.         if(maskbuf[i]!='0') {
  169.             p1=strchr(dline,t_buf[0][i]);
  170.             p2=strchr(dline,t_buf[1][i]);
  171.             if(p1==NULL || p2==NULL) continue;
  172.             j1=p1-dline; j2=p2-dline;
  173.             if(j1>=n || j2>=n) continue; /* should not occur */
  174.             p[k++]=tline[j1][j2];
  175.         }
  176.     }
  177.     p[k]=0;
  178. }
  179.  
  180.         /* returns a mask string composed of '0's and '1's, where
  181.          * '0' means corresponding char in buf[1] appears in buf[0]. */
  182. void text_mark(char *p)
  183. {
  184.     int i, n;
  185.     _text_cut(p,"in");
  186.     n=strlen(t_buf[1]);
  187.     for(i=0;i<n;i++) {
  188.         if(strchr(t_buf[0],t_buf[1][i])!=NULL) p[i]='1';
  189.         else p[i]='0';
  190.     }
  191.     p[i]=0;
  192. }
  193.  
  194.         /* Returns a string whose characters are the maximum
  195.          * of the two corresponding chars in buf[0] and buf[1].
  196.          * Length of the string is the longuest one. */
  197. void text_max(char *p)
  198. {
  199.     int min,max, i, j, k;
  200.     _text_cut(p,"and");
  201.     min=strlen(t_buf[0]); max=strlen(t_buf[1]);
  202.     if(min>max) {
  203.         i=min; min=max; max=i; j=0;
  204.     }
  205.     else j=1;
  206.     for(i=k=0; i<min; i++) {
  207.         if(maskbuf[i]=='0') continue;
  208.         if((unsigned char)t_buf[0][i]>(unsigned char)t_buf[1][i])
  209.           p[k++]=t_buf[0][i];
  210.         else p[k++]=t_buf[1][i];
  211.     }
  212.     for(;i<max;i++) {
  213.         if(maskbuf[i]!='0') p[k++]=t_buf[j][i];
  214.     }
  215.     p[k]=0;
  216. }
  217.  
  218.         /* Returns a string whose characters are the minimum
  219.          * of the two corresponding chars in buf[0] and buf[1].
  220.          * Length of the string is the shortest one. */
  221. void text_min(char *p)
  222. {
  223.     int min,max, i,k;
  224.     _text_cut(p,"and");
  225.     min=strlen(t_buf[0]); max=strlen(t_buf[1]);
  226.     if(min>max) {
  227.         i=min; min=max; max=i;
  228.     }
  229.     for(i=k=0; i<min; i++) {
  230.         if(maskbuf[i]=='0') continue;
  231.         if((unsigned char)t_buf[0][i]< (unsigned char)t_buf[1][i])
  232.           p[k++]=t_buf[0][i];
  233.         else p[k++]=t_buf[1][i];
  234.     }
  235.     p[k]=0;
  236. }
  237.  
  238.         /* extract chars in buf[0] which occur in buf[1]. */
  239. void text_occur(char *p)
  240. {
  241.     int i,j,n;
  242.     char buf[MAX_LINELEN+1];
  243.     memset(buf,0,sizeof(buf));
  244.     _text_cut(p,"in");
  245.     n=strlen(t_buf[1]);
  246.     for(i=0;i<n;i++) {
  247.         char *pp;
  248.         if(maskbuf[i]=='0') continue;
  249.         pp=strchr(t_buf[0],t_buf[1][i]);
  250.         if(pp!=NULL) buf[pp - t_buf[0]]=1;
  251.     }
  252.     n=strlen(t_buf[0]);
  253.     for(i=j=0;i<n;i++) {
  254.         if(buf[i]) p[j++]=t_buf[0][i];
  255.     }
  256.     p[j]=0;
  257. }
  258.  
  259.         /* remove characters of buf[1] in buf[0]. */
  260. void text_remove(char *p)
  261. {
  262.     int i, j, n;
  263.     _text_cut(p,"in");
  264.     n=strlen(t_buf[1]);
  265.     for(i=j=0;i<n;i++) {
  266.         if(strchr(t_buf[0],t_buf[1][i])==NULL
  267.            && maskbuf[i]!='0') p[j++]=t_buf[1][i];
  268.     }
  269.     p[j]=0;
  270. }
  271.  
  272.         /* Cyclic reordering of text. */
  273. void text_reorder(char *p)
  274. {
  275.     int i,j,k,l,n,t;
  276.     int list[10240];
  277.     char buf[MAX_LINELEN+1];
  278.     _text_cut(p,"by"); *p=0;
  279.     n=itemnum(t_buf[1]); if(n<=0 || n>=10240) return;
  280.     for(i=0;i<n;i++) {
  281.         buf[0]=0; fnd_item(t_buf[1],i+1,buf);
  282.         j=atoi(buf); if(j<=0 || j>n) return;
  283.         list[i]=j;
  284.     }
  285.     t=strlen(t_buf[0]);
  286.     for(i=l=0;l<t && i<t+n;i++) {
  287.         j=i/n; k=j*n+list[i%n];
  288.         if(k>t || k<=0) continue;
  289.         p[l++]=t_buf[0][k-1];
  290.     }
  291.     p[l]=0;
  292. }
  293.  
  294.         /* repeat a string to a given length. */
  295. void text_repeat(char *p)
  296. {
  297.     int n,i,k;
  298.     _text_cut(p,"to");
  299.     n=strevalue(t_buf[1]); if(n>MAX_LINELEN) n=MAX_LINELEN;
  300.     if(n<0) n=0;
  301.     k=strlen(t_buf[0]); if(k<=0) {*p=0; return;}
  302.     for(i=0;i<n;i++) {
  303.         p[i]=t_buf[0][i%k];
  304.     }
  305.     p[i]=0;
  306. }
  307.  
  308.         /* reverse a string */
  309. void text_reverse(char *p)
  310. {
  311.     int i,n;
  312.     char buf[MAX_LINELEN+1];
  313.     snprintf(t_buf[0],sizeof(t_buf[0]),"%s",p);
  314.     substitute(t_buf[0]);
  315.     n=strlen(t_buf[0]); if(n>MAX_LINELEN) n=MAX_LINELEN;
  316.     for(i=0;i<n;i++) buf[i]=t_buf[0][n-1-i];
  317.     buf[n]=0;
  318.     ovlstrcpy(p,buf);
  319. }
  320.  
  321.         /* remove characters of buf[1] not in buf[0]. */
  322. void text_select(char *p)
  323. {
  324.     int i, j, n;
  325.     _text_cut(p,"in");
  326.     n=strlen(t_buf[1]);
  327.     for(i=j=0;i<n;i++) {
  328.         if(strchr(t_buf[0],t_buf[1][i])!=NULL
  329.            && maskbuf[i]!='0') p[j++]=t_buf[1][i];
  330.     }
  331.     p[j]=0;
  332. }
  333.  
  334.         /* tag: bit 0 is mask. */
  335. struct {
  336.     char *name;
  337.     int tag;
  338.     void (*routine) (char *p);
  339. } text_proc[]={
  340.       {"appear",        1,      text_occur},
  341.       {"common",        1,      text_common},
  342.       {"compare",       0,      text_compare},
  343.       {"copy",          1,      text_copy},
  344.       {"count",         1,      text_count},
  345.       {"delete",        1,      text_remove},
  346.       {"diff",          1,      text_diff},
  347.       {"differ",        1,      text_diff},
  348.       {"drop",          1,      text_remove},
  349.       {"expand",        0,      text_expand},
  350.       {"extract",       1,      text_select},
  351.       {"insert",        1,      text_insert},
  352.       {"interact",      1,      text_interact},
  353.       {"mark",          0,      text_mark},
  354.       {"max",           1,      text_max},
  355.       {"min",           1,      text_min},
  356.       {"occur",         1,      text_occur},
  357.       {"occurrence",    1,      text_occur},
  358.       {"pick",          1,      text_select},
  359.       {"pickup",        1,      text_select},
  360.       {"remove",        1,      text_remove},
  361.       {"reorder",       0,      text_reorder},
  362.       {"repeat",        0,      text_repeat},
  363.       {"reverse",       0,      text_reverse},
  364.       {"select",        1,      text_select}
  365. };
  366. #define TEXT_PROC_NO (sizeof(text_proc)/sizeof(text_proc[0]))
  367.  
  368. int textab_verify(void) {
  369.     return verify_order(text_proc,TEXT_PROC_NO,sizeof(text_proc[0]));
  370. }
  371.  
  372.         /* main entry point for text routines */
  373. void text(char *p)
  374. {
  375.     int i,j,n;
  376.     char *p1, *p2;
  377.     char c,cc;
  378.     char buf[MAX_LINELEN+1];
  379.     p1=find_word_start(p); p2=find_word_end(p1);
  380.     if(p2<=p1 || *p2==0) error2("syntax_error");
  381.     *p2=0;
  382.     i=search_list(text_proc,TEXT_PROC_NO,sizeof(text_proc[0]),p1);
  383.     if(i<0) error2("syntax_error");
  384.     snprintf(buf,sizeof(buf),"%s",find_word_start(p2+1));
  385.     if((text_proc[i].tag&1)!=0 && (p1=wordchr(buf,"mask"))!=NULL) {
  386.         *p1=0; strip_trailing_spaces(buf);
  387.         p2=find_word_start(p1+strlen("mask"));
  388.         strip_trailing_spaces(p2);
  389.         snprintf(maskbuf,sizeof(maskbuf),"%s",p2);
  390.         substitute(maskbuf);
  391.         n=strlen(maskbuf); if(n==0) goto zeromask;
  392.         c=maskbuf[n-1]; cc=0;
  393.         if(c=='+') cc='1'; if(c=='-') cc='0';
  394.         if(cc!=0) memset(maskbuf+n-1,cc,sizeof(maskbuf)-n);
  395.         else for(j=n;j<MAX_LINELEN;j++) maskbuf[j]=maskbuf[j%n];
  396.         maskbuf[sizeof(maskbuf)-1]=0;
  397.     }
  398.     else zeromask: memset(maskbuf,0,sizeof(maskbuf));
  399.     text_proc[i].routine(buf);
  400.     buf[MAX_LINELEN]=0;ovlstrcpy(p,buf);
  401. }
  402.  
  403.