Subversion Repositories wimsdev

Rev

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,"&lt;");
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]));