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