Subversion Repositories wimsdev

Rev

Rev 10 | Rev 8155 | 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. void calc_itemof(char *p);
  19. void calc_rowof(char *p);
  20. void calc_columnof(char *p);
  21.  
  22.         /* It is this routine which uses print_precision. */
  23. void float2str(double d, char *p)
  24. {
  25.     char buf[16];
  26.     int i;
  27.     if(d==0) {
  28.         ovlstrcpy(p,"0"); return;
  29.     }
  30.     if(!finite(d)) { /* isinf, isnan possibly not available */
  31.         if (d == d) ovlstrcpy(p, (d > 0)? "Inf": "-Inf"); else ovlstrcpy(p,"NaN");
  32.         return;
  33.     }
  34.     if(d<1000000 && d>-1000000 && d==floor(d)) {
  35.         mystrncpy(p,int2str(d),MAX_LINELEN); return;
  36.     }
  37.     i=print_precision;
  38.     if(i<2) i=2; if(i>32) i=32;  /* Simple limitation. */
  39.     buf[0]='%';buf[1]='.';
  40.     if(i>=10) {
  41.         buf[2]='0'+i/10; buf[3]='0'+i%10; buf[4]='g'; buf[5]=0;
  42.     }
  43.     else {
  44.         buf[2]='0'+i; buf[3]='g'; buf[4]=0;
  45.     }
  46.     snprintf(p,MAX_LINELEN,buf,(double) d);
  47.     if(isspace(*p)) ovlstrcpy(p,find_word_start(p));
  48. }
  49.  
  50.         /* substitute variable names by their environment strings
  51.          * The buffer pointed to by p must have enough space
  52.          * (defined by MAX_LINELEN). */
  53. char *substit(char *p)
  54. {
  55.     char *pp, *p2, *ev;
  56.     char *oldlast, *oldnext, *oldend, *newend;
  57.     char buf[MAX_LINELEN+1], oldbuf[MAX_LINELEN+1];
  58.     int ln;
  59.  
  60.     if((p2=strchr(p,'$'))==NULL) return p;
  61.     if(substnest>SUBST_LIMIT) module_error("subst_exceeded");
  62.     ln=strlen(p); if(ln>=MAX_LINELEN) goto too_long;
  63.     memmove(oldbuf,p,ln); oldbuf[ln]=0; oldend=oldbuf+ln;
  64.     newend=p; oldlast=oldnext=oldbuf;
  65.     for(pp=oldbuf+(p2-p); pp!=NULL; pp=strchr(pp,'$')) {
  66.         if(*(pp+1)=='$') {      /* escaped dollar sign */
  67.             pp++; if(newend-p+(pp-oldlast)>=MAX_LINELEN) goto too_long;
  68.             memmove(newend,oldlast,pp-oldlast); newend+=pp-oldlast;
  69.             pp++; oldlast=pp; continue;
  70.         }
  71.         switch(*(pp+1)) {
  72.             case 0: {
  73.                 *pp=0; oldend--; goto end;
  74.             }
  75.             case '(': {
  76.                 p2=find_matching(pp+2,')');
  77.                 if(p2==NULL) {
  78.                     module_error("unmatched_parentheses");
  79.                     *p=0; return p;
  80.                 }
  81.                 *p2++=0; oldnext=p2; memmove(buf,pp+2,p2-pp-2);
  82.                 substnest++; substit(buf); substnest--;
  83.                 break;
  84.             }
  85.  
  86.             case '[': {
  87.                 double d;
  88.                 p2=find_matching(pp+2,']');
  89.                 if(p2==NULL) {
  90.                     module_error("unmatched_parentheses");
  91.                     *p=0; return p;
  92.                 }
  93.                 *p2=0; ovlstrcpy(buf,pp+2); oldnext=p2+1;
  94.                 substnest++; substit(buf); substnest--;
  95.                 d=evalue(buf); float2str(d,buf);
  96.                 goto replace;
  97.             }
  98.                
  99.             default: {
  100.                 for(p2=pp+1; myisalnum(*p2) || *p2=='_'; p2++);
  101.                 oldnext=p2; memmove(buf,pp+1,p2-(pp+1)); buf[p2-(pp+1)]=0;
  102.                 goto noarray;
  103.             }
  104.         }
  105.         if((p2=strchr(buf,'['))!=NULL) {
  106.             char *pt1, tbuf[MAX_LINELEN+1];
  107.             *p2++=0; pt1=find_matching(p2,']');
  108.             if(pt1==NULL) {buf[0]=0; goto replace;}
  109.             *pt1=0; pt1=strchr(p2,';');
  110.             if(pt1==NULL) {
  111.                 if(*find_word_start(p2)==0) {*p2=0; goto noarray;}
  112.                 snprintf(tbuf,sizeof(tbuf),"%s of $%s",p2,buf);
  113.                 calc_itemof(tbuf); ovlstrcpy(buf,tbuf); goto replace;
  114.             }
  115.             else {
  116.                 *pt1++=0; p2=find_word_start(p2);
  117.                 if(*p2) {
  118.                     snprintf(tbuf,sizeof(tbuf),"%s of $%s",p2,buf);
  119.                     calc_rowof(tbuf);
  120.                 }
  121.                 else {
  122.                     snprintf(tbuf,sizeof(tbuf),"$%s",buf); substit(tbuf);
  123.                 }
  124.                 if(*find_word_start(pt1)) {
  125.                     snprintf(buf,sizeof(buf),"%s of %s",pt1,tbuf);
  126.                     calc_columnof(buf); goto replace;
  127.                 }
  128.                 else ovlstrcpy(buf,tbuf);
  129.                 goto replace;
  130.             }
  131.         }
  132.         noarray: ev=getvar(buf); ln=getvar_len;
  133.         if(ev==NULL) ev=""; if(strchr(ev,'$')==NULL) goto rep2;
  134.         memmove(buf,ev,ln); buf[ln]=0;
  135.         substnest++; substit(buf); substnest--;
  136.         replace: ev=buf; ln=strlen(ev);
  137.         rep2:
  138.         if(pp>oldlast) {
  139.             if(newend-p+(pp-oldlast)>=MAX_LINELEN) goto too_long;
  140.             memmove(newend,oldlast,pp-oldlast); newend+=pp-oldlast;
  141.         }
  142.         if(ln>0) {
  143.             if((newend-p)+ln>=MAX_LINELEN) goto too_long;
  144.             memmove(newend,ev,ln); newend+=ln;
  145.         }
  146.         pp=oldlast=oldnext;
  147.         continue;
  148.     }
  149.     end:
  150.     if(oldlast<oldend) {
  151.         if(newend-p+(oldend-oldlast)>=MAX_LINELEN) goto too_long;
  152.         memmove(newend,oldlast,oldend-oldlast); newend+=oldend-oldlast;
  153.     }
  154.     *newend=0; return p;
  155.     too_long: user_error("cmd_output_too_long"); return NULL;
  156. }
  157.  
  158. enum {for_in, for_from};
  159. struct {
  160.     char var[MAX_NAMELEN+1];
  161.     int type;
  162.     double list[MAX_VALUE_LIST];
  163.     char *pos[MAX_VALUE_LIST];
  164.     double from, to, step;
  165. } forstruct;
  166.  
  167. int for_getvar(char *p)
  168. {
  169.     char *vp, buf[MAX_LINELEN+1];
  170.     mystrncpy(buf,p,sizeof(buf)); substit(buf);
  171.     vp=find_word_start(buf); for(p=vp; myisalnum(*p) || *p=='_'; p++);
  172.     *p=0; if(p-vp<=0 || p-vp>MAX_NAMELEN) return -1;
  173.     mystrncpy(forstruct.var,vp,sizeof(forstruct.var));
  174.     return 0;
  175. }
  176.  
  177.         /* If bufp=NULL then numeric. Else string-wise.
  178.          * returns 0 if success,
  179.          * -1 if syntax error, 1 if bad values */
  180. int cutfor(char *p, char *bufp)
  181. {
  182.     char *eqp, *fromp, *top, *stepp, *inp;
  183.  
  184.     p=find_word_start(p);
  185.     inp=find_word_start(find_word_end(p));
  186.     if(wordchr(inp,"in")==inp) {
  187.         char buf[MAX_LINELEN+1], *bp;
  188.         int i;
  189.         double d;
  190.         *inp=0; inp+=strlen("in");
  191.         forin: inp=find_word_start(inp); forstruct.type=for_in;
  192.         if(for_getvar(p)) return -1;
  193.         if(bufp!=NULL) bp=bufp; else bp=buf;
  194.         mystrncpy(bp,inp,MAX_LINELEN); substit(bp);
  195.         strip_trailing_spaces(bp);
  196.         if(bp[0]==0) {
  197.             forstruct.from=0; forstruct.to=-1; forstruct.step=1; return 0;
  198.         }
  199.         for(i=0, inp=bp; i<MAX_VALUE_LIST && inp!=NULL; inp=top) {
  200.             top=strparchr(inp,','); if(top) *top++=0;
  201.             if(bufp==NULL) {
  202.                 d=evalue(inp); if(finite(d)) forstruct.list[i++]=d;
  203.                 else return 1;
  204.             }
  205.             else {
  206.                 strip_trailing_spaces(inp);
  207.                 forstruct.pos[i++]=find_word_start(inp);
  208.             }
  209.         }
  210.         forstruct.from=0; forstruct.to=i-1; forstruct.step=1; return 0;
  211.     }
  212.     top=wordchr(p,"to"); if(top==NULL) {
  213.         inp=strchr(p,'='); if(inp==NULL) return -1;
  214.         *inp++=0; goto forin;
  215.     }
  216.     *top=0; top+=strlen("to");
  217.     stepp=wordchr(top,"step"); if(stepp!=NULL) {
  218.         *stepp=0; stepp+=strlen("step"); forstruct.step=evalue(stepp);
  219.     }
  220.     else forstruct.step=1;
  221.     forstruct.to=evalue(top); forstruct.type=for_from;
  222.     eqp=strchr(p,'='); fromp=wordchr(p,"from"); inp=wordchr(p,"in");
  223.     if(eqp!=NULL && (fromp==NULL || eqp<fromp)) {
  224.         *eqp++=0; fromp=eqp;
  225.     }
  226.     else {
  227.         if(fromp==NULL) return -1;
  228.         *fromp=0; fromp+=strlen("from");
  229.     }
  230.     forstruct.from=evalue(fromp);
  231.     if(for_getvar(p)) return -1;
  232.     if(!finite(forstruct.from+forstruct.to+forstruct.step)) return 1;
  233.     else return 0;
  234. }
  235.  
  236.