Rev 18108 | 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 |
||
14664 | bpr | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
10 | reyssat | 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 | |||
7673 | bpr | 18 | /* This is part of wims source. |
8155 | bpr | 19 | * This file does computations and output. |
20 | */ |
||
8185 | bpr | 21 | #include "wims.h" |
10 | reyssat | 22 | |
23 | int _sort_numeric, _sort_nocase; |
||
24 | typedef struct SORT_STRUCT {char *str; double val; int serial;} SORT_STRUCT; |
||
25 | struct SORT_STRUCT sort_sep[MAX_SORT_ITEM+1]; |
||
26 | |||
27 | void secure_exec(void) |
||
28 | { |
||
12228 | bpr | 29 | if((untrust&6)==0) return; |
30 | module_error("Illegal_command"); |
||
10 | reyssat | 31 | } |
32 | |||
7673 | bpr | 33 | /* internal comparers */ |
10 | reyssat | 34 | int __sorter(const void *p1, const void *p2) |
35 | { |
||
12228 | bpr | 36 | struct SORT_STRUCT *pp1, *pp2; |
7404 | bpr | 37 | |
12228 | bpr | 38 | pp1=(struct SORT_STRUCT *) p1; pp2=(struct SORT_STRUCT *) p2; |
39 | if(_sort_numeric) { |
||
40 | double dd=(pp1->val)-(pp2->val); |
||
41 | if(dd>0) return 1; |
||
42 | if(dd<0) return -1; |
||
43 | return 0; |
||
44 | } |
||
14712 | bpr | 45 | if(_sort_nocase) return mystrcmp(pp1->str,pp2->str); |
12228 | bpr | 46 | else return strcmp(pp1->str,pp2->str); |
10 | reyssat | 47 | } |
48 | |||
49 | int _char_sorter(const void *c1, const void *c2) |
||
50 | { |
||
12228 | bpr | 51 | if(_sort_nocase) return tolower(*(char *)c1)-tolower(*(char *)c2); |
52 | else return *(char *)c1-*(char *)c2; |
||
10 | reyssat | 53 | } |
54 | |||
55 | enum {sort_char, sort_word, sort_item, sort_line, sort_row, |
||
56 | sort_numeric, sort_nocase, sort_reverse |
||
57 | }; |
||
58 | struct {char *name; int type; |
||
59 | } sort_keyw[]={ |
||
12228 | bpr | 60 | {"char",sort_char}, |
61 | {"chars",sort_char}, |
||
62 | {"character",sort_char}, |
||
63 | {"characters",sort_char}, |
||
64 | {"word",sort_word}, |
||
65 | {"words",sort_word}, |
||
66 | {"item",sort_item}, |
||
67 | {"items",sort_item}, |
||
68 | {"line",sort_line}, |
||
69 | {"lines",sort_line}, |
||
70 | {"list",sort_item}, |
||
71 | {"numeric",sort_numeric}, |
||
72 | {"numerical",sort_numeric}, |
||
73 | {"nocase",sort_nocase}, |
||
74 | {"ignorecase",sort_nocase}, |
||
75 | {"reverse",sort_reverse}, |
||
76 | {"row",sort_row}, |
||
77 | {"rows",sort_row} |
||
10 | reyssat | 78 | }; |
79 | #define sort_keyw_no (sizeof(sort_keyw)/sizeof(sort_keyw[0])) |
||
80 | |||
7673 | bpr | 81 | /* string sort */ |
10 | reyssat | 82 | void calc_sort(char *p) |
83 | { |
||
12228 | bpr | 84 | char *p1, *p2, buf[MAX_LINELEN+1], *csep[MAX_SORT_ITEM+1]; |
85 | char fs=0; |
||
86 | int (*cutfn)(char *p,char *list[],int max); |
||
87 | int nocase=0, reverse=0, numeric=0, type; |
||
88 | int i,j,l,t,total; |
||
7404 | bpr | 89 | |
12228 | bpr | 90 | cutfn=NULL; |
91 | for(i=0,p1=find_word_start(p);i>=0;p1=find_word_start(p2)) { |
||
92 | p2=find_word_end(p1); |
||
93 | if(*p2!=0) *p2++=0; |
||
94 | for(i=0;i<sort_keyw_no && strcasecmp(p1,sort_keyw[i].name)!=0;i++); |
||
95 | if(i>=sort_keyw_no) module_error("syntax_error"); |
||
96 | switch(type=sort_keyw[i].type) { |
||
97 | case sort_nocase: nocase=1; break; |
||
98 | case sort_reverse: reverse=1; break; |
||
99 | case sort_numeric: numeric=1; break; |
||
100 | case sort_char: i=-1; break; |
||
101 | case sort_word: cutfn=cutwords; fs=' '; i=-1; break; |
||
102 | case sort_item: cutfn=cutitems; fs=','; i=-1; break; |
||
103 | case sort_row: |
||
104 | case sort_line: cutfn=cutlines; fs='\n'; i=-1; break; |
||
10 | reyssat | 105 | } |
12228 | bpr | 106 | } |
107 | if(p1[0]=='o' && p1[1]=='f' && myisspace(p1[2])) p1=find_word_start(p1+2); |
||
108 | mystrncpy(buf,p1,sizeof(buf)); substit(buf); *p=0; |
||
109 | t=0; if(type==sort_row) t=rows2lines(buf); |
||
110 | _sort_nocase=nocase; _sort_numeric=numeric; |
||
111 | if(cutfn) { |
||
112 | char ordbuf[MAX_LINELEN+1]; |
||
113 | total=cutfn(buf,csep,MAX_SORT_ITEM+1); |
||
114 | if(total<=0 || total>MAX_SORT_ITEM) return; |
||
115 | for(i=0;i<total;i++) { |
||
116 | sort_sep[i].str=csep[i]; |
||
117 | if(numeric) sort_sep[i].val=evalue(csep[i]); |
||
118 | } |
||
119 | for(i=0;i<total;i++) sort_sep[i].serial=i+1; |
||
120 | qsort(sort_sep,total,sizeof(sort_sep[0]),__sorter); |
||
121 | p1=p;p2=ordbuf;ordbuf[0]=0; |
||
122 | for(i=0;i<total;i++) { |
||
123 | if(reverse) j=total-1-i; else j=i; |
||
124 | l=strlen(sort_sep[j].str); |
||
125 | if(p1-p+l>=MAX_LINELEN-1) module_error("cmd_output_too_long"); |
||
126 | if(p1>p) *p1++=fs; |
||
7673 | bpr | 127 | memmove(p1,sort_sep[j].str,l+1); p1+=l; |
12228 | bpr | 128 | if(i>0) *p2++=','; |
129 | mystrncpy(p2,int2str(sort_sep[j].serial), |
||
130 | MAX_LINELEN-(p2-ordbuf)-1); |
||
131 | p2+=strlen(p2); |
||
10 | reyssat | 132 | } |
12228 | bpr | 133 | force_setvar("wims_sort_order",ordbuf); |
134 | } |
||
135 | else { /* case of chars */ |
||
136 | qsort(buf,strlen(buf),1,_char_sorter); |
||
137 | total=strlen(buf); |
||
138 | if(reverse) { |
||
139 | for(i=total-1;i>=0;i--) *(p+total-i-1)=buf[i]; |
||
140 | *(p+total)=0; |
||
10 | reyssat | 141 | } |
12228 | bpr | 142 | else memmove(p,buf,total+1); |
143 | } |
||
144 | if(t) lines2rows(p); |
||
10 | reyssat | 145 | } |
146 | |||
7673 | bpr | 147 | /* Print a debug output */ |
10 | reyssat | 148 | void calc_debug(char *p) |
149 | { |
||
12228 | bpr | 150 | secure_exec(); setvar("debug",p); module_error("debug"); |
10 | reyssat | 151 | } |
152 | |||
7673 | bpr | 153 | /* execute a command thru wimslogd */ |
10 | reyssat | 154 | void calc_daemon(char *p) |
155 | { |
||
12228 | bpr | 156 | if(!trusted_module() || is_class_module) {*p=0; return;} |
157 | _daemoncmd(p); |
||
10 | reyssat | 158 | } |
159 | |||
160 | void _get_exec_error(char *errorfname, char *cmdname) |
||
161 | { |
||
12228 | bpr | 162 | char *p2; |
163 | char obuf[MAX_LINELEN+1]; |
||
164 | int l; |
||
165 | if(errorfname) accessfile(obuf,"e","%s",errorfname); |
||
166 | else { |
||
167 | l=read(mxtab[multiexec_index].pipe_stderr[0],obuf,MAX_LINELEN/4); |
||
168 | if(l<0 || l>MAX_LINELEN) l=0; |
||
169 | obuf[l]=0; |
||
170 | } |
||
171 | if(obuf[0]) { |
||
172 | p2=find_word_end(obuf); |
||
173 | if((manageable<1 || strcasecmp(tmp_debug,"yes")!=0) && |
||
174 | !trusted_module() && |
||
7673 | bpr | 175 | strncmp(p2," not_INStalled",strlen(" not_INStalled"))==0) { |
12228 | bpr | 176 | *p2=0; setvar("missing_software",obuf); |
177 | snprintf(p2+1,MAX_LINELEN-strlen(obuf)-8,"missing_%s",obuf); |
||
178 | if(!outputing) user_error(p2+1); |
||
10 | reyssat | 179 | } |
12228 | bpr | 180 | p2=getvar("wims_exec_error"); if(p2==NULL) p2=""; |
181 | snprintf(tmplbuf,sizeof(tmplbuf),"%s\nERROR from %s:\n%s",p2,cmdname,obuf); |
||
182 | force_setvar("wims_exec_error",tmplbuf); |
||
183 | } |
||
10 | reyssat | 184 | } |
185 | |||
8155 | bpr | 186 | /* execute an external program |
187 | * The output of the external program should be put into |
||
188 | * a file session_directory/session/cmd.tmp. |
||
189 | */ |
||
10 | reyssat | 190 | void calc_exec(char *p) |
191 | { |
||
12228 | bpr | 192 | int i,j,k; |
193 | char *cmd, *parm, *pp; |
||
194 | char namebuf[MAX_EXEC_NAME+1], cmdstr[MAX_LINELEN+256], obuf[MAX_LINELEN+1]; |
||
195 | char outfname[MAX_FNAME+1], errorfname[MAX_FNAME+1], |
||
196 | typefname[MAX_FNAME+1], varfname[MAX_FNAME+1]; |
||
197 | char *abuf[2]={NULL,NULL}; |
||
198 | WORKING_FILE wf; |
||
199 | if(robot_access || time(0)>=limtimex-1) { |
||
200 | *p=0;return; |
||
201 | } |
||
202 | cmd=find_word_start(p); if(*cmd==0) return; /* No command. */ |
||
203 | parm=find_word_end(cmd);j=parm-cmd;parm=find_word_start(parm); |
||
204 | if(j>MAX_EXEC_NAME) { |
||
205 | wrong_command: |
||
206 | setvar(error_data_string,namebuf); module_error("bad_cmd"); |
||
207 | *p=0; return; /* should not occur */ |
||
208 | } |
||
209 | memmove(namebuf,cmd,j); namebuf[j]=0; |
||
7673 | bpr | 210 | /* Specifying parent directory in command name is of course |
211 | * prohibited. |
||
212 | * The module developper cannot start from root, for bin_dir |
||
8155 | bpr | 213 | * will be prefixed to cmd. |
214 | */ |
||
12228 | bpr | 215 | if(strstr(namebuf,parent_dir_string)!=NULL) { |
216 | setvar(error_data_string,namebuf); module_error("illegal_cmd"); |
||
217 | *p=0; return; |
||
218 | } |
||
219 | snprintf(cmdstr,sizeof(cmdstr),"%s/%s",bin_dir,namebuf); |
||
220 | if(ftest(cmdstr)!=is_exec) goto wrong_command; |
||
221 | abuf[0]=cmdstr; |
||
222 | mkfname(outfname,"%s/exec.out",tmp_dir); |
||
223 | mkfname(errorfname,"%s/exec.err",tmp_dir); |
||
224 | mkfname(typefname,"%s/exec.type",tmp_dir); |
||
225 | unlink(typefname); |
||
226 | mkfname(varfname,"%s/exec.var",tmp_dir); |
||
227 | unlink(varfname); |
||
228 | if(!trusted_module()) setenv("untrust","yes",1); else unsetenv("untrust"); |
||
229 | if(strcmp(parm,"about")!=0 && multiexec(namebuf,abuf)) { |
||
230 | fd_set rset; |
||
231 | struct timeval t; |
||
232 | int v1, v2, fd; |
||
7404 | bpr | 233 | |
12228 | bpr | 234 | i=strlen(parm); |
235 | fd=mxtab[multiexec_index].pipe_stdin[1]; |
||
236 | (void)write(fd,parm,i); |
||
237 | (void)write(fd,multiexec_random,strlen(multiexec_random)); |
||
238 | *p=0; i=0; k=MAX_LINELEN; fd=mxtab[multiexec_index].pipe_stdout[0]; |
||
239 | while(k>0) { |
||
240 | FD_ZERO(&rset); FD_SET(fd,&rset); |
||
241 | t.tv_sec=0; t.tv_usec=100000; v1=0; v2=300; /* 3 seconds */ |
||
242 | if(select(fd+1,&rset,NULL,NULL,&t)<=0) { |
||
243 | v1++; if(v1>=v2) break; |
||
244 | else continue; |
||
245 | } |
||
246 | j=read(fd,p+i,k); |
||
247 | if(j<0 || j>k) break; |
||
248 | i+=j; k-=j; p[i]=0; |
||
249 | pp=strstr(p,multiexec_random); |
||
250 | if(pp) {*pp=0; break;} |
||
10 | reyssat | 251 | } |
12228 | bpr | 252 | fd=mxtab[multiexec_index].pipe_stderr[0]; |
253 | FD_ZERO(&rset); FD_SET(fd,&rset); |
||
254 | t.tv_sec=0; t.tv_usec=0; |
||
255 | if(select(fd+1,&rset,NULL,NULL,&t)>0) |
||
256 | _get_exec_error(NULL,namebuf); |
||
257 | strip_trailing_spaces(p); |
||
258 | return; |
||
259 | } |
||
260 | exportall(); setenv("wims_exec_parm",parm,1); |
||
261 | execredirected(cmdstr,NULL,outfname,errorfname,abuf); |
||
262 | if(open_working_file(&wf,varfname)==0) { |
||
263 | char *pt, *pv; |
||
264 | while(wgetline(tmplbuf,MAX_LINELEN, &wf)!=EOF) { |
||
265 | pt=find_word_start(tmplbuf); pv=strchr(pt,'='); |
||
266 | if(pv==NULL || pv<=tmplbuf) continue; |
||
267 | *pv=0; pv=find_word_start(++pv); |
||
268 | *find_word_end(pt)=0; |
||
269 | strip_trailing_spaces(pv); |
||
270 | setvar(pt,pv); |
||
10 | reyssat | 271 | } |
12228 | bpr | 272 | close_working_file(&wf,0); |
273 | } |
||
274 | read_tmp_file(p,"exec.out"); |
||
275 | read_tmp_file(obuf,"exec.type"); |
||
276 | if(obuf[0]) k=atoi(obuf); else k=0; |
||
277 | for(i=2;i<=k && i<256;i++) { |
||
278 | char nbuf[32]; |
||
279 | snprintf(nbuf,sizeof(nbuf),"exec.out.%d",i); |
||
280 | read_tmp_file(obuf,nbuf); |
||
281 | if(obuf[0]) { |
||
282 | snprintf(nbuf,sizeof(nbuf),"wims_exec_out_%d",i); |
||
283 | force_setvar(nbuf,obuf); |
||
10 | reyssat | 284 | } |
12228 | bpr | 285 | } |
286 | strip_trailing_spaces(p); |
||
287 | _get_exec_error(errorfname,namebuf); |
||
288 | return; |
||
10 | reyssat | 289 | } |
290 | |||
7673 | bpr | 291 | /* execute external program in the module directory. |
8155 | bpr | 292 | * For privileged modules only |
293 | */ |
||
10 | reyssat | 294 | void calc_mexec(char *p) |
295 | { |
||
12228 | bpr | 296 | char *public_bin; |
297 | if(robot_access) return; |
||
298 | if(trusted_module()!=1 || is_class_module) { |
||
299 | module_error("not_trusted"); *p=0; return; |
||
300 | } |
||
7673 | bpr | 301 | /* The following is useless, because mexec content is often given |
8155 | bpr | 302 | * by variables |
303 | */ |
||
10 | reyssat | 304 | /* if(strstr(p,PARENT_DIR_STRING)!=NULL) { |
7673 | bpr | 305 | setvar("wims_error_data",p); |
306 | module_error("illegal_fname"); *p=0; return; |
||
10 | reyssat | 307 | } |
308 | */ public_bin=bin_dir; bin_dir=module_prefix; |
||
12228 | bpr | 309 | exec_is_module=1; |
310 | calc_exec(p); bin_dir=public_bin; |
||
311 | exec_is_module=0; |
||
10 | reyssat | 312 | } |
313 | |||
314 | void _calc_exec(char *p, char *arg0, char *arg1, int n) |
||
315 | { |
||
12228 | bpr | 316 | char *abuf[8]; |
317 | char outfname[MAX_FNAME+1], errorfname[MAX_FNAME+1]; |
||
10 | reyssat | 318 | |
12228 | bpr | 319 | if(robot_access) {*p=0; return;} |
320 | if(!trusted_module() || is_class_module) { |
||
321 | if(strcasecmp(tmp_debug,"yes")==0) |
||
322 | accessfile(p,"w","%s/%s.cmd",tmp_dir,arg0); |
||
323 | abuf[0]="bin/ch..root"; |
||
324 | abuf[1]="&"; abuf[2]=arg0; abuf[3]=p; |
||
325 | abuf[4]=NULL; |
||
326 | } |
||
327 | else { |
||
7673 | bpr | 328 | /* if(strstr(p,PARENT_DIR_STRING)!=NULL) { |
329 | setvar("wims_error_data",p); |
||
330 | module_error("illegal_fname"); *p=0; return; |
||
331 | } |
||
332 | */ |
||
333 | abuf[0]=arg0; abuf[1]=arg1; abuf[n]=p; abuf[n+1]=NULL; |
||
12228 | bpr | 334 | } |
335 | mkfname(outfname,"%s/exec.out",tmp_dir); |
||
336 | mkfname(errorfname,"%s/exec.err",tmp_dir); |
||
337 | wrapexec=1; exportall(); |
||
338 | execredirected(abuf[0],NULL,outfname,errorfname,abuf); |
||
339 | read_tmp_file(p,"exec.out"); |
||
340 | _get_exec_error(errorfname,arg0); |
||
10 | reyssat | 341 | } |
342 | |||
7673 | bpr | 343 | /* call shell. */ |
10 | reyssat | 344 | void calc_sh(char *p) |
345 | { |
||
12228 | bpr | 346 | _calc_exec(p,"sh","-c",2); |
10 | reyssat | 347 | } |
348 | |||
7673 | bpr | 349 | /* call perl. */ |
10 | reyssat | 350 | void calc_perl(char *p) |
351 | { |
||
12228 | bpr | 352 | _calc_exec(p,"perl","-e",2); |
10 | reyssat | 353 | } |
354 | |||
7673 | bpr | 355 | /* simple evaluation of string */ |
10 | reyssat | 356 | void calc_evalue(char *p) |
357 | { |
||
12228 | bpr | 358 | double d; |
359 | d=evalue(p); float2str(d,p); return; |
||
10 | reyssat | 360 | } |
361 | |||
7673 | bpr | 362 | /* substitute math variables */ |
10 | reyssat | 363 | void calc_mathsubst(char *p) |
364 | { |
||
12228 | bpr | 365 | char *expr, *val, *nam, *pp; |
366 | char buf[MAX_LINELEN+1]; |
||
367 | expr=wordchr(p,"in"); if(expr==NULL) goto error; |
||
368 | ovlstrcpy(buf,find_word_start(expr+strlen("in")));substit(buf); |
||
369 | *expr=0; substit(p); |
||
370 | val=strchr(p,'='); |
||
371 | if(val==NULL) { |
||
372 | error: |
||
373 | module_error("mathsubst_syntax"); *p=0;return; |
||
374 | } |
||
375 | nam=find_word_start(p); *val=0; |
||
376 | val=find_word_start(val+1); |
||
377 | for(pp=val+strlen(val)-1;pp>=val && isspace(*pp);*pp--=0); |
||
378 | *find_word_end(nam)=0; |
||
379 | if(*nam==0) goto error; |
||
380 | if(*nam) for(pp=varchr(buf,nam);pp!=NULL;pp=varchr(pp,nam)) { |
||
381 | string_modify(buf,pp,pp+strlen(nam),"%s",val); |
||
382 | pp+=strlen(val); |
||
383 | } |
||
384 | ovlstrcpy(p,buf); |
||
10 | reyssat | 385 | } |
386 | |||
7673 | bpr | 387 | /* substitute and evaluate. */ |
10 | reyssat | 388 | void calc_evalsubst(char *p) |
389 | { |
||
12228 | bpr | 390 | calc_mathsubst(p); |
391 | calc_evalue(p); |
||
10 | reyssat | 392 | } |
393 | |||
7673 | bpr | 394 | /* Nothing needs to be done in the function; |
8155 | bpr | 395 | * substitution is done or not by tag in the structure. |
396 | */ |
||
10 | reyssat | 397 | void calc_subst(char *p) |
398 | { |
||
399 | } |
||
400 | |||
401 | int _randrep(char *p) |
||
402 | { |
||
12228 | bpr | 403 | char *rep; |
404 | int i; |
||
405 | rep=wordchr(p,"repeat"); if(rep==NULL) return 1; |
||
406 | *rep=0; rep+=strlen("repeat"); i=evalue(rep); |
||
407 | if(i<1) i=1; |
||
408 | if(i>MAX_VALUE_LIST) i=MAX_VALUE_LIST; |
||
409 | return i; |
||
10 | reyssat | 410 | } |
411 | |||
7673 | bpr | 412 | /* integer random */ |
10 | reyssat | 413 | void calc_randint(char *p) |
414 | { |
||
12228 | bpr | 415 | int lbound, ubound, n, i, t; |
416 | char *p1, *parm[2]; |
||
10 | reyssat | 417 | |
12228 | bpr | 418 | t=_randrep(p); n=cutitems(p,parm,2); |
419 | if(n<=0) { |
||
420 | snprintf(p,3,"0"); return; /* Random without bound: return 0. */ |
||
421 | } |
||
422 | lbound=evalue(parm[0]); |
||
7673 | bpr | 423 | /* Missing ubound: random between +-1 and lbound. */ |
12228 | bpr | 424 | if(n<=1) {if(lbound<0) ubound=-1; else ubound=1;} |
425 | else ubound=evalue(parm[1]); |
||
426 | if(lbound>ubound) {i=lbound; lbound=ubound; ubound=i;} |
||
427 | for(i=0,p1=p;i<t;i++) { |
||
428 | if(i>0) *p1++=','; |
||
429 | mystrncpy(p1,int2str((int) irand(ubound-lbound+1)+lbound), |
||
7673 | bpr | 430 | MAX_LINELEN-(p1-p)-1); |
12228 | bpr | 431 | p1+=strlen(p1); |
432 | } |
||
433 | return; |
||
10 | reyssat | 434 | } |
435 | |||
7673 | bpr | 436 | /* floating random */ |
10 | reyssat | 437 | void calc_randdouble(char *p) |
438 | { |
||
12228 | bpr | 439 | double lbound, ubound; |
440 | int n, i, t; |
||
441 | char *parm[2], *p1; |
||
7404 | bpr | 442 | |
12228 | bpr | 443 | t=_randrep(p); n=cutitems(p,parm,2); |
444 | if(n<=0) { |
||
445 | snprintf(p,3,"0"); return; /* Random without bound: return 0. */ |
||
446 | } |
||
447 | lbound=evalue(parm[0]); |
||
448 | if(n<=1) ubound=0; /* Missing ubound: random between 0 and lbound. */ |
||
449 | else ubound=evalue(parm[1]); |
||
450 | for(i=0,p1=p;i<t;i++) { |
||
451 | float2str(drand(ubound-lbound)+lbound,tmplbuf); |
||
452 | mystrncpy(p1,tmplbuf,MAX_LINELEN-(p1-p)); |
||
453 | p1+=strlen(p1); |
||
454 | if(i<t-1 && p1-p<MAX_LINELEN) *p1++=','; |
||
455 | } |
||
456 | *p1=0; return; |
||
10 | reyssat | 457 | } |
458 | |||
7673 | bpr | 459 | /* Takes randomly a record in a datafile */ |
10 | reyssat | 460 | void calc_randfile(char *p) |
461 | { |
||
12228 | bpr | 462 | char *pp, n[MAX_FNAME+1]; |
463 | int i, j; |
||
7404 | bpr | 464 | |
12228 | bpr | 465 | pp=find_word_start(p); *find_word_end(pp)=0; |
466 | mystrncpy(n,pp,sizeof(n)); |
||
467 | i=datafile_recordnum(pp); |
||
468 | if(i<=0) { /* zero records */ |
||
469 | *p=0; return; |
||
470 | } |
||
471 | j=irand(i); datafile_fnd_record(n,j+1,p); |
||
472 | return; |
||
10 | reyssat | 473 | } |
474 | |||
7673 | bpr | 475 | /* random char, word, line, item in a string */ |
10 | reyssat | 476 | void calc_randchar(char *p) |
477 | { |
||
12228 | bpr | 478 | p[0]=p[(int) irand(strlen(p))];p[1]=0; |
10 | reyssat | 479 | } |
480 | |||
481 | void calc_randitem(char *p) |
||
482 | { |
||
12228 | bpr | 483 | int i; |
484 | i=itemnum(p); |
||
485 | (void) fnd_item(p,irand(i)+1,tmplbuf); |
||
486 | mystrncpy(p,tmplbuf,MAX_LINELEN); |
||
10 | reyssat | 487 | } |
488 | |||
489 | void calc_randline(char *p) |
||
490 | { |
||
12228 | bpr | 491 | int i; |
492 | i=linenum(p); fnd_line(p,irand(i)+1,tmplbuf); |
||
493 | mystrncpy(p,tmplbuf,MAX_LINELEN); |
||
10 | reyssat | 494 | } |
495 | |||
496 | void calc_randrow(char *p) |
||
497 | { |
||
12228 | bpr | 498 | rows2lines(p); calc_randline(p); |
10 | reyssat | 499 | } |
500 | |||
501 | void calc_randword(char *p) |
||
502 | { |
||
12228 | bpr | 503 | int i; |
504 | i=wordnum(p); fnd_word(p,irand(i)+1,tmplbuf); |
||
505 | mystrncpy(p,tmplbuf,MAX_LINELEN); |
||
10 | reyssat | 506 | } |
507 | |||
7673 | bpr | 508 | /* random permutation of {1,...,n} */ |
10 | reyssat | 509 | void calc_randperm(char *p) |
510 | { |
||
12228 | bpr | 511 | int n, i, j, k, t, pt, type; |
512 | double v; |
||
513 | char buf1[MAX_LINELEN+1],buf2[MAX_LINELEN+1]; |
||
514 | char *list[MAX_RANDPERM]; |
||
515 | int table[MAX_RANDPERM]; |
||
516 | char *p1,*p2,*pp; |
||
7404 | bpr | 517 | |
12228 | bpr | 518 | t=0; pt=0; pp=p; |
519 | p1=find_word_start(p); p2=find_word_end(p1); |
||
520 | if(p2-p1==strlen("even") && strncasecmp(p1,"even",strlen("even"))==0) { |
||
521 | t=1; pp=p2; |
||
522 | } |
||
523 | if(p2-p1==strlen("odd") && strncasecmp(p1,"odd",strlen("odd"))==0) { |
||
524 | t=-1; pp=p2; |
||
525 | } |
||
7404 | bpr | 526 | |
12228 | bpr | 527 | p1=find_item_end(pp); |
528 | if(*p1==',') { |
||
529 | type=1; n=cutitems(pp,list,MAX_RANDPERM); v=0; |
||
530 | } |
||
531 | else { |
||
532 | v=evalue(pp); n=v; type=0; |
||
533 | } |
||
534 | if(n==1 && !isfinite(v)) {ovlstrcpy(p,pp); goto shorder;} |
||
535 | if(n<=0) {*p=0; return;} |
||
536 | if(n==1 && type==0) { |
||
537 | ovlstrcpy(p,"1"); |
||
538 | shorder: force_setvar("wims_shuffle_order","1"); return; |
||
539 | } |
||
540 | if(n>MAX_RANDPERM) n=MAX_RANDPERM; |
||
541 | for(i=0;i<n;i++) table[i]=i; |
||
8155 | bpr | 542 | /* Uniformity of this algorithm is easy to show by induction. */ |
12228 | bpr | 543 | for(i=0;i<n-1;i++) { |
544 | j=irand(n-i)+i; if(j==i) continue; |
||
545 | k=table[i]; table[i]=table[j]; table[j]=k; |
||
546 | pt++; |
||
547 | } |
||
548 | pt&=1; |
||
549 | if((t==1 && pt==1) || (t==-1 && pt==0)) { |
||
550 | k=table[0]; table[0]=table[1]; table[1]=k; |
||
551 | } |
||
552 | if(type) {mystrncpy(buf1,list[table[0]],MAX_LINELEN); p1=buf1+strlen(buf1);} |
||
553 | else buf1[0]=0; |
||
554 | mystrncpy(buf2,int2str(table[0]+1),MAX_LINELEN); p2=buf2+strlen(buf2); |
||
555 | for(i=1;i<n;i++) { |
||
556 | if(type) { |
||
557 | j=strlen(list[table[i]]); |
||
558 | if(p1-buf1+j>=MAX_LINELEN-1) module_error("cmd_output_too_long"); |
||
559 | *p1++=','; memmove(p1,list[table[i]],j+1); p1+=j; |
||
10 | reyssat | 560 | } |
12228 | bpr | 561 | *p2++=','; |
562 | mystrncpy(p2,int2str(table[i]+1), MAX_LINELEN-(p2-buf2)-1); |
||
563 | p2+=strlen(p2); |
||
564 | } |
||
565 | if(type) mystrncpy(p,buf1,MAX_LINELEN); |
||
566 | else mystrncpy(p,buf2,MAX_LINELEN); |
||
567 | force_setvar("wims_shuffle_order",buf2); |
||
10 | reyssat | 568 | } |
569 | |||
7673 | bpr | 570 | /* Computes number of lines in the parm. */ |
10 | reyssat | 571 | void calc_linenum(char *p) |
572 | { |
||
12228 | bpr | 573 | int i=linenum(p); mystrncpy(p,int2str(i),MAX_LINELEN); |
10 | reyssat | 574 | } |
575 | |||
7673 | bpr | 576 | /* Computes number of lines in the parm. */ |
10 | reyssat | 577 | void calc_rownum(char *p) |
578 | { |
||
12228 | bpr | 579 | int i=rownum(p); mystrncpy(p,int2str(i),MAX_LINELEN); |
10 | reyssat | 580 | } |
581 | |||
7673 | bpr | 582 | /* Computes number of items in the list p. */ |
10 | reyssat | 583 | void calc_itemnum(char *p) |
584 | { |
||
12228 | bpr | 585 | int i=itemnum(p); mystrncpy(p,int2str(i),MAX_LINELEN); |
10 | reyssat | 586 | } |
587 | |||
7673 | bpr | 588 | /* Computes number of records in the datafile p. */ |
10 | reyssat | 589 | void calc_recordnum(char *p) |
590 | { |
||
12228 | bpr | 591 | int i; |
592 | i=datafile_recordnum(p); mystrncpy(p,int2str(i),MAX_LINELEN); |
||
10 | reyssat | 593 | } |
594 | |||
7673 | bpr | 595 | /* Computes number of words in the parm. */ |
10 | reyssat | 596 | void calc_wordnum(char *p) |
597 | { |
||
12228 | bpr | 598 | int i=wordnum(p); mystrncpy(p,int2str(i),MAX_LINELEN); |
10 | reyssat | 599 | } |
600 | |||
7673 | bpr | 601 | /* string length */ |
10 | reyssat | 602 | void calc_lengthof(char *p) |
603 | { |
||
12228 | bpr | 604 | int i; |
7404 | bpr | 605 | /* Strip leading and trailing spaces? */ |
12228 | bpr | 606 | i=strlen(p); mystrncpy(p,int2str(i),MAX_LINELEN); |
10 | reyssat | 607 | } |
608 | |||
609 | char *_blockof_one(char *buf, |
||
7673 | bpr | 610 | unsigned int len, |
611 | char *(fnd_fn)(char *pl, int n, char bbuf[]), |
||
612 | int i, char bbuf[]) |
||
10 | reyssat | 613 | { |
12228 | bpr | 614 | if(i<0 || i>len || (i==0 && fnd_fn!=datafile_fnd_record) ) { |
615 | bbuf[0]=0; return bbuf; |
||
616 | } |
||
617 | return fnd_fn(buf,i,bbuf); |
||
10 | reyssat | 618 | } |
619 | |||
620 | void _blockof(char *p, |
||
7673 | bpr | 621 | unsigned int (len_fn)(char *pl), |
622 | char *(fnd_fn)(char *pl, int n, char bbuf[]), |
||
623 | char *append_char, |
||
624 | char *msg_str) |
||
10 | reyssat | 625 | { |
12228 | bpr | 626 | int i,j,l,started; |
627 | char *pp, *pe, *po, *pnext; |
||
628 | char buf[MAX_LINELEN+1], obuf[MAX_LINELEN+1], bbuf[MAX_LINELEN+1]; |
||
629 | pp=wordchr(p,"of"); |
||
630 | if(pp==NULL) { |
||
631 | setvar(error_data_string,msg_str); |
||
632 | module_error("no_of"); *p=0; return; |
||
633 | } |
||
634 | *pp=0; pp=find_word_start(pp+strlen("of")+1); |
||
635 | mystrncpy(buf,pp,sizeof(buf)); substit(buf); |
||
636 | obuf[0]=0; started=0; po=obuf; |
||
637 | pp=strparstr(p,"to"); |
||
638 | while(*pp!=0 && ((pp>p && !isspace(*(pp-1))) || !isspace(*(pp+2)))) |
||
639 | pp=strparstr(pp+2,"to"); |
||
640 | if(*pp==0) pp=strparstr(p,".."); |
||
641 | if(*pp!=0) { |
||
642 | int t=len_fn(buf); |
||
643 | *pp=0; pe=find_word_start(pp+2); |
||
644 | i=evalue(p); j=evalue(pe); pnext=buf; |
||
645 | if(i<0) i=t+i+1; |
||
646 | if(i<1) i=1; |
||
647 | if(j<0) j=t+j+1; |
||
648 | if(j>t) j=t; |
||
649 | for(; i<=j; i++) { |
||
650 | if(started==0 || fnd_fn==datafile_fnd_record) |
||
651 | pp=_blockof_one(buf,t,fnd_fn,i,bbuf); |
||
652 | else |
||
653 | pp=_blockof_one(pnext,1,fnd_fn,1,bbuf); |
||
654 | l=strlen(pp); pnext=fnd_nextpos; |
||
655 | if(l+(po-obuf)>=MAX_LINELEN-3) { |
||
656 | too_long: user_error("cmd_output_too_long"); return; |
||
657 | } |
||
658 | if(started) {ovlstrcpy(po,append_char); po+=strlen(po);} |
||
659 | memmove(po,pp,l); po+=l; *po=0; started++; |
||
10 | reyssat | 660 | } |
12228 | bpr | 661 | } |
662 | else { |
||
663 | char *p1,*p2,ibuf[MAX_LINELEN+1]; |
||
664 | int t=len_fn(buf); |
||
665 | mystrncpy(ibuf,p,sizeof(ibuf)); substit(ibuf); |
||
666 | for(p1=ibuf;*p1;p1=find_word_start(p2)) { |
||
667 | p2=find_item_end(p1); if(*p2) *p2++=0; |
||
668 | i=evalue(p1); |
||
669 | if(i<0) i=t+i+1; |
||
670 | if(i>t || i<0) continue; |
||
671 | pp=_blockof_one(buf,t,fnd_fn,i,bbuf);l=strlen(pp); |
||
672 | if(l+(po-obuf)>=MAX_LINELEN-3) goto too_long; |
||
673 | if(started) {ovlstrcpy(po,append_char); po+=strlen(po);} |
||
674 | memmove(po,pp,l); po+=l; *po=0; started++; |
||
10 | reyssat | 675 | } |
12228 | bpr | 676 | } |
677 | mystrncpy(p,obuf,MAX_LINELEN); |
||
10 | reyssat | 678 | } |
679 | |||
7673 | bpr | 680 | /* pick lines */ |
10 | reyssat | 681 | void calc_lineof(char *p) |
682 | { |
||
12228 | bpr | 683 | _blockof(p,linenum,fnd_line,"\n","line"); |
10 | reyssat | 684 | } |
685 | |||
7673 | bpr | 686 | /* pick rows */ |
10 | reyssat | 687 | void calc_rowof(char *p) |
688 | { |
||
12228 | bpr | 689 | char *cc, tbuf[MAX_LINELEN+1]; /* called by substit(); no right to use tmplbuf */ |
690 | mystrncpy(tbuf,p,sizeof(tbuf)); substit(tbuf); |
||
691 | if(strchr(tbuf,'\n')==NULL && strchr(tbuf,';')!=NULL) cc=";"; |
||
692 | else cc="\n"; |
||
693 | _blockof(p,rownum,fnd_row,cc,"row"); |
||
10 | reyssat | 694 | } |
695 | |||
7673 | bpr | 696 | /* pick items */ |
10 | reyssat | 697 | void calc_itemof(char *p) |
698 | { |
||
12228 | bpr | 699 | _blockof(p,itemnum,fnd_item,", ","item"); |
10 | reyssat | 700 | } |
701 | |||
7673 | bpr | 702 | /* pick records in datafile */ |
10 | reyssat | 703 | void calc_recordof(char *p) |
704 | { |
||
12228 | bpr | 705 | _blockof(p,datafile_recordnum,datafile_fnd_record,"\n:","record"); |
10 | reyssat | 706 | } |
707 | |||
7673 | bpr | 708 | /* pick words */ |
10 | reyssat | 709 | void calc_wordof(char *p) |
710 | { |
||
12228 | bpr | 711 | _blockof(p,wordnum,fnd_word," ","word"); |
10 | reyssat | 712 | } |
713 | |||
7673 | bpr | 714 | /* pick characters */ |
10 | reyssat | 715 | void calc_charof(char *p) |
716 | { |
||
12228 | bpr | 717 | _blockof(p,charnum,fnd_char,"","char"); |
10 | reyssat | 718 | } |
719 | |||
720 | char *append_obj[]={ |
||
12228 | bpr | 721 | "item","line","word","semicolon","colon" |
10 | reyssat | 722 | }; |
9378 | schaersvoo | 723 | char apch_list[]={',','\n',' ',';',':'}; |
10 | reyssat | 724 | #define append_obj_no (sizeof(append_obj)/sizeof(append_obj[0])) |
725 | |||
7673 | bpr | 726 | /* append object to string */ |
10 | reyssat | 727 | void calc_append(char *p) |
728 | { |
||
12228 | bpr | 729 | char append_char, *p1,*p2,*p3,*p4; |
730 | int i,l1,l2; |
||
731 | p1=find_word_start(p);p2=find_word_end(p1); |
||
732 | if(*p2!=0) *p2++=0; |
||
733 | for(i=0;i<append_obj_no && strcmp(p1,append_obj[i])!=0;i++); |
||
734 | if(i>=append_obj_no) { |
||
735 | synterr: |
||
736 | module_error("append_syntax"); |
||
737 | *p=0; return; |
||
738 | } |
||
739 | append_char=apch_list[i]; |
||
740 | p3=wordchr(p2,"to"); |
||
741 | if(p3==NULL) goto synterr; |
||
742 | for(p4=p3-1;p4>p2 && isspace(*(p4-1));p4--); |
||
743 | if(p4<=p2) goto synterr; |
||
744 | *p4=0;p3=find_word_start(p3+strlen("to")); |
||
745 | memmove(tmplbuf,p2,p4-p2); tmplbuf[p4-p2]=0; ovlstrcpy(p,p3); |
||
746 | substit(tmplbuf);substit(p); |
||
747 | l1=strlen(p); l2=strlen(tmplbuf); |
||
748 | if(l1+l2>=MAX_LINELEN-1) user_error("cmd_output_too_long"); |
||
749 | p3=find_word_start(p); p4=p+l1; |
||
750 | if(*p3) *p4++=append_char; |
||
751 | memmove(p4,tmplbuf,l2); p4[l2]=0; |
||
10 | reyssat | 752 | } |
753 | |||
7673 | bpr | 754 | /* character translation */ |
10 | reyssat | 755 | void calc_translate(char *p) |
756 | { |
||
12228 | bpr | 757 | int i, internal; |
758 | char *q[3]; |
||
759 | char bf[3][MAX_LINELEN+1]; |
||
760 | char fn[3][MAX_FNAME+1], *arglist[8]; |
||
10 | reyssat | 761 | |
12228 | bpr | 762 | q[0]=find_word_start(p); internal=0; |
763 | if(strncasecmp(q[0],"internal",strlen("internal"))==0 && |
||
764 | isspace(*(q[0]+strlen("internal")))) { |
||
765 | q[0]=find_word_start(q[0]+strlen("internal")); |
||
766 | internal=1; |
||
767 | } |
||
768 | q[1]=wordchr(q[0],"to"); q[2]=wordchr(q[0],"in"); |
||
769 | if(q[1]==NULL || q[2]==NULL) { |
||
770 | module_error("tr_syntax"); *p=0; return; |
||
771 | } |
||
772 | *q[1]=0; *q[2]=0; |
||
773 | q[1]=find_word_start(q[1]+strlen("to")); |
||
774 | q[2]=find_word_start(q[2]+strlen("in")); |
||
775 | for(i=0;i<3;i++) { |
||
776 | strip_trailing_spaces(q[i]); |
||
777 | mystrncpy(bf[i],q[i],sizeof(bf[i]));substit(bf[i]); |
||
778 | } |
||
779 | if(bf[0][0]==0) goto bailout; |
||
780 | if(internal || strstr(tmp_dir,"sessions")==NULL || (strpbrk(bf[0],"\\[-")==NULL && |
||
781 | strpbrk(bf[1],"\\[-")==NULL)) { /* direct internal translation */ |
||
782 | char *pp; |
||
783 | if(strlen(bf[1])<strlen(bf[0])) bf[0][strlen(bf[1])]=0; |
||
784 | for(pp=strpbrk(bf[2],bf[0]);pp!=NULL && *pp!=0 && pp<bf[2]+MAX_LINELEN; |
||
785 | pp=strpbrk(pp+1,bf[0])) { |
||
786 | for(i=0;bf[0][i]!=*pp && bf[0][i]!=0;i++); |
||
787 | if(bf[0][i]!=0) *pp=bf[1][i]; |
||
10 | reyssat | 788 | } |
12228 | bpr | 789 | bailout: mystrncpy(p,bf[2],MAX_LINELEN); |
790 | return; |
||
791 | } |
||
792 | mkfname(fn[0],"%s/tr.in",tmp_dir); |
||
793 | mkfname(fn[1],"%s/tr.out",tmp_dir); |
||
794 | accessfile(bf[2],"w",fn[0]); |
||
795 | arglist[0]=tr_prog; arglist[1]=bf[0]; arglist[2]=bf[1]; |
||
796 | arglist[3]=NULL; exportall(); |
||
797 | execredirected(tr_prog,fn[0],fn[1],"/dev/null",arglist); |
||
798 | read_tmp_file(p,"tr.out"); |
||
799 | strip_trailing_spaces(p); |
||
10 | reyssat | 800 | } |
801 | |||
7673 | bpr | 802 | /* internal common routine for positionof */ |
10 | reyssat | 803 | void _pos(char *hay, char *stitch, int style, char *out, |
7673 | bpr | 804 | char *(fnd_obj)(char *p, int n, char bf[]), |
805 | unsigned int (objnum)(char *p)) |
||
10 | reyssat | 806 | { |
12228 | bpr | 807 | int i,n,t; |
15516 | bpr | 808 | char buf[MAX_LINELEN+1], nbuf[12]; |
7404 | bpr | 809 | |
12228 | bpr | 810 | n=objnum(hay); |
811 | for(i=1;i<=n;i++) { |
||
812 | fnd_obj(hay,i,buf); |
||
813 | if(strcmp(buf,stitch)!=0) continue; |
||
814 | t=strlen(out); if(t>MAX_LINELEN-12) return; |
||
815 | if(t>0) strcat(out,","); |
||
816 | snprintf(nbuf,sizeof(nbuf),"%d",i); strcat(out,nbuf); |
||
817 | } |
||
10 | reyssat | 818 | } |
819 | |||
7673 | bpr | 820 | /* return positions of searched for objects */ |
10 | reyssat | 821 | void calc_pos(char *p) |
822 | { |
||
12228 | bpr | 823 | char buf[2][MAX_LINELEN+1]; |
824 | char *p1, *p2; |
||
825 | int style; |
||
7404 | bpr | 826 | |
12228 | bpr | 827 | p1=find_word_start(p); p2=wordchr(p1,"in"); |
828 | if(p2==NULL) module_error("syntax_error"); |
||
829 | *p2=0;p2=find_word_start(p2+strlen("in")); |
||
830 | strip_trailing_spaces(p1); |
||
831 | ovlstrcpy(buf[0],p1);*find_word_end(buf[0])=0; style=0; |
||
832 | if(strcmp(buf[0],"word")==0) style=1; |
||
833 | else { |
||
834 | if(strcmp(buf[0],"item")==0) style=2; |
||
10 | reyssat | 835 | else { |
12228 | bpr | 836 | if(strcmp(buf[0],"line")==0) style=3; |
837 | else { |
||
838 | if(strcmp(buf[0],"char")==0) style=4; |
||
14711 | bpr | 839 | else { |
840 | if(strcmp(buf[0],"row")==0) style=5; |
||
841 | } |
||
12228 | bpr | 842 | } |
10 | reyssat | 843 | } |
12228 | bpr | 844 | } |
845 | if(style>0) p1=find_word_start(find_word_end(p1)); |
||
846 | ovlstrcpy(buf[0],p1); ovlstrcpy(buf[1],p2); |
||
847 | substit(buf[0]); substit(buf[1]); *p=0; |
||
848 | switch(style) { |
||
849 | case 0: { /* string */ |
||
850 | char *pp, nbuf[10]; |
||
851 | int i,t; |
||
852 | for(pp=strstr(buf[1],buf[0]);pp!=NULL;pp=strstr(pp+1,buf[0])) { |
||
853 | i=pp-buf[1]; t=strlen(p); if(t>MAX_LINELEN-12) return; |
||
854 | if(t>0) strcat(p,","); |
||
855 | snprintf(nbuf,sizeof(nbuf),"%d",i); strcat(p,nbuf); |
||
856 | } |
||
857 | return; |
||
10 | reyssat | 858 | } |
12228 | bpr | 859 | case 1: { /* word */ |
860 | _pos(buf[1],buf[0],style,p,fnd_word,wordnum); |
||
861 | return; |
||
862 | } |
||
863 | case 2: { /* item */ |
||
864 | _pos(buf[1],buf[0],style,p,fnd_item,itemnum); |
||
865 | return; |
||
866 | } |
||
867 | case 3: { /* line */ |
||
868 | _pos(buf[1],buf[0],style,p,fnd_line,linenum); |
||
869 | return; |
||
870 | } |
||
871 | case 4: { /* char */ |
||
872 | _pos(buf[1],buf[0],style,p,fnd_char,charnum); |
||
873 | return; |
||
874 | } |
||
14711 | bpr | 875 | case 5: { /* row */ |
876 | _pos(buf[1],buf[0],style,p,fnd_row,rownum); |
||
877 | return; |
||
878 | } |
||
12228 | bpr | 879 | } |
10 | reyssat | 880 | } |
881 | |||
7673 | bpr | 882 | /* internal routine for calc_replace. */ |
10 | reyssat | 883 | void _obj_replace(char *orig, char *by, char *in, int num, |
7673 | bpr | 884 | char separator, char *result, |
885 | char *(fnd_obj)(char *p, int n, char bf[]), |
||
886 | unsigned int (objnum)(char *p), |
||
887 | char *(objchr)(char *p,char *w)) |
||
10 | reyssat | 888 | { |
12228 | bpr | 889 | int i; |
890 | char *p1, *p2; |
||
7404 | bpr | 891 | |
12228 | bpr | 892 | ovlstrcpy(result,in); |
893 | if(num!=0) { |
||
894 | num=objnum(in); i=evalue(orig); |
||
895 | if(i==0) module_error("bad_index"); |
||
896 | if(i<0) i=num+i+1; |
||
897 | if(i>num || i<1) return; |
||
898 | if(separator==0) { /* char */ |
||
899 | result[i-1]=by[0]; return; |
||
10 | reyssat | 900 | } |
12228 | bpr | 901 | fnd_obj(result,i,orig); p1=fnd_position; |
902 | if(i<num) { |
||
903 | fnd_obj(result,i+1,orig); p2=fnd_position; |
||
904 | } |
||
905 | else p2=result+strlen(result); |
||
906 | if(p1==NULL || p2==NULL) internal_error("_obj_replace() error."); |
||
907 | if(i<num) { |
||
908 | i=strlen(by); by[i++]=separator;by[i]=0; |
||
909 | } |
||
910 | string_modify(result,p1,p2,"%s",by); |
||
911 | } |
||
912 | else { |
||
913 | if(separator==0) { |
||
914 | if(orig[0]==0 || by[0]==0) return; |
||
915 | for(p1=strchr(result,orig[0]);p1!=NULL;p1=strchr(p1+1,orig[0])) |
||
916 | *p1=by[0]; |
||
917 | return; |
||
918 | } |
||
919 | if(strlen(orig)+strlen(by)==0) return; |
||
920 | for(p1=objchr(result,orig);p1!=NULL;p1=objchr(p1+strlen(by)+1,orig)) { |
||
7673 | bpr | 921 | string_modify(result,p1,p1+strlen(orig),"%s",by); |
10 | reyssat | 922 | } |
12228 | bpr | 923 | } |
10 | reyssat | 924 | } |
925 | |||
7673 | bpr | 926 | /* replacement */ |
10 | reyssat | 927 | void calc_replace(char *p) |
928 | { |
||
12228 | bpr | 929 | int i,style,num,internal; |
930 | char *q[3], *pp; |
||
931 | char bf[4][MAX_LINELEN+17]; |
||
932 | char fn[3][MAX_FNAME+1], *arglist[8]; |
||
933 | char regexp_char='/'; |
||
10 | reyssat | 934 | |
12228 | bpr | 935 | style=num=0; |
936 | q[0]=find_word_start(p); internal=0; |
||
937 | if(strncasecmp(q[0],"internal",strlen("internal"))==0 && |
||
938 | isspace(*(q[0]+strlen("internal")))) { |
||
939 | q[0]=find_word_start(q[0]+strlen("internal")); |
||
940 | internal=1; |
||
941 | } |
||
942 | q[1]=wordchr(q[0],"by"); q[2]=wordchr(q[0],"in"); |
||
943 | if(q[1]==NULL || q[2]==NULL) { |
||
944 | module_error("replace_syntax"); *p=0; return; |
||
945 | } |
||
946 | *q[1]=0; *q[2]=0; |
||
947 | q[1]=find_word_start(q[1]+strlen("by")); |
||
948 | q[2]=find_word_start(q[2]+strlen("in")); |
||
949 | mystrncpy(bf[0],q[0],sizeof(bf[0])); |
||
950 | pp=find_word_end(bf[0]); if(*pp) *(pp++)=0; |
||
951 | if(strcmp(bf[0],"word")==0) style=1; |
||
952 | else { |
||
953 | if(strcmp(bf[0],"item")==0) style=2; |
||
954 | else { |
||
955 | if(strcmp(bf[0],"line")==0) style=3; |
||
956 | else { |
||
957 | if(strcmp(bf[0],"char")==0) style=4; |
||
958 | } |
||
10 | reyssat | 959 | } |
12228 | bpr | 960 | } |
961 | if(style>0) { |
||
962 | q[0]=find_word_start(find_word_end(q[0])); |
||
10 | reyssat | 963 | mystrncpy(bf[0],q[0],sizeof(bf[0])); |
964 | pp=find_word_end(bf[0]); if(*pp) *(pp++)=0; |
||
12228 | bpr | 965 | if(strcmp(bf[0],"number")==0) { |
966 | num=1; q[0]=find_word_start(pp); |
||
10 | reyssat | 967 | } |
12228 | bpr | 968 | } |
969 | for(i=0;i<3;i++) { |
||
970 | strip_trailing_spaces(q[i]); |
||
971 | mystrncpy(bf[i],q[i],sizeof(bf[i])); |
||
972 | substit(bf[i]); |
||
973 | } |
||
974 | if(bf[0][0]==0) {mystrncpy(p,bf[2],MAX_LINELEN); return;} |
||
975 | switch(style) { |
||
976 | case 1: { /* word */ |
||
977 | _obj_replace(bf[0],bf[1],bf[2],num,' ',p, |
||
978 | fnd_word,wordnum,wordchr); |
||
979 | return; |
||
10 | reyssat | 980 | } |
12228 | bpr | 981 | case 2: { /* item */ |
982 | _obj_replace(bf[0],bf[1],bf[2],num,',',p, |
||
983 | fnd_item,itemnum,itemchr); |
||
984 | return; |
||
10 | reyssat | 985 | } |
12228 | bpr | 986 | case 3: { /* line */ |
987 | _obj_replace(bf[0],bf[1],bf[2],num,'\n',p, |
||
988 | fnd_line,linenum,linechr); |
||
989 | return; |
||
10 | reyssat | 990 | } |
12228 | bpr | 991 | case 4: { /* char */ |
992 | if(bf[1][0]==0) bf[1][0]=' '; |
||
993 | if(bf[0][0]==0) return; |
||
994 | _obj_replace(bf[0],bf[1],bf[2],num,0,p, |
||
995 | fnd_char,charnum,charchr); |
||
996 | return; |
||
997 | } |
||
998 | default: break; |
||
999 | } |
||
1000 | if(internal || strstr(tmp_dir,"sessions")==NULL || (strpbrk(bf[0],"\\[^.*$")==NULL && |
||
10 | reyssat | 1001 | strpbrk(bf[1],"\\[^.*$")==NULL)) { |
7673 | bpr | 1002 | /* No regexp, direct replace */ |
12228 | bpr | 1003 | char *pp; |
1004 | for(pp=strstr(bf[2],bf[0]);pp<bf[2]+MAX_LINELEN && pp!=NULL; |
||
1005 | pp=strstr(pp+strlen(bf[1]),bf[0])) { |
||
1006 | string_modify(bf[2],pp,pp+strlen(bf[0]),"%s",bf[1]); |
||
10 | reyssat | 1007 | } |
12228 | bpr | 1008 | mystrncpy(p,bf[2],MAX_LINELEN);return; |
1009 | } |
||
1010 | mkfname(fn[0],"%s/sed.in",tmp_dir); |
||
1011 | mkfname(fn[1],"%s/sed.out",tmp_dir); |
||
1012 | accessfile(bf[2],"w",fn[0]); |
||
1013 | snprintf(bf[3],sizeof(bf[3]),"s%c%s%c%s%cg", |
||
7673 | bpr | 1014 | regexp_char,bf[0],regexp_char,bf[1],regexp_char); |
12228 | bpr | 1015 | arglist[0]=sed_prog; arglist[1]=bf[3]; arglist[2]=NULL; |
1016 | execredirected(sed_prog,fn[0],fn[1],"/dev/null",arglist); |
||
1017 | read_tmp_file(p,"sed.out"); |
||
1018 | strip_trailing_spaces(p); |
||
10 | reyssat | 1019 | } |
1020 | |||
7673 | bpr | 1021 | /* transforms a string to hexadecimal code, upper-case */ |
10 | reyssat | 1022 | void calc_hex(char *p) |
1023 | { |
||
12228 | bpr | 1024 | unsigned char *p1, orig[MAX_LINELEN+1]; |
1025 | char *p2; |
||
1026 | char *hex="0123456789ABCDEF"; |
||
7404 | bpr | 1027 | |
12228 | bpr | 1028 | mystrncpy((char*)orig,p,MAX_LINELEN); |
1029 | for(p1=orig, p2=p; *p1 && p2-p<MAX_LINELEN-2; p1++) { |
||
1030 | *p2++=hex[(*p1>>4)&15]; *p2++=hex[*p1&15]; |
||
1031 | } |
||
1032 | *p2=0; |
||
10 | reyssat | 1033 | } |
1034 | |||
7673 | bpr | 1035 | /* transforms to lower/upper cases */ |
10 | reyssat | 1036 | void calc_tolower(char *p) |
1037 | { |
||
12228 | bpr | 1038 | char *pp; |
1039 | for(pp=p;*pp;pp++) *pp=tolower(*pp); |
||
10 | reyssat | 1040 | } |
1041 | |||
1042 | void calc_toupper(char *p) |
||
1043 | { |
||
12228 | bpr | 1044 | char *pp; |
1045 | for(pp=p;*pp;pp++) *pp=toupper(*pp); |
||
10 | reyssat | 1046 | } |
1047 | |||
7673 | bpr | 1048 | /* strip leading and trailing spaces */ |
10 | reyssat | 1049 | void calc_trim(char *p) |
1050 | { |
||
12228 | bpr | 1051 | char *s; |
1052 | s=find_word_start(p); |
||
1053 | if(s>p) memmove(p,s,MAX_LINELEN-(s-p)+1); |
||
1054 | strip_trailing_spaces(p); |
||
10 | reyssat | 1055 | } |
1056 | |||
7673 | bpr | 1057 | /* output date. Uses Linux 'date' utility. */ |
10 | reyssat | 1058 | void calc_date(char *p) |
1059 | { |
||
12228 | bpr | 1060 | char *p1, *p2, *p3; |
1061 | if(!trusted_module() || is_class_module) { |
||
1062 | if(strstr(p,"..")!=NULL) return; |
||
1063 | for(p1=find_word_start(p); *p1; p1=find_word_start(p2)) { |
||
1064 | p2=find_word_end(p1); |
||
1065 | while(*p1=='\'' || *p1=='"') p1++; |
||
1066 | if(*p1!='-') continue; |
||
1067 | for(p3=p1+1;p3<p2;p3++) if(strchr("rs",*p3)!=NULL) return; |
||
10 | reyssat | 1068 | } |
12228 | bpr | 1069 | } |
1070 | wrapexec=1; |
||
1071 | call_ssh("date %s >%s/date.out 2>/dev/null",p,tmp_dir); |
||
1072 | read_tmp_file(p,"date.out"); |
||
10 | reyssat | 1073 | } |
1074 | |||
7673 | bpr | 1075 | /* ls, or dir */ |
10 | reyssat | 1076 | void calc_listfile(char *p) |
1077 | { |
||
12228 | bpr | 1078 | char *pp; |
7404 | bpr | 1079 | |
7673 | bpr | 1080 | /* only for trusted modules */ |
12228 | bpr | 1081 | if(!trusted_module() || is_class_module) { |
1082 | module_error("not_trusted"); *p=0; return; |
||
1083 | } |
||
7673 | bpr | 1084 | /* security measures. */ |
12228 | bpr | 1085 | for(pp=p;*pp;pp++) if(isspace(*pp) || *pp==';') *pp=' '; |
1086 | if(strstr(p,parent_dir_string)!=NULL) { |
||
1087 | setvar(error_data_string,p); |
||
1088 | module_error("illegal_fname"); return; |
||
1089 | } |
||
1090 | wrapexec=1; |
||
1091 | call_sh("ls %s >%s/ls.out 2>%s/ls.err", |
||
7673 | bpr | 1092 | p,tmp_dir,tmp_dir); |
12228 | bpr | 1093 | read_tmp_file(p,"ls.out"); |
10 | reyssat | 1094 | } |
1095 | |||
12047 | bpr | 1096 | void calc_fileexists(char *p) |
1097 | { |
||
12228 | bpr | 1098 | char *pp, *fname; |
12047 | bpr | 1099 | /* security measures. */ |
12228 | bpr | 1100 | for(pp=p;*pp;pp++) if(isspace(*pp) || *pp==';') *pp=' '; |
1101 | if(strstr(p,parent_dir_string)!=NULL) { |
||
1102 | setvar(error_data_string,p); |
||
1103 | module_error("illegal_fname"); return mystrncpy(p,"no",MAX_LINELEN); |
||
1104 | } |
||
1105 | if(strncmp(p,"wimshome/",9)==0){ |
||
1106 | if(robot_access || !trusted_module() || is_class_module){ |
||
1107 | module_error("illegal_fname"); return mystrncpy(p,"no",MAX_LINELEN); |
||
12047 | bpr | 1108 | } |
12228 | bpr | 1109 | else |
1110 | { |
||
1111 | fname=strchr(p,'/'); |
||
1112 | if(ftest(mkfname(NULL,"%s/%s",getvar("wims_home"),fname))==is_file) |
||
12074 | bpr | 1113 | return mystrncpy(p,"yes",MAX_LINELEN); |
12047 | bpr | 1114 | } |
12228 | bpr | 1115 | } |
1116 | if(ftest(mkfname(NULL,"%s",p))==is_file) return mystrncpy(p,"yes",MAX_LINELEN); |
||
1117 | else return mystrncpy(p,"no",MAX_LINELEN); |
||
12047 | bpr | 1118 | } |
1119 | |||
7673 | bpr | 1120 | /* instex static: static tex inserts */ |
10 | reyssat | 1121 | void calc_instexst(char *p) |
1122 | { |
||
12228 | bpr | 1123 | char nbuf[MAX_FNAME+1], bufc[MAX_LINELEN+1]; |
1124 | char buf2[1024], altbuf[1024], buf[MAX_LINELEN+1], urlbuf[MAX_LINELEN+1]; |
||
1125 | char *b, *at, *al, *md1, *md2; |
||
1126 | int t, border, vspace; |
||
1127 | struct stat st,stc; |
||
1128 | char *p1, *p2, *p3, *ppp, *pt; |
||
10 | reyssat | 1129 | |
12228 | bpr | 1130 | if(robot_access) {*p=0; return;} |
1131 | p1=find_word_start(p); p2=find_word_end(p1); |
||
1132 | p3=p2-4; vspace=0; |
||
1133 | fix_tex_size(); |
||
1134 | t=untrust; untrust=0; |
||
1135 | if(find_module_file(m_file.name,bufc,0)) module_error(m_file.name); |
||
1136 | else stat(bufc,&stc); |
||
1137 | untrust=t; |
||
1138 | if(*p3=='.' && (memcmp(p3+1,"gif",3)==0 || memcmp(p3+1,"png",3)==0)) { |
||
1139 | char mbuf[MAX_LINELEN+1]; |
||
1140 | if(*p2!=0) *p2++=0; |
||
1141 | p2=find_word_start(p2); |
||
1142 | ovlstrcpy(mbuf,p1); substit(mbuf); |
||
1143 | if(strstr(mbuf,parent_dir_string)!=NULL) { |
||
1144 | setvar(error_data_string,mbuf); |
||
1145 | module_error("illegal_fname"); return; |
||
10 | reyssat | 1146 | } |
12228 | bpr | 1147 | mkfname(nbuf,"%s/%s",module_prefix,mbuf); |
1148 | } |
||
1149 | else { |
||
1150 | ppp=getvar(ro_name[ro_module]); |
||
1151 | if(ppp==NULL) internal_error("calc_instexst(): module name vanishes."); |
||
1152 | p2=p1; |
||
1153 | mkfname(nbuf,"w/instex/%d/%s/%s_%d.gif", |
||
7673 | bpr | 1154 | current_tex_size,ppp,m_file.name,m_file.l); |
12228 | bpr | 1155 | } |
1156 | snprintf(urlbuf,sizeof(urlbuf),"%s%s?%X",ref_base,nbuf, |
||
7673 | bpr | 1157 | (unsigned short int) stc.st_mtime); |
12228 | bpr | 1158 | mystrncpy(buf,nbuf,sizeof(buf)); |
1159 | if((ppp=strrchr(buf,'/'))!=NULL) { |
||
1160 | *ppp=0;mkdirs(buf); |
||
1161 | } |
||
1162 | b=getvar("ins_border"); |
||
1163 | at=getvar("ins_attr"); |
||
1164 | al=getvar("ins_align"); |
||
1165 | if(at==NULL) at=""; |
||
1166 | if(al==NULL) al=""; |
||
1167 | al=find_word_start(al); |
||
1168 | if(*al!=0) snprintf(buf2,sizeof(buf2),"vertical-align:%s",al); else buf2[0]=0; |
||
1169 | if(b==NULL || *b==0) border=0; |
||
1170 | else border=atoi(b); |
||
1171 | if(border<0) border=0; |
||
1172 | if(border>100) border=100; |
||
1173 | if(instex_ready(p2,urlbuf)) goto prt; |
||
1174 | if(stat(nbuf,&st)!=0 || st.st_mtime<stc.st_mtime || st.st_size<45) { |
||
1175 | setenv("texgif_style",instex_style,1); |
||
1176 | setenv("texgif_src",p2,1); |
||
1177 | setenv("texgif_outfile",nbuf,1); |
||
1178 | setenv("texgif_tmpdir",tmp_dir,1); exportall(); |
||
1179 | wrapexec=0; call_ssh("%s &>%s/instexst.log",tex2gif,tmp_dir); |
||
1180 | setenv("instexst_src","",1); |
||
1181 | } |
||
1182 | prt: md1=md2=""; |
||
1183 | if(strcasecmp(al,"middle")==0) { |
||
1184 | md1=mathalign_sup1; md2=mathalign_sup2; |
||
1185 | vspace=5; |
||
1186 | } |
||
1187 | if(ins_alt[0]==0) mystrncpy(ins_alt,p2,sizeof(ins_alt)); |
||
1188 | if(strchr(ins_alt,'"')!=NULL || strlen(ins_alt)>256) ins_alt[0]=0; |
||
1189 | pt=getvar("wims_ins_alt"); if(pt==NULL) pt=""; |
||
12526 | bpr | 1190 | if(strcmp(pt,"empty")==0) altbuf[0]=0; |
1191 | else |
||
1192 | if(ins_alt[0] && strcmp(pt,"none")!=0) |
||
1193 | snprintf(altbuf,sizeof(altbuf)," alt=\"\""); |
||
1194 | else |
||
1195 | snprintf(altbuf,sizeof(altbuf)," alt=\"%s\"",ins_alt); |
||
17177 | bpr | 1196 | snprintf(p,MAX_LINELEN,"%s<img src=\"%s\" style=\"border:solid;border-width:%dpx;margin-bottom:%dpx;%s\" %s %s>%s", |
12228 | bpr | 1197 | md1,urlbuf,border,vspace,buf2,at,altbuf,md2); |
1198 | setvar("ins_attr",""); ins_alt[0]=0; |
||
1199 | setvar("ins_url",urlbuf); |
||
10 | reyssat | 1200 | } |
1201 | |||
7673 | bpr | 1202 | /* extract non-empty lines or items */ |
10 | reyssat | 1203 | void calc_nonempty(char *p) |
1204 | { |
||
12228 | bpr | 1205 | int type, i, cnt; |
1206 | char *p1, *p2, buf[MAX_LINELEN+1], out[MAX_LINELEN+1]; |
||
1207 | p1=find_word_start(p); p2=find_word_end(p1); |
||
1208 | if(*p2) *p2++=0; else { |
||
1209 | *p=0; return; |
||
1210 | } |
||
1211 | type=0; |
||
1212 | if(strcasecmp(p1,"item")==0 || strcasecmp(p1,"items")==0) type=1; |
||
1213 | if(type==0 && (strcasecmp(p1,"line")==0 || strcasecmp(p1,"lines")==0)) |
||
1214 | type=2; |
||
1215 | if(type==0 && (strcasecmp(p1,"row")==0 || strcasecmp(p1,"rows")==0)) |
||
1216 | type=3; |
||
1217 | if(type==0) module_error("syntax_error"); |
||
1218 | out[0]=out[1]=0; |
||
1219 | switch(type) { |
||
1220 | case 1: { /* items */ |
||
1221 | cnt=itemnum(p2); |
||
1222 | for(i=1; i<=cnt; i++) { |
||
1223 | fnd_item(p2,i,buf); |
||
1224 | if(*find_word_start(buf)) { |
||
1225 | strcat(out,",");strcat(out,buf); |
||
1226 | } |
||
1227 | } |
||
1228 | break; |
||
10 | reyssat | 1229 | } |
12228 | bpr | 1230 | case 2: { /* lines */ |
1231 | lines: cnt=linenum(p2); |
||
1232 | for(i=1; i<=cnt; i++) { |
||
1233 | fnd_line(p2,i,buf); |
||
1234 | if(*find_word_start(buf)) { |
||
1235 | strcat(out,"\n");strcat(out,buf); |
||
1236 | } |
||
1237 | } |
||
1238 | break; |
||
10 | reyssat | 1239 | } |
12228 | bpr | 1240 | case 3: { /* rows */ |
1241 | int t=rows2lines(p2); |
||
1242 | if(t==0) goto lines; |
||
1243 | cnt=linenum(p2); |
||
1244 | for(i=1; i<=cnt; i++) { |
||
1245 | fnd_line(p2,i,buf); |
||
1246 | if(*find_word_start(buf)) { |
||
1247 | strcat(out,";");strcat(out,buf); |
||
1248 | } |
||
1249 | } |
||
1250 | break; |
||
1251 | } |
||
1252 | default: break; |
||
1253 | } |
||
1254 | ovlstrcpy(p,out+1); |
||
10 | reyssat | 1255 | } |
1256 | |||
7673 | bpr | 1257 | /* returns a list with unique items */ |
10 | reyssat | 1258 | void calc_listuniq(char *p) |
1259 | { |
||
12228 | bpr | 1260 | int i,n; |
1261 | char lout[MAX_LINELEN+2], *ll; |
||
1262 | char *cut[MAX_LIST]; |
||
1263 | lout[0]=lout[1]=0; |
||
1264 | n=cutitems(p,cut,MAX_LIST); for(i=0;i<n;i++) { |
||
1265 | ll=cut[i]; |
||
1266 | if(*ll && itemchr(lout,ll)==NULL && |
||
7673 | bpr | 1267 | strlen(lout)+strlen(ll)<MAX_LINELEN-2) { |
12228 | bpr | 1268 | strcat(lout,",");strcat(lout,ll); |
10 | reyssat | 1269 | } |
12228 | bpr | 1270 | } |
1271 | ovlstrcpy(p,lout+1); |
||
10 | reyssat | 1272 | } |
1273 | |||
7673 | bpr | 1274 | /* returns intersection of 2 lists */ |
10 | reyssat | 1275 | void calc_listintersect(char *p) |
1276 | { |
||
18493 | bpr | 1277 | char l1[MAX_LINELEN+1],l2[MAX_LINELEN+1]; |
1278 | char *cut[MAX_LIST],*cut1[MAX_LIST],*cuts[MAX_LIST]; |
||
12228 | bpr | 1279 | char *pp, *ll; |
18493 | bpr | 1280 | int i,j,k,n,m,s=0; |
12228 | bpr | 1281 | pp=wordchr(p,"and"); |
1282 | if(pp==NULL) module_error("syntax_error"); |
||
1283 | *pp=0;ovlstrcpy(l1,p); ovlstrcpy(l2,pp+strlen("and")); |
||
18493 | bpr | 1284 | substit(l1); substit(l2); |
1285 | n=cutitems(l2,cut,MAX_LIST); if(n<=0) {*p=0; return;} |
||
1286 | m=cutitems(l1,cut1,MAX_LIST); |
||
12228 | bpr | 1287 | for(i=0;i<n;i++) { |
1288 | ll=cut[i]; |
||
18493 | bpr | 1289 | for(k=0;k<m;k++) |
1290 | if(!strcmp(cut1[k],ll)) break; |
||
1291 | if (k==m) continue; |
||
1292 | for(j=0;j<s;j++) |
||
1293 | if(!strcmp(cuts[j],ll)) break; |
||
1294 | if (j==s) cuts[s++]=ll; |
||
12228 | bpr | 1295 | } |
18493 | bpr | 1296 | p[0]=0; |
1297 | for(i=0;i<s;i++){ |
||
1298 | if(i) strcat(p,","); |
||
1299 | if(strlen(p)+strlen(cuts[i])<MAX_LINELEN-2) |
||
1300 | strcat(p,cuts[i]); |
||
1301 | } |
||
10 | reyssat | 1302 | } |
1303 | |||
7673 | bpr | 1304 | /* returns union of 2 lists */ |
10 | reyssat | 1305 | void calc_listunion(char *p) |
1306 | { |
||
18493 | bpr | 1307 | char l1[MAX_LINELEN+1],l2[MAX_LINELEN+1]; |
1308 | char *cut[MAX_LIST],*cut1[MAX_LIST],*cuts[MAX_LIST]; |
||
12228 | bpr | 1309 | char *pp, *ll; |
18493 | bpr | 1310 | int i,j,k,n,m,s=0; |
12228 | bpr | 1311 | pp=wordchr(p,"and"); |
1312 | if(pp==NULL) module_error("syntax_error"); |
||
1313 | *pp=0;ovlstrcpy(l1,p); ovlstrcpy(l2,pp+strlen("and")); |
||
18493 | bpr | 1314 | substit(l1); substit(l2); |
1315 | n=cutitems(l2,cut,MAX_LIST); if(n<=0) {*p=0; return;} |
||
1316 | m=cutitems(l1,cut1,MAX_LIST); |
||
1317 | for(i=0;i<n;i++) { |
||
12228 | bpr | 1318 | ll=cut[i]; |
18493 | bpr | 1319 | for(j=0;j<s;j++) |
1320 | if(!strcmp(cuts[j],ll)) break; |
||
1321 | if (j==s) cuts[s++]=ll; |
||
12228 | bpr | 1322 | } |
18493 | bpr | 1323 | for(k=0;k<m;k++) { |
1324 | ll=cut1[k]; |
||
1325 | for(j=0;j<s;j++) |
||
1326 | if(!strcmp(cuts[j],ll)) break; |
||
1327 | if(j==s) cuts[s++]=ll; |
||
12228 | bpr | 1328 | } |
18493 | bpr | 1329 | p[0]=0; |
1330 | for(i=0;i<s;i++){ |
||
1331 | if(i) strcat(p,","); |
||
1332 | if(strlen(p)+strlen(cuts[i])<MAX_LINELEN-2) |
||
1333 | strcat(p,cuts[i]); |
||
1334 | } |
||
10 | reyssat | 1335 | } |
1336 | |||
7673 | bpr | 1337 | /* returns items of list2 not in list1 */ |
10 | reyssat | 1338 | void calc_listcomplement(char *p) |
1339 | { |
||
18493 | bpr | 1340 | char l1[MAX_LINELEN+1],l2[MAX_LINELEN+1]; |
1341 | char *cut[MAX_LIST],*cut1[MAX_LIST],*cuts[MAX_LIST]; |
||
12228 | bpr | 1342 | char *pp, *ll; |
18493 | bpr | 1343 | int i,j,k,n,m,s=0; |
12228 | bpr | 1344 | pp=wordchr(p,"in"); |
1345 | if(pp==NULL) module_error("syntax_error"); |
||
1346 | *pp=0;ovlstrcpy(l1,p); ovlstrcpy(l2,pp+strlen("in")); |
||
18493 | bpr | 1347 | substit(l1); substit(l2); |
12228 | bpr | 1348 | n=cutitems(l2,cut,MAX_LIST); if(n<=0) {*p=0; return;} |
18493 | bpr | 1349 | m=cutitems(l1,cut1,MAX_LIST); |
12228 | bpr | 1350 | for(i=0;i<n;i++) { |
1351 | ll=cut[i]; |
||
18493 | bpr | 1352 | for(j=0;j<s;j++) |
1353 | if(!strcmp(cuts[j],ll)) break; |
||
1354 | for(k=0;k<m;k++) |
||
1355 | if(!strcmp(cut1[k],ll)) break; |
||
1356 | if(j==s && k==m) cuts[s++]=ll; |
||
12228 | bpr | 1357 | } |
18493 | bpr | 1358 | p[0]=0; |
1359 | for(i=0;i<s;i++){ |
||
1360 | if(i) strcat(p,","); |
||
1361 | if(strlen(p)+strlen(cuts[i])<MAX_LINELEN-2) |
||
1362 | strcat(p,cuts[i]); |
||
1363 | } |
||
10 | reyssat | 1364 | } |
1365 | |||
7673 | bpr | 1366 | /* Consult a dictionary to translate a string */ |
10 | reyssat | 1367 | /* |
1368 | void calc_dictionary(char *p) |
||
1369 | { |
||
12228 | bpr | 1370 | char *pp; |
1371 | char name[MAX_LINELEN+1], str[MAX_LINELEN+1]; |
||
1372 | int t; |
||
1373 | pp=wordchr(p,"for"); |
||
1374 | if(pp==NULL || pp<=p) module_error("syntax_error"); |
||
1375 | *(find_word_end(pp-1))=0; |
||
1376 | ovlstrcpy(name,p); substit(name); |
||
1377 | pp=find_word_start(pp+strlen("for")); t=0; |
||
1378 | if(memcmp(pp,"word",strlen("word"))==0 && |
||
1379 | (isspace(*(pp+strlen("word"))) || |
||
1380 | (*(pp+strlen("word"))=='s' && isspace(*(pp+strlen("words")))))) { |
||
1381 | pp=find_word_start(pp+strlen("words")); t=1; |
||
1382 | } |
||
1383 | if(memcmp(pp,"line",strlen("line"))==0 && |
||
1384 | (isspace(*(pp+strlen("line"))) || |
||
1385 | (*(pp+strlen("line"))=='s' && isspace(*(pp+strlen("lines")))))) { |
||
1386 | pp=find_word_start(pp+strlen("lines")); t=1; |
||
1387 | } |
||
1388 | if(memcmp(pp,"list",strlen("list"))==0 && isspace(*(pp+strlen("list")))) { |
||
1389 | pp=find_word_start(pp+strlen("list")); |
||
1390 | } |
||
1391 | if(memcmp(pp,"items",strlen("items"))==0 && isspace(*(pp+strlen("items")))) { |
||
1392 | pp=find_word_start(pp+strlen("items")); |
||
1393 | } |
||
1394 | if(memcmp(pp,"item",strlen("item"))==0 && isspace(*(pp+strlen("item")))) { |
||
1395 | pp=find_word_start(pp+strlen("item")); |
||
1396 | } |
||
1397 | ovlstrcpy(str,pp); substit(str); |
||
1398 | switch(t) { |
||
1399 | case 1: { |
||
1400 | calc_words2items(str); break; |
||
1401 | } |
||
1402 | case 2: { |
||
7673 | bpr | 1403 | calc_lines2items(str); break; |
1404 | } |
||
1405 | default: break; |
||
10 | reyssat | 1406 | } |
1407 | } |
||
1408 | */ |
||
1409 | |||
1410 | void calc_module(char *p) |
||
1411 | { |
||
12228 | bpr | 1412 | char *p1,*p2, ind_buf[MAX_LINELEN+1], buf[MAX_FNAME+1]; |
1413 | char *tp; |
||
7404 | bpr | 1414 | |
12228 | bpr | 1415 | p1=find_word_start(p); p2=find_word_end(p1); |
1416 | if(*p2!=0) *p2++=0; |
||
1417 | p2=find_word_start(p2); *find_word_end(p2)=0; |
||
1418 | if(*p1==0) {empty: *p=0; return;} |
||
1419 | if(*p2==0) { |
||
1420 | snprintf(buf,sizeof(buf),"module_%s",p1); |
||
1421 | p1=getvar(buf); if(p1==NULL) p1=""; |
||
1422 | mystrncpy(p,p1,MAX_LINELEN); return; |
||
1423 | } |
||
1424 | mkfname(buf,"%s/%s/INDEX",module_dir,p2); |
||
1425 | tp=readfile(buf,ind_buf,MAX_LINELEN); |
||
1426 | if(tp==NULL) { |
||
1427 | mkfname(buf,"%s/%s/index",module_dir,p2); |
||
10 | reyssat | 1428 | tp=readfile(buf,ind_buf,MAX_LINELEN); |
12228 | bpr | 1429 | } |
1430 | if(tp==NULL && p2[strlen(p2)-3]!='.') { |
||
1431 | mkfname(buf,"%s/%s.%s/INDEX",module_dir,p2,lang); |
||
1432 | tp=readfile(buf,ind_buf,MAX_LINELEN); |
||
10 | reyssat | 1433 | if(tp==NULL) { |
12228 | bpr | 1434 | mkfname(buf,"%s/%s.%s/index",module_dir,p2,lang); |
1435 | tp=readfile(buf,ind_buf,MAX_LINELEN); |
||
10 | reyssat | 1436 | } |
12228 | bpr | 1437 | if(tp==NULL) { |
1438 | int i; |
||
1439 | for(i=0;i<available_lang_no;i++) { |
||
1440 | mkfname(buf,"%s/%s.%s/INDEX",module_dir,p2,available_lang[i]); |
||
1441 | tp=readfile(buf,ind_buf,MAX_LINELEN); if(tp) break; |
||
1442 | mkfname(buf,"%s/%s.%s/index",module_dir,p2, |
||
1443 | available_lang[i]); |
||
1444 | tp=readfile(buf,ind_buf,MAX_LINELEN); if(tp) break; |
||
1445 | } |
||
10 | reyssat | 1446 | } |
12228 | bpr | 1447 | } |
1448 | if(tp==NULL) goto empty; /* module not found */ |
||
1449 | _getdef(ind_buf,p1,p); |
||
10 | reyssat | 1450 | } |
1451 | |||
7673 | bpr | 1452 | /* strip enclosing parentheses */ |
10 | reyssat | 1453 | void calc_declosing(char *p) |
1454 | { |
||
12228 | bpr | 1455 | strip_enclosing_par(p); |
10 | reyssat | 1456 | } |
15588 | bpr | 1457 | /* return no if the parenthesis do not match */ |
1458 | void calc_checkallpar(char *p) |
||
1459 | { |
||
1460 | if(check_parentheses(p,1)==0) |
||
1461 | ovlstrcpy(p, "yes"); |
||
1462 | else ovlstrcpy(p, "no"); |
||
1463 | } |
||
16080 | bpr | 1464 | /* remove html tag, very rudimentary. |
1465 | by default, everything is detagged |
||
1466 | one can choose what to detag by the parameter wims_parm_detag |
||
1467 | */ |
||
10 | reyssat | 1468 | void calc_detag(char *p) |
1469 | { |
||
16080 | bpr | 1470 | char *p1, *p2, *s, tag[100]; |
1471 | int n=0; |
||
1472 | |||
1473 | s=getvar("wims_parm_detag"); |
||
1474 | if(s==NULL || *s == 0) |
||
1475 | for(p1=strchr(p,'<'); p1!=NULL; p1=strchr(p1,'<')) |
||
1476 | { |
||
1477 | p2=strchr(p1,'>'); |
||
1478 | if(p2==NULL) p1++; else ovlstrcpy(p1,p2+1); |
||
1479 | } |
||
1480 | else |
||
1481 | for(s=find_word_start(s); *s; s=find_word_start(s+n)) |
||
1482 | { |
||
1483 | n = find_word_end(s) - s; if (n > 96) n = 96; |
||
1484 | tag[0]='<'; |
||
1485 | mystrncpy(tag+1, s, n+1); tag[n+1]=0; |
||
1486 | for(p1=strstr(p,tag); p1!=NULL; p1=strstr(p1,tag)) |
||
1487 | { |
||
1488 | p2=strchr(p1,'>'); |
||
1489 | if(p2==NULL) p1++; else ovlstrcpy(p1,p2+1); |
||
1490 | } |
||
1491 | tag[1]='/'; |
||
1492 | mystrncpy(tag+2, s, n+1); tag[n+2]='>'; tag[n+3]=0; |
||
1493 | for(p1=strstr(p,tag); p1!=NULL; p1=strstr(p1,tag)) |
||
1494 | ovlstrcpy(p1,p1+strlen(tag)); |
||
1495 | } |
||
10 | reyssat | 1496 | } |
1497 | |||
13757 | bpr | 1498 | /* replace html symbols by their iso translation */ |
1499 | void calc_html2iso(char *p) |
||
1500 | { |
||
1501 | int st, ns; |
||
13783 | bpr | 1502 | unsigned char buffer[MAX_LINELEN], *s = buffer; |
13757 | bpr | 1503 | inithtmltrans(); |
13783 | bpr | 1504 | strcpy((char *)buffer, p); |
13757 | bpr | 1505 | while (*s) |
1506 | if (*s == '&'){ |
||
1507 | unsigned char *p1 = ++s; |
||
1508 | for (st = 0; (ns = htmltrans[abs(st)][*s]); st = ns) |
||
1509 | s++; |
||
1510 | if (st > 0 && *s == ';') |
||
13783 | bpr | 1511 | {char *r=htmlsymbs[st][1]; strcpy((char *)p, r); s++; p+=strlen(r);} |
13757 | bpr | 1512 | else |
13783 | bpr | 1513 | {*p++='&'; s=p1;} |
13757 | bpr | 1514 | } |
13783 | bpr | 1515 | else *p++=*s++; |
1516 | *p = 0; |
||
13757 | bpr | 1517 | } |
1518 | |||
8155 | bpr | 1519 | /* prepare a string to be inserted into a form input or textarea as is */ |
10 | reyssat | 1520 | void calc_reinput(char *p) |
1521 | { |
||
12228 | bpr | 1522 | char *p1; |
1523 | for(p1=strchr(p,'&'); p1!=NULL; p1=strchr(p1,'&')) { |
||
1524 | p1++; string_modify(p,p1,p1,"amp;"); |
||
1525 | } |
||
1526 | for(p1=strchr(p,'<'); p1!=NULL; p1=strchr(++p1,'<')) |
||
1527 | string_modify(p,p1,p1+1,"<"); |
||
10 | reyssat | 1528 | } |
1529 | |||
7673 | bpr | 1530 | /* get a definition from a file. Trusted modules only. */ |
10 | reyssat | 1531 | void calc_defof(char *p) |
1532 | { |
||
12228 | bpr | 1533 | char *p1; |
1534 | char fbuf[MAX_FNAME+1], nbuf[MAX_LINELEN+1], tbuf[MAX_LINELEN+1]; |
||
7404 | bpr | 1535 | |
12228 | bpr | 1536 | secure_exec(); |
1537 | p1=wordchr(p,"in"); if(p1==NULL) module_error("syntax_error"); |
||
1538 | *p1=0; p1=find_word_start(p1+strlen("in")); |
||
1539 | mystrncpy(nbuf,p,sizeof(nbuf)); mystrncpy(tbuf,p1,sizeof(tbuf)); |
||
1540 | substit(nbuf); substit(tbuf); |
||
1541 | p1=find_word_start(tbuf); *find_word_end(p1)=0; |
||
1542 | if(find_module_file(p1,fbuf,0)) {*p=0; return;} |
||
1543 | p1=find_word_start(nbuf); strip_trailing_spaces(p1); |
||
1544 | getdef(fbuf,p1,p); |
||
10 | reyssat | 1545 | } |
1546 | |||
7673 | bpr | 1547 | /* check host */ |
10 | reyssat | 1548 | void calc_checkhost(char *p) |
1549 | { |
||
12228 | bpr | 1550 | int t; |
1551 | if(robot_access || !trusted_module()) ovlstrcpy(p,"0"); |
||
1552 | else { |
||
1553 | t=checkhost(p); mystrncpy(p,int2str(t),MAX_LINELEN); |
||
1554 | } |
||
10 | reyssat | 1555 | } |
1556 | |||
1557 | #define MAX_COLUMNS 256 |
||
1558 | |||
7673 | bpr | 1559 | /* A rudimentary database facility */ |
10 | reyssat | 1560 | void calc_select(char *p) |
1561 | { |
||
12228 | bpr | 1562 | char *p1, *p2, *p3, *bufp, c, sep; |
1563 | char buf1[MAX_LINELEN+1], buf2[MAX_LINELEN+1]; |
||
1564 | char buf[MAX_LINELEN+1]; |
||
1565 | int i,j,lmax; |
||
1566 | p2=wordchr(p,"where"); if(p2==NULL) module_error("syntax_error"); |
||
1567 | *p2=0; p2+=strlen("where"); |
||
1568 | p2=find_word_start(p2); strip_trailing_spaces(p2); |
||
1569 | p1=find_word_start(p) ; strip_trailing_spaces(p1); |
||
1570 | if(*p1==0 || *p2==0) module_error("syntax_error"); |
||
1571 | ovlstrcpy(buf1,p1); ovlstrcpy(buf2,p2); sep='\n'; |
||
7673 | bpr | 1572 | /* buf1: data; buf2: condition. */ |
12228 | bpr | 1573 | substit(buf1); |
1574 | if(strstr(buf2,"column")!=NULL) { /* matrix */ |
||
1575 | lmax=0; if(rows2lines(buf1)) sep=';'; |
||
1576 | for(p1=strstr(buf2,"column"); p1; p1=strstr(p1+1,"column")) { |
||
1577 | if(p1>buf2 && isalnum(*(p1-1))) continue; |
||
1578 | p2=find_word_start(p1+strlen("column")); |
||
1579 | for(p3=p2; myisdigit(*p3); p3++); |
||
1580 | if(p3==p2) continue; |
||
1581 | c=*p3; *p3=0; i=atoi(p2); *p3=c; |
||
1582 | if(i<=0 || i>MAX_COLUMNS) continue; |
||
1583 | if(i>lmax) lmax=i; |
||
1584 | string_modify(buf2,p1,p3,"$(wims_select_col_%d)",i); |
||
10 | reyssat | 1585 | } |
12228 | bpr | 1586 | buf[0]=0; bufp=buf; |
1587 | for(p1=buf1; *p1; p1=p2) { |
||
1588 | char ibuf[MAX_LINELEN+1], nbuf[MAX_NAMELEN+1]; |
||
1589 | p2=strchr(p1,'\n'); |
||
1590 | if(p2==NULL) p2=p1+strlen(p1); else *p2++=0; |
||
1591 | if(*find_word_start(p1)==0) continue; |
||
1592 | for(j=1;j<=lmax;j++) { |
||
1593 | snprintf(nbuf,sizeof(nbuf),"wims_select_col_%d",j); |
||
1594 | fnd_item(p1,j,ibuf); force_setvar(nbuf,ibuf); |
||
1595 | } |
||
1596 | ovlstrcpy(ibuf,buf2); if(compare(ibuf,0,0)) { |
||
1597 | snprintf(bufp,MAX_LINELEN-(bufp-buf),"%s%c",p1,sep); |
||
1598 | bufp+=strlen(bufp); |
||
1599 | } |
||
10 | reyssat | 1600 | } |
12228 | bpr | 1601 | } |
1602 | else { /* datafile */ |
||
1603 | module_error("syntax_error"); |
||
1604 | } |
||
1605 | if(buf[0]!=0) buf[strlen(buf)-1]=0; |
||
1606 | mystrncpy(p,buf,MAX_LINELEN); |
||
10 | reyssat | 1607 | } |
1608 | |||
7673 | bpr | 1609 | /* Extract a column from a matrix */ |
10 | reyssat | 1610 | void calc_columnof(char *p) |
1611 | { |
||
12228 | bpr | 1612 | char *p1, *p2, *bufp, sep; |
1613 | char buf1[MAX_LINELEN+1], buf2[MAX_LINELEN+1]; |
||
1614 | char buf[MAX_LINELEN+1]; |
||
1615 | p2=wordchr(p,"of"); if(p2==NULL) module_error("syntax_error"); |
||
1616 | *p2=0; p2+=strlen("of"); |
||
1617 | p2=find_word_start(p2); strip_trailing_spaces(p2); |
||
1618 | p1=find_word_start(p) ; strip_trailing_spaces(p1); |
||
1619 | if(*p1==0) module_error("syntax_error"); |
||
1620 | if(*p2==0) {*p=0; return;} |
||
1621 | ovlstrcpy(buf1,p1); ovlstrcpy(buf2,p2); sep='\n'; |
||
7673 | bpr | 1622 | /* buf1: number(s); buf2: matrix. */ |
12228 | bpr | 1623 | substit(buf1); substit(buf2); |
1624 | if(rows2lines(buf2)) sep=';'; |
||
1625 | if(strchr(buf1,',')==NULL && wordchr(buf1,"to")==NULL |
||
1626 | && strstr(buf1,"..")==NULL) sep=','; |
||
1627 | buf[0]=0; bufp=buf; |
||
1628 | for(p1=buf2; *p1; p1=p2) { |
||
1629 | char ibuf[MAX_LINELEN+1]; |
||
1630 | p2=strchr(p1,'\n'); |
||
1631 | if(p2==NULL) p2=p1+strlen(p1); else *p2++=0; |
||
1632 | snprintf(ibuf,sizeof(ibuf),"%s of %s",buf1,p1); |
||
1633 | calc_itemof(ibuf); |
||
1634 | snprintf(bufp,MAX_LINELEN-(bufp-buf),"%s%c",ibuf,sep); |
||
1635 | bufp+=strlen(bufp); |
||
1636 | } |
||
1637 | if(buf[0]!=0) buf[strlen(buf)-1]=0; |
||
1638 | mystrncpy(p,buf,MAX_LINELEN); |
||
10 | reyssat | 1639 | } |
1640 | |||
7673 | bpr | 1641 | /* find roots of a function or equation in a given zone */ |
10 | reyssat | 1642 | void calc_solve(char *p) |
1643 | { |
||
12228 | bpr | 1644 | char *pp, *fp, *forp; |
1645 | char buf[MAX_LINELEN+1], vbuf[MAX_LINELEN+1]; |
||
1646 | double v, dd, start, stop, step, old, v1, v2, v3, d1, d3; |
||
1647 | int i, pos; |
||
7404 | bpr | 1648 | |
12228 | bpr | 1649 | forp=wordchr(p,"for"); |
1650 | if(forp==NULL) { syntax: module_error("syntax_error"); *p=0; return; } |
||
1651 | *forp=0; forp+=strlen("for"); |
||
1652 | fp=find_word_start(p); strip_trailing_spaces(fp); |
||
1653 | if(*fp==0) goto syntax; |
||
1654 | i=cutfor(forp,NULL); if(i<0 || forstruct.type==for_in) goto syntax; |
||
1655 | if(i>0) {*p=0; return;} |
||
1656 | start=forstruct.from; stop=forstruct.to; forp=forstruct.var; |
||
1657 | mystrncpy(buf,fp,sizeof(buf)); substitute(buf); |
||
1658 | *p=0; pp=strchr(buf,'='); if(pp!=NULL) { |
||
1659 | if(strlen(buf)>=MAX_LINELEN-16) return; |
||
1660 | strcat(buf,")"); |
||
1661 | string_modify(buf,pp,pp+1,"-("); |
||
1662 | } |
||
1663 | i=0; for(fp=varchr(buf,forp); fp!=NULL; fp=varchr(fp,forp)) { |
||
1664 | string_modify(buf,fp,fp+strlen(forp),EV_X); fp+=strlen(EV_X); i++; |
||
1665 | } |
||
1666 | if(i==0 || start==stop) return; |
||
1667 | evalue_compile(buf); pos=eval_getpos(EV_X); |
||
1668 | if(start>stop) {dd=start; start=stop; stop=dd;} |
||
1669 | step=(stop-start)/100; if(step==0) return; |
||
1670 | pp=p; old=0; |
||
1671 | for(v=start; v<=stop; v+=step, old=dd) { |
||
1672 | eval_setval(pos,v); |
||
1673 | dd=checked_eval(buf); |
||
1674 | if(v==start) continue; |
||
1675 | if(!isfinite(old) || !isfinite(dd) || (old>0 && dd>0) || (old<0 && dd<0)) |
||
1676 | continue; |
||
1677 | if(dd==0 && v<stop) continue; |
||
1678 | v1=v-step; v2=v; d1=old; |
||
1679 | for(i=0;i<30;i++) { |
||
1680 | v3=(v1+v2)/2; eval_setval(pos,v3); |
||
1681 | d3=checked_eval(buf); |
||
1682 | if(!isfinite(d3)) goto next; |
||
1683 | if((d1>0 && d3>0) || (d1<0 && d3<0)) {d1=d3; v1=v3;} |
||
1684 | else {v2=v3;} |
||
10 | reyssat | 1685 | } |
12228 | bpr | 1686 | float2str(v3,vbuf); if(pp-p+strlen(vbuf)<MAX_LINELEN-1) { |
1687 | if(pp>p) *pp++=','; |
||
1688 | ovlstrcpy(pp,vbuf); |
||
1689 | pp+=strlen(pp); |
||
10 | reyssat | 1690 | } |
12228 | bpr | 1691 | else break; |
1692 | next: ; |
||
1693 | } |
||
10 | reyssat | 1694 | } |
1695 | |||
7673 | bpr | 1696 | /* type: 1=values, 2=sum, 3=product, 4=recursion, 5=subst */ |
10 | reyssat | 1697 | void _values(char *p, int type) |
1698 | { |
||
12228 | bpr | 1699 | char *pp, *fp, *forp; |
1700 | char vbuf[MAX_LINELEN+1], buf[MAX_LINELEN+1], fbuf[MAX_LINELEN+1], tbuf[MAX_LINELEN+1]; |
||
1701 | char *f[64]; |
||
1702 | double v, dd, start, stop, step, v0; |
||
1703 | int i, k, fcnt, pos, posr; |
||
7404 | bpr | 1704 | |
12228 | bpr | 1705 | forp=wordchr(p,"for"); |
1706 | if(forp==NULL) { syntax: module_error("syntax_error"); *p=0; return; } |
||
1707 | *forp=0; forp+=strlen("for"); forp=find_word_start(forp); |
||
1708 | fp=find_word_start(p); strip_trailing_spaces(fp); |
||
1709 | if(*fp==0) goto syntax; |
||
1710 | if(type<5) i=cutfor(forp,NULL); else i=cutfor(forp,tbuf); |
||
1711 | if(i<0) goto syntax; |
||
1712 | if(i>0) {*p=0; return;} |
||
1713 | start=forstruct.from; stop=forstruct.to; step=forstruct.step; |
||
1714 | forp=forstruct.var; |
||
1715 | mystrncpy(buf,fp,sizeof(buf)); substitute(buf); |
||
1716 | for(fp=varchr(buf,forp); fp!=NULL; fp=varchr(fp,forp)) { |
||
1717 | string_modify(buf,fp,fp+strlen(forp),EV_X); fp+=strlen(EV_X); |
||
1718 | } |
||
1719 | for(fp=varchr(buf,"last"); fp!=NULL; fp=varchr(fp,"last")) { |
||
1720 | string_modify(buf,fp,fp+strlen("last"),EV_S); fp+=strlen(EV_S); |
||
1721 | } |
||
1722 | fcnt=pos=posr=0; |
||
1723 | if(type==5) goto skip; |
||
1724 | fcnt=itemnum(buf); if(fcnt>64) fcnt=64; pp=fbuf; |
||
1725 | for(k=0; k<fcnt; k++) { |
||
1726 | fnd_item(buf,k+1,vbuf); evalue_compile(vbuf); |
||
1727 | if(pp-fbuf+strlen(vbuf)<MAX_LINELEN-1) { |
||
1728 | f[k]=pp; ovlstrcpy(pp,vbuf); pp+=strlen(pp)+1; |
||
10 | reyssat | 1729 | } |
12228 | bpr | 1730 | else f[k]=""; |
1731 | } |
||
1732 | pos=eval_getpos(EV_X); posr=eval_getpos(EV_S); |
||
1733 | skip: |
||
1734 | if(step==0) step=1;/* if(step<0) step=-step; |
||
1735 | if(stop<start) {dd=start; start=stop; stop=dd;} */ |
||
1736 | *p=0; v0=0; |
||
1737 | switch(type) { |
||
1738 | case 4: |
||
1739 | case 1: { |
||
1740 | pp=getvar("recursion_start"); |
||
1741 | if(pp==NULL || *pp==0) v0=0; |
||
1742 | else { |
||
1743 | v0=evalue(pp); if(!isfinite(v0)) return; |
||
1744 | } |
||
1745 | break; |
||
10 | reyssat | 1746 | } |
12228 | bpr | 1747 | case 2: v0=0; break; |
1748 | case 3: v0=1; break; |
||
1749 | case 5: break; |
||
10 | reyssat | 1750 | } |
1751 | pp=p; |
||
1752 | if(type==5) { |
||
12228 | bpr | 1753 | char *ps, *pt, buf2[MAX_LINELEN+1]; |
1754 | int l,ln; |
||
1755 | *p=0; l=strlen(buf); if(l>=MAX_LINELEN) return; |
||
1756 | for(i=0,v=start; i<MAX_VALUE_LIST && v*step<=stop*step; v+=step, i++) { |
||
1757 | if(forstruct.type==for_from) { |
||
7673 | bpr | 1758 | float2str(v,vbuf); ps=vbuf; |
12228 | bpr | 1759 | } |
1760 | else ps=forstruct.pos[i]; |
||
1761 | ovlstrcpy(buf2,buf); l=strlen(ps);ln=strlen(EV_X); |
||
1762 | for(pt=varchr(buf2,EV_X);pt!=NULL;pt=varchr(pt+l,EV_X)) |
||
1763 | string_modify(buf2,pt,pt+ln,"%s",ps); |
||
1764 | if(pp-p+strlen(buf2)>=MAX_LINELEN-1) return; |
||
1765 | if(pp>p) *pp++=','; |
||
1766 | ovlstrcpy(pp,buf2); |
||
1767 | pp+=strlen(pp); |
||
1768 | } |
||
1769 | return; |
||
10 | reyssat | 1770 | } |
1771 | for(i=0,v=start; i<MAX_VALUE_LIST && v*step<=stop*step; v+=step, i++) { |
||
12228 | bpr | 1772 | if(forstruct.type==for_from) eval_setval(pos,v); |
1773 | else eval_setval(pos,forstruct.list[i]); |
||
1774 | eval_setval(posr,v0); |
||
1775 | for(k=0; k<fcnt; k++) { |
||
1776 | dd=checked_eval(f[k]); |
||
1777 | switch(type) { |
||
7673 | bpr | 1778 | case 1: { /* values */ |
12228 | bpr | 1779 | float2str(dd,vbuf); |
1780 | if(pp-p+strlen(vbuf)<MAX_LINELEN-1) { |
||
1781 | if(pp>p) *pp++=','; |
||
1782 | ovlstrcpy(pp,vbuf); |
||
1783 | pp+=strlen(pp); |
||
1784 | } |
||
1785 | v0=dd; break; |
||
7673 | bpr | 1786 | } |
12228 | bpr | 1787 | case 2: { /* sum */ |
1788 | v0=v0+dd; break; |
||
1789 | } |
||
1790 | case 3: { /* product */ |
||
1791 | v0=v0*dd; break; |
||
1792 | } |
||
1793 | case 4: { /* recursion */ |
||
1794 | v0=dd; break; |
||
1795 | } |
||
1796 | } |
||
10 | reyssat | 1797 | } |
12228 | bpr | 1798 | } |
1799 | if(type!=1) float2str(v0,p); |
||
10 | reyssat | 1800 | } |
1801 | |||
7673 | bpr | 1802 | /* cut a function into values */ |
10 | reyssat | 1803 | void calc_values(char *p) |
1804 | { _values(p,1); } |
||
1805 | |||
7673 | bpr | 1806 | /* compute sum */ |
10 | reyssat | 1807 | void calc_sum(char *p) |
1808 | { _values(p,2); } |
||
1809 | |||
7673 | bpr | 1810 | /* compute product */ |
10 | reyssat | 1811 | void calc_product(char *p) |
1812 | { _values(p,3); } |
||
1813 | |||
7673 | bpr | 1814 | /* simple recursion */ |
10 | reyssat | 1815 | void calc_recursion(char *p) |
1816 | { _values(p,4); } |
||
1817 | |||
7673 | bpr | 1818 | /* List substitution */ |
10 | reyssat | 1819 | void calc_makelist(char *p) |
1820 | { _values(p,5); } |
||
1821 | |||
7673 | bpr | 1822 | /* level curve data */ |
10 | reyssat | 1823 | void calc_leveldata(char *p) |
1824 | { |
||
12228 | bpr | 1825 | leveldata ld; |
1826 | char *sizep, *rangep, *fp, *levelp, *stepp; |
||
1827 | char *pp,*p2,fbuf[MAX_LINELEN+1],buf[MAX_LINELEN+1]; |
||
1828 | double d[4]; |
||
1829 | int i; |
||
7404 | bpr | 1830 | |
12228 | bpr | 1831 | sizep=wordchr(p,"size"); |
1832 | rangep=wordchr(p,"ranges"); |
||
1833 | fp=wordchr(p,"function"); |
||
1834 | levelp=wordchr(p,"levels"); |
||
1835 | stepp=wordchr(p,"step"); |
||
1836 | if(sizep==NULL || rangep==NULL || fp==NULL) { |
||
1837 | syntax: module_error("syntax_error"); *p=0; return; |
||
1838 | } |
||
1839 | *sizep=0; sizep+=strlen("size"); |
||
1840 | *rangep=0; rangep+=strlen("ranges"); |
||
1841 | *fp=0; fp+=strlen("function"); |
||
1842 | if(levelp!=NULL) {*levelp=0; levelp+=strlen("levels");} |
||
1843 | else levelp="0"; |
||
1844 | if(stepp!=NULL) {*stepp=0; stepp+=strlen("step");} |
||
1845 | else stepp="0"; |
||
1846 | mystrncpy(fbuf,fp,sizeof(fbuf)); substitute(fbuf); |
||
1847 | ld.fn=fbuf; |
||
1848 | ld.xname="x"; ld.yname="y"; ld.grain=evalue(stepp); |
||
1849 | mystrncpy(buf,sizep,sizeof(buf)); substitute(buf); |
||
1850 | for(i=0,pp=buf;i<2;i++,pp=p2) { |
||
1851 | if(*pp==0) goto syntax; |
||
1852 | p2=find_item_end(pp); if(*p2) *p2++=0; |
||
1853 | d[i]=evalue(pp); |
||
1854 | } |
||
1855 | ld.xsize=d[0]; ld.ysize=d[1]; |
||
1856 | mystrncpy(buf,rangep,sizeof(buf)); substitute(buf); |
||
1857 | for(i=0,pp=buf;i<4;i++,pp=p2) { |
||
1858 | if(*pp==0) goto syntax; |
||
1859 | p2=find_item_end(pp); if(*p2) *p2++=0; |
||
1860 | d[i]=evalue(pp); |
||
1861 | } |
||
1862 | ld.xrange[0]=d[0]; ld.xrange[1]=d[1]; ld.yrange[0]=d[3]; ld.yrange[1]=d[2]; |
||
1863 | mystrncpy(buf,levelp,sizeof(buf)); substitute(buf); |
||
1864 | ld.levelcnt=itemnum(buf); if(ld.levelcnt>LEVEL_LIM) ld.levelcnt=LEVEL_LIM; |
||
1865 | for(i=0,pp=buf;i<ld.levelcnt;i++,pp=p2) { |
||
1866 | if(*pp==0) goto syntax; |
||
1867 | p2=find_item_end(pp); if(*p2) *p2++=0; |
||
1868 | ld.levels[i]=evalue(pp); |
||
1869 | } |
||
1870 | levelcurve(&ld); |
||
1871 | for(i=0, pp=p; i<ld.datacnt && pp<p+MAX_LINELEN-16; i++) { |
||
1872 | float2str(ld.xdata[i],buf); |
||
1873 | if(pp-p+strlen(buf)<MAX_LINELEN-1) { |
||
1874 | if(pp>p) *pp++=';'; |
||
1875 | ovlstrcpy(pp,buf); pp+=strlen(pp); |
||
10 | reyssat | 1876 | } |
12228 | bpr | 1877 | float2str(ld.ydata[i],buf); |
1878 | if(pp-p+strlen(buf)<MAX_LINELEN-1) { |
||
1879 | if(pp>p) *pp++=','; |
||
1880 | ovlstrcpy(pp,buf); pp+=strlen(pp); |
||
10 | reyssat | 1881 | } |
12228 | bpr | 1882 | } |
10 | reyssat | 1883 | } |
1884 | |||
7673 | bpr | 1885 | /* internal routine with no security check */ |
10 | reyssat | 1886 | void _lookup(char *p, char *fname) |
1887 | { |
||
12228 | bpr | 1888 | char buf1[MAX_LINELEN+1]; |
1889 | char *p1, *p2, *mbuf; |
||
10 | reyssat | 1890 | |
12228 | bpr | 1891 | mbuf=readfile(fname,NULL,WORKFILE_LIMIT); |
1892 | if(mbuf==NULL) {abort: *p=0; return;} |
||
1893 | p1=find_word_start(p); strip_trailing_spaces(p1); |
||
1894 | snprintf(buf1,sizeof(buf1),"%s:",p1); substit(buf1); |
||
1895 | for(p1=strstr(mbuf,buf1); |
||
1896 | p1!=NULL && p1>mbuf && *(p1-1)!='\n'; |
||
1897 | p1=strstr(p1+1,buf1)); |
||
1898 | if(p1==NULL) {free(mbuf); goto abort;} |
||
1899 | p1+=strlen(buf1); |
||
1900 | for(p2=strchr(p1,'\n'); p2!=NULL; p2=strchr(p2+1,'\n')) { |
||
1901 | if(p2>p1 && *(p2-1)=='\\') {*(p2-1)=' '; continue;} |
||
1902 | else break; |
||
1903 | } |
||
1904 | if(p2==NULL) p2=p1+strlen(p1); else *p2=0; |
||
1905 | mystrncpy(p,p1,MAX_LINELEN); free(mbuf); |
||
10 | reyssat | 1906 | } |
1907 | |||
7673 | bpr | 1908 | /* lookup a definition in a definition file */ |
10 | reyssat | 1909 | void calc_lookup(char *p) |
1910 | { |
||
12228 | bpr | 1911 | char buf2[MAX_LINELEN+1], buf3[MAX_FNAME+1]; |
1912 | char *p2; |
||
7404 | bpr | 1913 | |
12228 | bpr | 1914 | p2=wordchr(p,"in"); if(p2==NULL) {abort: *p=0; return;} |
1915 | *p2=0;p2=find_word_start(p2+2); |
||
1916 | mystrncpy(buf2,p2,sizeof(buf2)); substit(buf2); |
||
1917 | *find_word_end(buf2)=0; |
||
1918 | if(strstr(buf2,parent_dir_string)!=NULL) { |
||
1919 | force_setvar("wims_error_data",buf2); module_error("illegal_cmd"); |
||
1920 | } |
||
1921 | if(strncmp(buf2,"bases/",strlen("bases/"))!=0) { |
||
1922 | if(datafile_check(buf2)!=0 || find_module_file(buf2,buf3,0)!=0) |
||
1923 | goto abort; |
||
1924 | _lookup(p,buf3); |
||
1925 | } |
||
1926 | else _lookup(p,buf2); |
||
10 | reyssat | 1927 | } |
1928 | |||
7673 | bpr | 1929 | /* Hide name of a file. Only in module directory or in gifs/ */ |
10 | reyssat | 1930 | void calc_rename(char *p) |
1931 | { |
||
12228 | bpr | 1932 | char buf1[MAX_LINELEN+1], buf2[MAX_LINELEN+1]; |
1933 | char *p1, *ext, *s; |
||
1934 | int t; |
||
7404 | bpr | 1935 | |
12228 | bpr | 1936 | if(robot_access || strstr(p,"getfile")!=NULL) return; |
1937 | p1=find_word_start(p); *find_word_end(p1)=0; |
||
1938 | if(strncmp(p1,ref_name,strlen(ref_name))==0) p1+=strlen(ref_name); |
||
1939 | if(p1>p) ovlstrcpy(p,p1); |
||
1940 | if(strstr(p,parent_dir_string)!=NULL || |
||
1941 | strncmp(p,"modules/adm/",strlen("modules/adm/"))==0) { |
||
1942 | badfile: force_setvar("wims_error_data",p); module_error("illegal_cmd"); |
||
1943 | } |
||
1944 | if(strncmp(p,module_dir,strlen(module_dir))!=0 && |
||
1945 | strncmp(p,"modules/data/",strlen("modules/data/"))!=0 && |
||
1946 | strncmp(p,"scripts/data/",strlen("scripts/data/"))!=0 && |
||
1947 | strncmp(p,"gifs",strlen("gifs"))!=0) goto badfile; |
||
1948 | mkfname(buf1,"%s/getfile",session_prefix); mkdirs(buf1); |
||
1949 | mkfname(buf1,"%s/.rename",session_prefix); |
||
1950 | mystrncpy(buf2,p,sizeof(buf2)); _lookup(buf2,buf1); |
||
1951 | if(buf2[0]!=0) { /* already */ |
||
1952 | mystrncpy(p,buf2,MAX_LINELEN); return; |
||
1953 | } |
||
1954 | if(cwdbuf[0]==0) return; |
||
1955 | p1=p+strlen(p)-1; |
||
1956 | while(p1>p && isalnum(*p1)) p1--; |
||
1957 | if(p1>p && *p1=='.') ext=p1; else ext=""; |
||
1958 | rerand: t=random(); |
||
1959 | mkfname(buf1,"%s/%s",cwdbuf,p); |
||
1960 | mkfname(buf2,"%s/getfile/rename-%u%s",session_prefix,t,ext); |
||
1961 | if(ftest(buf2)>=0) goto rerand; |
||
1962 | (void) symlink(buf1,buf2); |
||
1963 | s=getvar("wims_session"); if(s==NULL) return; |
||
1964 | if(good_httpd) snprintf(buf1,sizeof(buf1), |
||
7673 | bpr | 1965 | "getfile/rename-%u%s?session=%s", t,ext,s); |
12228 | bpr | 1966 | else snprintf(buf1,sizeof(buf1),"%s?cmd=getfile&+session=%s&+special_parm=rename-%u%s", |
7673 | bpr | 1967 | ref_name, s, t,ext); |
12228 | bpr | 1968 | snprintf(buf2,sizeof(buf2),"%s:%s\n",p,buf1); |
1969 | accessfile(buf2,"a","%s/.rename",session_prefix); |
||
1970 | mystrncpy(p,buf1,MAX_LINELEN); |
||
10 | reyssat | 1971 | } |
1972 | |||
7673 | bpr | 1973 | /* Pick up and translate imgrename(...) within a string */ |
10 | reyssat | 1974 | void calc_imgrename(char *p) |
1975 | { |
||
12228 | bpr | 1976 | char buf[MAX_LINELEN+1], buf2[MAX_LINELEN+1]; |
1977 | char *p1, *p2, *p3, *p4; |
||
7404 | bpr | 1978 | |
12228 | bpr | 1979 | for(p1=varchr(p,"imgrename"); p1!=NULL; p1=varchr(p1,"imgrename")) { |
1980 | p2=find_word_start(p1+strlen("imgrename")); |
||
1981 | if(*p2!='(') {p1=p2; continue;} |
||
1982 | p2++; p3=find_matching(p2,')'); |
||
1983 | if(*p3!=')') {p1=p2-1; continue;} |
||
1984 | p2=find_word_start(p2); p4=find_word_end(p2); |
||
7673 | bpr | 1985 | memmove(buf,p2,p4-p2); buf[p4-p2]=0; |
12228 | bpr | 1986 | calc_rename(buf); *p3=0; |
17177 | bpr | 1987 | snprintf(buf2,sizeof(buf2),"<img src=\"%s\"%s alt=\"\">",buf, p4); |
12228 | bpr | 1988 | *p3=')'; p3++; |
1989 | string_modify(p,p1,p3,"%s",buf2); |
||
1990 | p1+=strlen(buf2); |
||
1991 | } |
||
10 | reyssat | 1992 | } |
1993 | |||
7673 | bpr | 1994 | /* internal use only */ |
10 | reyssat | 1995 | void calc_unhttp(char *p) |
1996 | { |
||
12228 | bpr | 1997 | _http2env(tmplbuf,p); mystrncpy(p,tmplbuf,MAX_LINELEN); |
10 | reyssat | 1998 | } |
1999 | |||
2000 | /* |
||
15328 | bpr | 2001 | method BDSi not maintained in linux: |
2002 | ...0 gives the number of DES rounds (2 here) _...0smiw |
||
2003 | come back to "Nv", basic DES |
||
10 | reyssat | 2004 | */ |
15324 | bpr | 2005 | void _passcrypt(char *p, char *salted_hash) |
10 | reyssat | 2006 | { |
2007 | #ifdef HAVE_CRYPT |
||
15328 | bpr | 2008 | char* saltstr=salted_hash ? salted_hash: "Nv"; |
12228 | bpr | 2009 | char *p1, *p2, *pp, *s, buf[MAX_LINELEN+1]; |
15324 | bpr | 2010 | buf[0]=0; pp=buf; |
12228 | bpr | 2011 | for(p1=find_word_start(p);*p1;p1=find_word_start(p2)) { |
2012 | p2=find_word_end(p1); if(*p2) *p2++=0; |
||
2013 | pp=pp+strlen(pp); |
||
2014 | if(pp>buf) s=" "; else s=""; |
||
2015 | if(*p1=='*') |
||
2016 | snprintf(pp,MAX_LINELEN-(pp-buf),"%s%s",s,p1); |
||
2017 | else |
||
2018 | snprintf(pp,MAX_LINELEN-(pp-buf),"%s*%s",s,crypt(p1,saltstr)); |
||
2019 | } |
||
2020 | ovlstrcpy(p,buf); |
||
10 | reyssat | 2021 | #endif |
2022 | } |
||
2023 | |||
15324 | bpr | 2024 | void calc_passcrypt(char *p) |
2025 | { |
||
2026 | _passcrypt(p, NULL); |
||
2027 | } |
||
2028 | /* |
||
2029 | syntax: passcheck nocrypt and list of words as *cryptwords |
||
15328 | bpr | 2030 | check if the passcrypt of nocrypt is amongst the list of words |
15324 | bpr | 2031 | */ |
2032 | void calc_passcheck(char *p) |
||
2033 | { |
||
2034 | char cl[MAX_LINELEN+1],sh[MAX_LINELEN+1]; |
||
2035 | char *qq, *pp=wordchr(p,"and"); |
||
2036 | if(pp==NULL) module_error("syntax_error"); |
||
2037 | *pp=0;ovlstrcpy(cl,p); ovlstrcpy(sh,pp+strlen("and")); |
||
2038 | substit(cl); substit(sh); |
||
2039 | for (pp = sh;*pp; pp=qq){ |
||
2040 | while (*pp && *pp != '*') ++pp; |
||
2041 | /* delete the star */ |
||
2042 | pp++; |
||
2043 | if(!*pp) break; |
||
2044 | for (qq = pp; *qq && *qq != ' '; ++qq); |
||
2045 | if (*qq) *qq++ = 0; |
||
2046 | _passcrypt(cl, pp); |
||
2047 | if (!strcmp(cl+1, pp)) |
||
2048 | {ovlstrcpy(p, "yes"); return;} |
||
2049 | } |
||
2050 | ovlstrcpy(p, "no"); |
||
2051 | } |
||
2052 | |||
10 | reyssat | 2053 | void exec_readproc(char *p); |
2054 | |||
7673 | bpr | 2055 | /* crypted mail interface */ |
10 | reyssat | 2056 | void calc_mailurl(char *p) |
2057 | { |
||
12228 | bpr | 2058 | char *p0, buf[MAX_LINELEN+1]; |
7404 | bpr | 2059 | |
12228 | bpr | 2060 | if(robot_access) {*p=0; return;} |
2061 | snprintf(buf,sizeof(buf),"mailurl.proc %s",p); |
||
2062 | exec_readproc(buf); |
||
2063 | p0=getvar("mailurl_"); if(p0==NULL) p0=""; |
||
2064 | mystrncpy(p,p0,MAX_LINELEN); |
||
10 | reyssat | 2065 | } |
2066 | |||
7673 | bpr | 2067 | /* get option word in a string */ |
10 | reyssat | 2068 | void calc_getopt(char *p) |
2069 | { |
||
12228 | bpr | 2070 | char *p1, *p2, *p3, *p4; |
2071 | char buf1[MAX_LINELEN+1], buf2[MAX_LINELEN+1]; |
||
7404 | bpr | 2072 | |
12228 | bpr | 2073 | p1=wordchr(p,"in"); if(p1==NULL) module_error("syntax error"); |
2074 | *p1=0; p1=find_word_start(p1+3); |
||
2075 | mystrncpy(buf1,p,MAX_LINELEN); mystrncpy(buf2,p1,MAX_LINELEN); |
||
2076 | substitute(buf1); substitute(buf2); |
||
2077 | p1=find_word_start(buf1); *find_word_end(p1)=0; |
||
2078 | for(p2=buf2;*p2;p2++) { |
||
2079 | if(myisspace(*p2)) *p2=' '; |
||
2080 | if(*p2=='=') *p2=' '; |
||
2081 | } |
||
2082 | *p=0; |
||
2083 | p2=wordchr(buf2,p1); if(p2==NULL) return; |
||
2084 | for(p3=find_word_end(p2);myisspace(*p3);p3++) { |
||
2085 | if(*p3==' ') { |
||
2086 | p3=find_word_start(p3); |
||
2087 | switch(*p3) { |
||
2088 | case '"': { |
||
2089 | p4=strchr(p3+1,'"'); |
||
2090 | goto tested; |
||
2091 | } |
||
2092 | case '(': { |
||
2093 | p4=find_matching(p3+1,')'); |
||
2094 | goto tested; |
||
2095 | } |
||
2096 | case '[': { |
||
2097 | p4=find_matching(p3+1,']'); |
||
2098 | goto tested; |
||
2099 | } |
||
2100 | case '{': { |
||
2101 | p4=find_matching(p3+1,'}'); |
||
2102 | tested: |
||
2103 | if(p4) { |
||
2104 | p3++; *p4=0; break; |
||
2105 | } |
||
2106 | else goto nomatch; |
||
2107 | } |
||
2108 | default: { |
||
2109 | nomatch: |
||
2110 | *find_word_end(p3)=0; |
||
2111 | } |
||
2112 | } |
||
2113 | mystrncpy(p,p3,MAX_LINELEN); |
||
2114 | return; |
||
10 | reyssat | 2115 | } |
12228 | bpr | 2116 | } |
2117 | *find_word_end(p2)=0; |
||
2118 | mystrncpy(p,p2,MAX_LINELEN); |
||
10 | reyssat | 2119 | } |
2120 | |||
7673 | bpr | 2121 | /* internal */ |
14664 | bpr | 2122 | static void _embraced(char buf[], void (app)(char *p)) |
10 | reyssat | 2123 | { |
12228 | bpr | 2124 | char *p1, *p2, buf2[MAX_LINELEN+1]; |
2125 | for(p1=strchr(buf,'{'); p1; p1=strchr(p1,'{')) { |
||
2126 | p2=find_matching(p1+1,'}'); |
||
2127 | if(p2==NULL) module_error("unmatched_parentheses"); |
||
2128 | *p2=0; mystrncpy(buf2,p1+1,sizeof(buf2)); app(buf2); |
||
2129 | string_modify(buf,p1,p2+1,buf2); |
||
2130 | } |
||
10 | reyssat | 2131 | } |
2132 | |||
14664 | bpr | 2133 | static void _embraced_tree(char buf[]) |
2134 | { |
||
2135 | char *p1, *p2, buf2[MAX_LINELEN+1]; |
||
2136 | int nb, index; |
||
2137 | for (p1=strchr(buf,'{'); p1; p1=strchr(buf,'{')){ |
||
2138 | p2=find_matching(p1+1,'}'); |
||
2139 | if(p2==NULL) module_error("unmatched_parentheses"); |
||
2140 | *p2=0; nb=itemnum(p1+1); *p2='}'; index=(random()%nb)+1; |
||
2141 | for (p1=strchr(buf,'{'); p1; p1=strchr(p1,'{')){ |
||
2142 | p2=find_matching(p1+1,'}'); |
||
2143 | if(p2==NULL) module_error("unmatched_parentheses"); |
||
2144 | *p2=0; fnd_item(p1+1,index,buf2); |
||
2145 | string_modify(buf,p1,p2+1,buf2); |
||
2146 | p1+=strlen(buf2); |
||
2147 | } |
||
2148 | } |
||
2149 | } |
||
2150 | |||
7673 | bpr | 2151 | /* embraced operations */ |
10 | reyssat | 2152 | void calc_embraced(char *p) |
2153 | { |
||
12228 | bpr | 2154 | char *p1, *p2, buf[MAX_LINELEN+1]; |
10 | reyssat | 2155 | |
12228 | bpr | 2156 | p1=find_word_start(p); p2=find_word_end(p1); |
2157 | if(*p2==0) {*p=0; return;} |
||
2158 | *p2++=0; p2=find_word_start(p2); |
||
2159 | mystrncpy(buf,p2,sizeof(buf)); substit(buf); |
||
2160 | if(p1>p) ovlstrcpy(p,p1); |
||
2161 | substit(p); |
||
2162 | if(strcmp(p,"randitem")==0) {_embraced(buf,calc_randitem); goto end;} |
||
14165 | bpr | 2163 | if(strcmp(p,"randrow")==0) {_embraced(buf,calc_randrow); goto end;} |
14664 | bpr | 2164 | if(strcmp(p,"linkedranditem")==0) {_embraced_tree(buf); goto end;} |
12228 | bpr | 2165 | if(strcmp(p,"extract")==0) { |
2166 | p1=strchr(buf,'{'); |
||
2167 | if(p1!=NULL) { |
||
2168 | p2=find_matching(++p1,'}'); |
||
2169 | if(p2!=NULL) { |
||
2170 | memmove(buf,p1,p2-p1); buf[p2-p1]=0; |
||
2171 | } |
||
2172 | else buf[0]=0; |
||
10 | reyssat | 2173 | } |
12228 | bpr | 2174 | else buf[0]=0; |
2175 | goto end; |
||
2176 | } |
||
2177 | if(strcmp(p,"delete")==0) { |
||
2178 | for(p1=strchr(buf,'{'); p1; p1=strchr(p1,'{')) { |
||
2179 | p2=find_matching(p1+1,'}'); |
||
2180 | if(p2) ovlstrcpy(p1,p2+1); else p1++; |
||
10 | reyssat | 2181 | } |
12228 | bpr | 2182 | goto end; |
2183 | } |
||
2184 | module_error("syntax_error"); |
||
7404 | bpr | 2185 | |
12228 | bpr | 2186 | end: |
2187 | mystrncpy(p,buf,MAX_LINELEN); |
||
10 | reyssat | 2188 | } |
2189 | |||
2190 | void calc_rows2lines(char *p) |
||
12228 | bpr | 2191 | { rows2lines(p); } |
10 | reyssat | 2192 | |
2193 | void calc_lines2rows(char *p) |
||
12228 | bpr | 2194 | { lines2rows(p); } |
10 | reyssat | 2195 | |
7673 | bpr | 2196 | /* check whether datamodules exist */ |
10 | reyssat | 2197 | void calc_checkdata(char *p) |
2198 | { |
||
12228 | bpr | 2199 | char *p1, *p2, buf[MAX_LINELEN+1], nbuf[MAX_FNAME+1]; |
2200 | struct stat st; |
||
7404 | bpr | 2201 | |
12228 | bpr | 2202 | memmove(p,"yes",4); |
2203 | p1=getvar("module_data"); |
||
2204 | if(p1==NULL || *p1==0) return; |
||
2205 | snprintf(buf,sizeof(buf),"%s",p1); |
||
2206 | for(p2=buf; *p2; p2++) if(*p2==',' || *p2==';') *p2=' '; |
||
2207 | if(strstr(buf,"..")!=NULL) { |
||
2208 | snprintf(p,MAX_LINELEN,"badly_defined_data_module"); |
||
2209 | return; |
||
2210 | } |
||
2211 | for(p1=find_word_start(buf); *p1; p1=find_word_start(p2)) { |
||
2212 | p2=find_word_end(p1); if(*p2) *p2++=0; |
||
2213 | snprintf(nbuf,sizeof(nbuf),"%s/%s/INDEX",module_dir,p1); |
||
2214 | if(stat(nbuf,&st)<0) { |
||
2215 | snprintf(nbuf,sizeof(nbuf),"%s/%s/index",module_dir,p1); |
||
2216 | if(stat(nbuf,&st)<0) { |
||
2217 | snprintf(p,MAX_LINELEN,"%s",p1); |
||
2218 | return; |
||
2219 | } |
||
10 | reyssat | 2220 | } |
12228 | bpr | 2221 | } |
10 | reyssat | 2222 | } |
2223 | |||
18014 | bpr | 2224 | void calc_getexoindex(char *p){ |
18086 | bpr | 2225 | char *c, *p1, *p2, *p3, *p4; |
2226 | char nbuf[MAX_LINELEN+1], fname[MAX_FNAME+1], buf[MAX_LINELEN+1], |
||
2227 | fcontent[MAX_LINELEN+1]; |
||
18014 | bpr | 2228 | int i, sheet, start=1, stop=MAX_SHEETS; |
2229 | c=getvar("wims_class"); if(c==NULL) return; |
||
18086 | bpr | 2230 | p1=strstr(p, "module="); if(p1==NULL) return; |
2231 | p1=find_word_start(p1+strlen("module=")); |
||
2232 | p2=find_word_end(p1); *p2=0; |
||
18108 | bpr | 2233 | p4=strstr(p2+1, " sheet="); |
2234 | if (p4!=NULL) {*p4=0;start=stop=evalue(p4+strlen(" sheet="));} |
||
18086 | bpr | 2235 | p2=strstr(p2+1, "param="); if(p2==NULL) return; |
2236 | p2=find_word_start(p2+strlen("param=")); |
||
18108 | bpr | 2237 | p3=find_word_end(p2);*p3=0; |
18086 | bpr | 2238 | |
2239 | snprintf(fname,sizeof(fname),"%s/%s/sheets/.severity",class_base,c); |
||
2240 | readfile(fname,fcontent,MAX_LINELEN); |
||
2241 | snprintf(nbuf,sizeof(nbuf),":%s\n%s\n",p1,p2); *p=0; |
||
18014 | bpr | 2242 | for (sheet=start; sheet <= stop; ++sheet){ |
18086 | bpr | 2243 | snprintf(fname,sizeof(fname),"%s/%s/sheets/.sheet%d",class_base,c,sheet); |
2244 | if(readfile(fname,buf,MAX_LINELEN)==NULL) break; |
||
18014 | bpr | 2245 | p1=strstr(buf,nbuf); |
2246 | while(p1>buf && *(p1-1)!='\n') p1=strstr(p1+1,nbuf); |
||
2247 | if(p1!=NULL) { |
||
2248 | p2=strchr(buf,':'); |
||
2249 | while(p2>buf && *(p2-1)!='\n') p2=strchr(p2+1,':'); |
||
2250 | for(i=1;p2!=NULL && p2<p1;i++) { |
||
2251 | p2=strchr(p2+1,':'); |
||
2252 | while(p2>buf && *(p2-1)!='\n') p2=strchr(p2+1,':'); |
||
2253 | } |
||
2254 | if(p2==NULL) return; |
||
18086 | bpr | 2255 | fnd_line(fcontent,sheet+1,buf); |
2256 | if(!buf[0]) getdef("bases/sys/define.conf","DF_SEVERITY",buf); |
||
2257 | snprintf(p,20,"%d/%d,%s",sheet,i,buf); |
||
18014 | bpr | 2258 | break; |
2259 | } |
||
2260 | } |
||
2261 | } |
||
2262 | |||
7673 | bpr | 2263 | /* tag!=0 if we don't want automatic substit(). */ |
10 | reyssat | 2264 | MYFUNCTION calc_routine[]={ |
7673 | bpr | 2265 | {"TeXmath", 0, texmath}, |
2266 | {"add", 1, calc_sum}, |
||
2267 | {"append", 1, calc_append}, |
||
2268 | {"call", 0, calc_exec}, |
||
2269 | {"char", 1, calc_charof}, |
||
2270 | {"charcnt", 0, calc_lengthof}, |
||
2271 | {"charcount", 0, calc_lengthof}, |
||
2272 | {"charno", 0, calc_lengthof}, |
||
2273 | {"charnum", 0, calc_lengthof}, |
||
2274 | {"chars", 1, calc_charof}, |
||
15588 | bpr | 2275 | {"checkallpar",0,calc_checkallpar}, |
7673 | bpr | 2276 | {"checkdata", 0, calc_checkdata}, |
2277 | {"checkdatamodule",0, calc_checkdata}, |
||
2278 | {"checkhost", 0, calc_checkhost}, |
||
2279 | {"column", 1, calc_columnof}, |
||
2280 | {"columns", 1, calc_columnof}, |
||
2281 | {"daemon", 0, calc_daemon}, |
||
2282 | {"date", 0, calc_date}, |
||
2283 | {"deaccent", 0, deaccent}, |
||
2284 | {"debug", 0, calc_debug}, |
||
2285 | {"declosing", 0, calc_declosing}, |
||
2286 | {"definitionof", 1, calc_defof}, |
||
2287 | {"defof", 1, calc_defof}, |
||
2288 | {"detag", 0, calc_detag}, |
||
2289 | /* {"dictionary", 1, calc_dictionary}, */ |
||
2290 | {"dir", 0, calc_listfile}, |
||
2291 | {"embraced", 1, calc_embraced}, |
||
2292 | {"encyclo", 0, pedia}, |
||
2293 | {"encyclopedia", 0, pedia}, |
||
2294 | {"eval", 0, calc_evalue}, |
||
2295 | {"evalsubst", 1, calc_evalsubst}, |
||
2296 | {"evalsubstit", 1, calc_evalsubst}, |
||
2297 | {"evalsubstitute",1, calc_evalsubst}, |
||
2298 | {"evalue", 0, calc_evalue}, |
||
2299 | {"evaluesubst", 1, calc_evalsubst}, |
||
2300 | {"evaluesubstit", 1, calc_evalsubst}, |
||
2301 | {"evaluesubstitute",1, calc_evalsubst}, |
||
2302 | {"examdep", 0, calc_examdep}, |
||
2303 | {"examscore", 0, calc_examscore}, |
||
2304 | {"exec", 0, calc_exec}, |
||
2305 | {"execute", 0, calc_exec}, |
||
12047 | bpr | 2306 | {"fileexists", 0, calc_fileexists}, |
7673 | bpr | 2307 | {"filelist", 0, calc_listfile}, |
12047 | bpr | 2308 | {"filexists", 0, calc_fileexists}, |
7673 | bpr | 2309 | {"getdef", 1, calc_defof}, |
18014 | bpr | 2310 | {"getexoindex", 0, calc_getexoindex}, |
7673 | bpr | 2311 | {"getopt", 1, calc_getopt}, |
2312 | {"getscore", 0, calc_getscore}, |
||
12197 | bpr | 2313 | {"getscorealltries", 0, calc_getscorealltries}, |
7673 | bpr | 2314 | {"getscorebest", 0, calc_getscorebest}, |
2315 | {"getscorelast", 0, calc_getscorelast}, |
||
2316 | {"getscorelevel", 0, calc_getscorelevel}, |
||
12213 | bpr | 2317 | {"getscoremaxexotry",0,calc_getscoremaxexotry}, |
7673 | bpr | 2318 | {"getscoremean",0, calc_getscoremean}, |
2319 | {"getscorepercent",0, calc_getscorepercent}, |
||
2320 | {"getscorequality",0, calc_getscoremean}, |
||
2321 | {"getscoreremain",0, calc_getscoreremain}, |
||
2322 | {"getscorerequire",0, calc_getscorerequire}, |
||
2323 | {"getscorestatus",0, calc_getscorestatus}, |
||
2324 | {"getscoretry", 0, calc_getscoretry}, |
||
2325 | {"getscoreweight",0, calc_getscoreweight}, |
||
12273 | bpr | 2326 | {"getseedlast", 0, calc_getseedlast}, |
12295 | bpr | 2327 | {"getseedlastcnt", 0, calc_getseedlastcnt}, |
12273 | bpr | 2328 | {"getseedscorelast", 0, calc_getseedscorelast}, |
2329 | {"getseedscores", 0, calc_getseedscores}, |
||
18056 | bpr | 2330 | {"getsheetstatus", 0, calc_getsheetstatus}, |
7673 | bpr | 2331 | {"hex", 0, calc_hex}, |
13757 | bpr | 2332 | {"html2iso", 0, calc_html2iso}, |
7673 | bpr | 2333 | {"htmlmath", 0, htmlmath}, |
2334 | {"httpquery", 0, tohttpquery}, |
||
2335 | {"imgrename", 0, calc_imgrename}, |
||
2336 | {"instexst", 1, calc_instexst}, |
||
2337 | {"instexstatic", 1, calc_instexst}, |
||
2338 | {"item", 1, calc_itemof}, |
||
2339 | {"itemcnt", 0, calc_itemnum}, |
||
2340 | {"itemcount", 0, calc_itemnum}, |
||
2341 | {"itemno", 0, calc_itemnum}, |
||
2342 | {"itemnum", 0, calc_itemnum}, |
||
2343 | {"items", 1, calc_itemof}, |
||
2344 | {"items2lines", 0, items2lines}, |
||
2345 | {"items2words", 0, items2words}, |
||
2346 | {"itemstolines", 0, items2lines}, |
||
2347 | {"itemstowords", 0, items2words}, |
||
2348 | {"lengthof", 0, calc_lengthof}, |
||
2349 | {"leveldata", 1, calc_leveldata}, |
||
2350 | {"levelpoints", 1, calc_leveldata}, |
||
2351 | {"line", 1, calc_lineof}, |
||
2352 | {"linecnt", 0, calc_linenum}, |
||
2353 | {"linecount", 0, calc_linenum}, |
||
2354 | {"lineno", 0, calc_linenum}, |
||
2355 | {"linenum", 0, calc_linenum}, |
||
2356 | {"lines", 1, calc_lineof}, |
||
2357 | {"lines2items", 0, lines2items}, |
||
2358 | {"lines2list", 0, lines2items}, |
||
2359 | {"lines2rows", 0, calc_lines2rows}, |
||
2360 | {"lines2words", 0, lines2words}, |
||
2361 | {"linestoitems", 0, lines2items}, |
||
2362 | {"linestolist", 0, lines2items}, |
||
2363 | {"linestowords", 0, lines2words}, |
||
2364 | {"list2lines", 0, items2lines}, |
||
2365 | {"list2words", 0, items2words}, |
||
2366 | {"listcomplement",1, calc_listcomplement}, |
||
2367 | {"listfile", 0, calc_listfile}, |
||
2368 | {"listfiles", 0, calc_listfile}, |
||
2369 | {"listintersect", 1, calc_listintersect}, |
||
2370 | {"listintersection",1, calc_listintersect}, |
||
2371 | {"listtolines", 0, items2lines}, |
||
2372 | {"listtowords", 0, items2words}, |
||
2373 | {"listunion", 1, calc_listunion}, |
||
2374 | {"listuniq", 0, calc_listuniq}, |
||
2375 | {"listunique", 0, calc_listuniq}, |
||
2376 | {"listvar", 0, mathvarlist}, |
||
2377 | {"lookup", 1, calc_lookup}, |
||
2378 | {"lower", 0, calc_tolower}, |
||
2379 | {"lowercase", 0, calc_tolower}, |
||
2380 | {"ls", 0, calc_listfile}, |
||
2381 | {"mailurl", 0, calc_mailurl}, |
||
2382 | {"makelist", 1, calc_makelist}, |
||
2383 | {"math2html", 0, htmlmath}, |
||
2384 | {"math2mathml", 0,mathmlmath}, |
||
2385 | {"math2tex", 0, texmath}, |
||
2386 | {"mathmlmath", 0, mathmlmath}, |
||
2387 | {"mathsubst", 1, calc_mathsubst}, |
||
2388 | {"mathsubstit", 1, calc_mathsubst}, |
||
2389 | {"mathsubstitute",1, calc_mathsubst}, |
||
2390 | {"mexec", 0, calc_mexec}, |
||
2391 | {"module", 0, calc_module}, |
||
2392 | {"multiply", 1, calc_product}, |
||
2393 | {"non_empty", 0, calc_nonempty}, |
||
2394 | {"nonempty", 0, calc_nonempty}, |
||
2395 | {"nospace", 0, nospace}, |
||
2396 | {"nosubst", 1, calc_subst}, |
||
2397 | {"nosubstit", 1, calc_subst}, |
||
2398 | {"nosubstitute", 1, calc_subst}, |
||
15324 | bpr | 2399 | {"passcheck", 1, calc_passcheck}, |
7673 | bpr | 2400 | {"passcrypt", 0, calc_passcrypt}, |
2401 | {"pedia", 0, pedia}, |
||
2402 | {"perl", 0, calc_perl}, |
||
2403 | {"position", 1, calc_pos}, |
||
2404 | {"positionof", 1, calc_pos}, |
||
2405 | {"positions", 1, calc_pos}, |
||
2406 | {"prod", 1, calc_product}, |
||
2407 | {"product", 1, calc_product}, |
||
2408 | {"randchar", 0, calc_randchar}, |
||
2409 | {"randdouble", 0, calc_randdouble}, |
||
2410 | {"randfile", 0, calc_randfile}, |
||
2411 | {"randfloat", 0, calc_randdouble}, |
||
2412 | {"randint", 0, calc_randint}, |
||
2413 | {"randitem", 0, calc_randitem}, |
||
2414 | {"randline", 0, calc_randline}, |
||
2415 | {"random", 0, calc_randdouble}, |
||
2416 | {"randperm", 0, calc_randperm}, |
||
2417 | {"randpermute", 0, calc_randperm}, |
||
2418 | {"randreal", 0, calc_randdouble}, |
||
2419 | {"randrecord", 0, calc_randfile}, |
||
2420 | {"randrow", 0, calc_randrow}, |
||
2421 | {"randword", 0, calc_randword}, |
||
2422 | {"rawmath", 0, rawmath}, |
||
2423 | {"rawmatrix", 0, rawmatrix}, |
||
2424 | {"reaccent", 0, reaccent}, |
||
2425 | {"record", 1, calc_recordof}, |
||
2426 | {"recordcnt", 0, calc_recordnum}, |
||
2427 | {"recordcount", 0, calc_recordnum}, |
||
2428 | {"recordno", 0, calc_recordnum}, |
||
2429 | {"recordnum", 0, calc_recordnum}, |
||
2430 | {"records", 1, calc_recordof}, |
||
2431 | {"recursion", 1, calc_recursion}, |
||
2432 | {"reinput", 0, calc_reinput}, |
||
2433 | {"rename", 0, calc_rename}, |
||
2434 | {"replace", 1, calc_replace}, |
||
2435 | {"rootof", 1, calc_solve}, |
||
2436 | {"row", 1, calc_rowof}, |
||
2437 | {"rowcnt", 0, calc_rownum}, |
||
2438 | {"rowcount", 0, calc_rownum}, |
||
2439 | {"rowno", 0, calc_rownum}, |
||
2440 | {"rownum", 0, calc_rownum}, |
||
2441 | {"rows", 1, calc_rowof}, |
||
2442 | {"rows2lines", 0, calc_rows2lines}, |
||
2443 | {"run", 0, calc_exec}, |
||
2444 | {"select", 1, calc_select}, |
||
2445 | {"sh", 0, calc_sh}, |
||
2446 | {"shuffle", 0, calc_randperm}, |
||
2447 | {"singlespace", 0, singlespace}, |
||
2448 | {"slashsubst", 0, slashsubst}, |
||
14664 | bpr | 2449 | {"solve", 1, calc_solve}, |
2450 | {"sort", 1, calc_sort}, |
||
2451 | /* {"sql", 0, calc_sql}, */ |
||
7673 | bpr | 2452 | {"staticinstex", 1, calc_instexst}, |
2453 | {"stinstex", 1, calc_instexst}, |
||
14664 | bpr | 2454 | {"subst", 0, calc_subst}, |
7673 | bpr | 2455 | {"substit", 0, calc_subst}, |
2456 | {"substitute", 0, calc_subst}, |
||
14664 | bpr | 2457 | {"sum", 1, calc_sum}, |
7673 | bpr | 2458 | {"system", 0, calc_sh}, |
2459 | {"texmath", 0, texmath}, |
||
14664 | bpr | 2460 | {"text", 1, text}, |
2461 | {"tohex", 0, calc_hex}, |
||
7673 | bpr | 2462 | {"tolower", 0, calc_tolower}, |
2463 | {"toupper", 0, calc_toupper}, |
||
2464 | {"translate", 1, calc_translate}, |
||
14664 | bpr | 2465 | {"trim", 0, calc_trim}, |
7673 | bpr | 2466 | {"unhttp", 0, calc_unhttp}, |
14664 | bpr | 2467 | {"upper", 0, calc_toupper}, |
7673 | bpr | 2468 | {"uppercase", 0, calc_toupper}, |
2469 | {"values", 1, calc_values}, |
||
2470 | {"varlist", 0, mathvarlist}, |
||
14664 | bpr | 2471 | {"word", 1, calc_wordof}, |
2472 | {"wordcnt", 0, calc_wordnum}, |
||
2473 | {"wordcount", 0,calc_wordnum}, |
||
2474 | {"wordno", 0, calc_wordnum}, |
||
2475 | {"wordnum", 0, calc_wordnum}, |
||
2476 | {"words", 1, calc_wordof}, |
||
2477 | {"words2items", 0, words2items}, |
||
2478 | {"words2lines", 0, words2lines}, |
||
2479 | {"words2list", 0, words2items}, |
||
2480 | {"wordstoitems", 0,words2items}, |
||
2481 | {"wordstolines", 0,words2lines}, |
||
2482 | {"wordstolist", 0, words2items} |
||
10 | reyssat | 2483 | }; |
8185 | bpr | 2484 | int CALC_FN_NO=(sizeof(calc_routine)/sizeof(calc_routine[0])); |