Back to index

wims  3.65+svn20090927
evalue.c
Go to the documentation of this file.
00001 /*    Copyright (C) 1998-2003 XIAO, Gang of Universite de Nice - Sophia Antipolis
00002  *
00003  *  This program is free software; you can redistribute it and/or modify
00004  *  it under the terms of the GNU General Public License as published by
00005  *  the Free Software Foundation; either version 2 of the License, or
00006  *  (at your option) any later version.
00007  *
00008  *  This program is distributed in the hope that it will be useful,
00009  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00010  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011  *  GNU General Public License for more details.
00012  *
00013  *  You should have received a copy of the GNU General Public License
00014  *  along with this program; if not, write to the Free Software
00015  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00016  */
00017 
00018 void calc_itemof(char *p);
00019 void calc_rowof(char *p);
00020 void calc_columnof(char *p);
00021 
00022        /* It is this routine which uses print_precision. */
00023 void float2str(double d, char *p)
00024 {
00025     char buf[16];
00026     int i;
00027     if(d==0) {
00028        strcpy(p,"0"); return;
00029     }
00030     if(!finite(d)) { /* isinf, isnan possibly not available */
00031        if (d == d) strcpy(p, (d > 0)? "Inf": "-Inf"); else strcpy(p,"NaN");
00032        return;
00033     }
00034     if(d<1000000 && d>-1000000 && d==floor(d)) {
00035        mystrncpy(p,int2str(d),MAX_LINELEN); return;
00036     }
00037     i=print_precision;
00038     if(i<2) i=2; if(i>32) i=32;  /* Simple limitation. */
00039     buf[0]='%';buf[1]='.';
00040     if(i>=10) {
00041        buf[2]='0'+i/10; buf[3]='0'+i%10; buf[4]='g'; buf[5]=0;
00042     }
00043     else {
00044        buf[2]='0'+i; buf[3]='g'; buf[4]=0;
00045     }
00046     snprintf(p,MAX_LINELEN,buf,(double) d);
00047     if(isspace(*p)) strcpy(p,find_word_start(p));
00048 }
00049 
00050        /* substitute variable names by their environment strings
00051         * The buffer pointed to by p must have enough space
00052         * (defined by MAX_LINELEN). */
00053 char *substit(char *p)
00054 {
00055     char *pp, *p2, *ev;
00056     char *oldlast, *oldnext, *oldend, *newend;
00057     char buf[MAX_LINELEN+1], oldbuf[MAX_LINELEN+1];
00058     int ln;
00059 
00060     if((p2=strchr(p,'$'))==NULL) return p;
00061     if(substnest>SUBST_LIMIT) module_error("subst_exceeded");
00062     ln=strlen(p); if(ln>=MAX_LINELEN) goto too_long;
00063     memmove(oldbuf,p,ln); oldbuf[ln]=0; oldend=oldbuf+ln;
00064     newend=p; oldlast=oldnext=oldbuf;
00065     for(pp=oldbuf+(p2-p); pp!=NULL; pp=strchr(pp,'$')) {
00066        if(*(pp+1)=='$') {   /* escaped dollar sign */
00067            pp++; if(newend-p+(pp-oldlast)>=MAX_LINELEN) goto too_long;
00068            memmove(newend,oldlast,pp-oldlast); newend+=pp-oldlast;
00069            pp++; oldlast=pp; continue;
00070        }
00071        switch(*(pp+1)) {
00072            case 0: {
00073               *pp=0; oldend--; goto end;
00074            }
00075            case '(': {
00076               p2=find_matching(pp+2,')');
00077               if(p2==NULL) {
00078                   module_error("unmatched_parentheses");
00079                   *p=0; return p;
00080               }
00081               *p2++=0; oldnext=p2; memmove(buf,pp+2,p2-pp-2);
00082               substnest++; substit(buf); substnest--;
00083               break;
00084            }
00085 
00086            case '[': {
00087               double d;
00088               p2=find_matching(pp+2,']');
00089               if(p2==NULL) {
00090                   module_error("unmatched_parentheses");
00091                   *p=0; return p;
00092               }
00093               *p2=0; strcpy(buf,pp+2); oldnext=p2+1;
00094               substnest++; substit(buf); substnest--;
00095               d=evalue(buf); float2str(d,buf);
00096               goto replace;
00097            }
00098               
00099            default: {
00100               for(p2=pp+1; myisalnum(*p2) || *p2=='_'; p2++);
00101               oldnext=p2; memmove(buf,pp+1,p2-(pp+1)); buf[p2-(pp+1)]=0;
00102               goto noarray;
00103            }
00104        }
00105        if((p2=strchr(buf,'['))!=NULL) {
00106            char *pt1, tbuf[MAX_LINELEN+1];
00107            *p2++=0; pt1=find_matching(p2,']');
00108            if(pt1==NULL) {buf[0]=0; goto replace;}
00109            *pt1=0; pt1=strchr(p2,';');
00110            if(pt1==NULL) {
00111               if(*find_word_start(p2)==0) {*p2=0; goto noarray;}
00112               snprintf(tbuf,sizeof(tbuf),"%s of $%s",p2,buf);
00113               calc_itemof(tbuf); strcpy(buf,tbuf); goto replace;
00114            }
00115            else {
00116               *pt1++=0; p2=find_word_start(p2);
00117               if(*p2) {
00118                   snprintf(tbuf,sizeof(tbuf),"%s of $%s",p2,buf);
00119                   calc_rowof(tbuf);
00120               }
00121               else {
00122                   snprintf(tbuf,sizeof(tbuf),"$%s",buf); substit(tbuf);
00123               }
00124               if(*find_word_start(pt1)) {
00125                   snprintf(buf,sizeof(buf),"%s of %s",pt1,tbuf);
00126                   calc_columnof(buf); goto replace;
00127               }
00128               else strcpy(buf,tbuf);
00129               goto replace;
00130            }
00131        }
00132        noarray: ev=getvar(buf); ln=getvar_len;
00133        if(ev==NULL) ev=""; if(strchr(ev,'$')==NULL) goto rep2;
00134        memmove(buf,ev,ln); buf[ln]=0;
00135        substnest++; substit(buf); substnest--;
00136        replace: ev=buf; ln=strlen(ev);
00137        rep2:
00138        if(pp>oldlast) {
00139            if(newend-p+(pp-oldlast)>=MAX_LINELEN) goto too_long;
00140            memmove(newend,oldlast,pp-oldlast); newend+=pp-oldlast;
00141        }
00142        if(ln>0) {
00143            if((newend-p)+ln>=MAX_LINELEN) goto too_long;
00144            memmove(newend,ev,ln); newend+=ln;
00145        }
00146        pp=oldlast=oldnext;
00147        continue;
00148     }
00149     end: 
00150     if(oldlast<oldend) {
00151        if(newend-p+(oldend-oldlast)>=MAX_LINELEN) goto too_long;
00152        memmove(newend,oldlast,oldend-oldlast); newend+=oldend-oldlast;
00153     }
00154     *newend=0; return p;
00155     too_long: user_error("cmd_output_too_long"); return NULL;
00156 }
00157 
00158 enum {for_in, for_from};
00159 struct {
00160     char var[MAX_NAMELEN+1];
00161     int type;
00162     double list[MAX_VALUE_LIST];
00163     char *pos[MAX_VALUE_LIST];
00164     double from, to, step;
00165 } forstruct;
00166 
00167 int for_getvar(char *p)
00168 {
00169     char *vp, buf[MAX_LINELEN+1];
00170     mystrncpy(buf,p,sizeof(buf)); substit(buf);
00171     vp=find_word_start(buf); for(p=vp; myisalnum(*p) || *p=='_'; p++);
00172     *p=0; if(p-vp<=0 || p-vp>MAX_NAMELEN) return -1;
00173     mystrncpy(forstruct.var,vp,sizeof(forstruct.var));
00174     return 0;
00175 }
00176 
00177        /* If bufp=NULL then numeric. Else string-wise.
00178         * returns 0 if success, 
00179         * -1 if syntax error, 1 if bad values */
00180 int cutfor(char *p, char *bufp)
00181 {
00182     char *eqp, *fromp, *top, *stepp, *inp;
00183 
00184     p=find_word_start(p);
00185     inp=find_word_start(find_word_end(p));
00186     if(wordchr(inp,"in")==inp) {
00187        char buf[MAX_LINELEN+1], *bp;
00188        int i;
00189        double d;
00190        *inp=0; inp+=strlen("in");
00191        forin: inp=find_word_start(inp); forstruct.type=for_in;
00192        if(for_getvar(p)) return -1;
00193        if(bufp!=NULL) bp=bufp; else bp=buf;
00194        mystrncpy(bp,inp,MAX_LINELEN); substit(bp);
00195        strip_trailing_spaces(bp);
00196        if(bp[0]==0) {
00197            forstruct.from=0; forstruct.to=-1; forstruct.step=1; return 0;
00198        }
00199        for(i=0, inp=bp; i<MAX_VALUE_LIST && inp!=NULL; inp=top) {
00200            top=strparchr(inp,','); if(top) *top++=0;
00201            if(bufp==NULL) {
00202               d=evalue(inp); if(finite(d)) forstruct.list[i++]=d;
00203               else return 1;
00204            }
00205            else {
00206               strip_trailing_spaces(inp);
00207               forstruct.pos[i++]=find_word_start(inp);
00208            }
00209        }
00210        forstruct.from=0; forstruct.to=i-1; forstruct.step=1; return 0;
00211     }
00212     top=wordchr(p,"to"); if(top==NULL) {
00213        inp=strchr(p,'='); if(inp==NULL) return -1;
00214        *inp++=0; goto forin;
00215     }
00216     *top=0; top+=strlen("to");
00217     stepp=wordchr(top,"step"); if(stepp!=NULL) {
00218        *stepp=0; stepp+=strlen("step"); forstruct.step=evalue(stepp);
00219     }
00220     else forstruct.step=1;
00221     forstruct.to=evalue(top); forstruct.type=for_from;
00222     eqp=strchr(p,'='); fromp=wordchr(p,"from"); inp=wordchr(p,"in");
00223     if(eqp!=NULL && (fromp==NULL || eqp<fromp)) {
00224        *eqp++=0; fromp=eqp;
00225     }
00226     else {
00227        if(fromp==NULL) return -1;
00228        *fromp=0; fromp+=strlen("from");
00229     }
00230     forstruct.from=evalue(fromp);
00231     if(for_getvar(p)) return -1;
00232     if(!finite(forstruct.from+forstruct.to+forstruct.step)) return 1;
00233     else return 0;
00234 }
00235