Subversion Repositories wimsdev

Rev

Rev 12047 | Rev 12196 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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