Subversion Repositories wimsdev

Rev

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

Rev Author Line No. Line
10 reyssat 1
/*    Copyright (C) 1998-2003 XIAO, Gang of Universite de Nice - Sophia Antipolis
2
 *
3
 *  This program is free software; you can redistribute it and/or modify
4
 *  it under the terms of the GNU General Public License as published by
5
 *  the Free Software Foundation; either version 2 of the License, or
6
 *  (at your option) any later version.
7
 *
8
 *  This program is distributed in the hope that it will be useful,
9
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 *  GNU General Public License for more details.
12
 *
13
 *  You should have received a copy of the GNU General Public License
14
 *  along with this program; if not, write to the Free Software
15
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16
 */
17
 
8185 bpr 18
/* this is part of wims server source.
19
 * This file does execution commands.
20
 */
21
#include "wims.h"
10 reyssat 22
 
23
static void _skip_contents(int isif);
24
 
8213 bpr 25
/* common routine for the two if's. */
10 reyssat 26
static void _exec_if_while(char *p, int numerical, int isif)
27
{
28
    if(compare(p,numerical,0)==0) _skip_contents(isif); /* skip if false */
29
    else if(!isif) m_file.for_idx++;
30
    return;
31
}
32
 
7379 bpr 33
    /* 'if' non-numerical (unless comparisons are < or >, etc.) */
10 reyssat 34
void exec_if(char *p)
35
{
36
    _exec_if_while(p,0,1);
37
}
38
 
8213 bpr 39
/* 'if' numerical. */
10 reyssat 40
void exec_ifval(char *p)
41
{
7379 bpr 42
    _exec_if_while(p,1,1);
10 reyssat 43
}
44
 
45
void _exec_while(char *p, int numerical)
46
{
47
    FOR_STACK *stk;
48
    if(m_file.for_idx>=MAX_FOR_LEVEL) module_error("too_many_fors");
49
    stk=&(m_file.for_stack[m_file.for_idx]);
50
    stk->lineno=m_file.l;
51
    memmove(stk->varname,"?",2);
52
    _exec_if_while(p,numerical,0);
53
}
54
 
8213 bpr 55
/* 'while' non-numerical (unless comparisons are < or >, etc.) */
10 reyssat 56
void exec_while(char *p)
57
{
58
    _exec_while(p,0);
59
}
60
 
8213 bpr 61
/* 'while' numerical. */
10 reyssat 62
void exec_whileval(char *p)
63
{
64
    _exec_while(p,1);
65
}
66
 
67
void exec_endwhile(char *p)
68
{
69
    FOR_STACK *stk;
70
    if(m_file.for_idx<=0) module_error("next_without_for");
71
    stk=&(m_file.for_stack[m_file.for_idx-1]);
72
    if(stk->varname[0]!='?') module_error("next_without_for");
73
    m_file.for_idx--; *p=0;
74
    m_file.linepointer=stk->lineno;
75
    executed_gotos++;
76
    if(executed_gotos>=GOTO_LIMIT) module_error("too_many_gotos");
77
}
78
 
8213 bpr 79
/* Should provide a method to stop infinite loop. */
10 reyssat 80
void exec_goto(char *p)
81
{
82
    char lbuf[MAX_NAMELEN+17];
83
    char *label_start, *line_start;
84
    int old_line;
85
    int i;
86
    executed_gotos++;
87
    if(executed_gotos>=GOTO_LIMIT) module_error("too_many_gotos");
88
    old_line=m_file.l;
89
    label_start=find_word_start(p);
90
    *find_word_end(label_start)=0;
91
    m_file.l=m_file.linepointer=0;
92
    for(i=0;i<m_file.linecnt;i++) {
7379 bpr 93
      if(((m_file.lines[i].isstart)&4)==0) continue;
94
      line_start=find_word_start((m_file.lines[i]).address);
95
      if(line_start>(m_file.lines[i+1]).address && i<m_file.linecnt)
96
        continue;
97
      m_file.linepointer=i;
98
      wgetline(lbuf,MAX_NAMELEN+8,&m_file);
99
      line_start=find_word_start(lbuf);
100
      if(*line_start!=label_prefix_char) continue;
101
      line_start++;*find_word_end(line_start)=0;
102
      if(line_start[0]!='*' && strcmp(line_start,label_start)!=0) continue;
103
      *p=0; i++; return;
10 reyssat 104
    }
105
    m_file.l=old_line;
7379 bpr 106
    setvar(error_data_string,label_start); module_error("label_not_found");
10 reyssat 107
/*    m_file.linepointer=m_file.linecnt; *p=0;
108
    return;
109
*/}
110
 
8213 bpr 111
/* 'else' with or without 'if'.
112
 * Philosophy: we implement a loosely checked grammar.
113
 * We cannot check 'if' grammar if we want to use 'goto'
114
 * together with 'if'.
115
 */
10 reyssat 116
void exec_else(char *p)
117
{
7379 bpr 118
    _skip_contents(1); return;
10 reyssat 119
}
120
 
8213 bpr 121
/* 'endif': nothing needs to be done here. */
10 reyssat 122
void exec_endif(char *p)
123
{
124
    return;
125
}
126
 
8213 bpr 127
/* find out the end of a for loop */
10 reyssat 128
void goto_for_end(void)
129
{
130
    int inner;
131
    char buf[16];
132
    inner=0;
133
    while(m_file.linepointer<m_file.linecnt) {
7379 bpr 134
      if((m_file.lines[m_file.linepointer].isstart&2)==0) {
135
        m_file.linepointer++; continue;
136
      }
137
      if(wgetline(buf,8,&m_file)==EOF) break;
138
      *find_word_end(buf)=0;
139
      if(strcmp(buf,"!for")==0) {
140
        inner++; continue;
141
      }
142
      if(strcmp(buf,"!next")==0) {
143
        if(inner>0) {
144
          inner--; continue;
145
        }
146
        else break;
147
      }
10 reyssat 148
    }
149
}
150
 
8213 bpr 151
/* for */
10 reyssat 152
void exec_for(char *p)
153
{
154
    char *p1, *p2, *p3;
155
    double v1, v2, step;
156
    char buf[MAX_LINELEN+1];
157
    FOR_STACK *stk;
158
 
159
    if(m_file.for_idx>=MAX_FOR_LEVEL) module_error("too_many_fors");
160
    stk=&(m_file.for_stack[m_file.for_idx]);
161
    stk->lineno=m_file.l;
7379 bpr 162
    p1=find_word_start(p);
10 reyssat 163
    for(p2=p1; !isspace(*p2) && *p2!=0 && *p2!='=' ; p2++);
164
    if(*p2==0) syntax: module_error("for_syntax");
165
    if(p2-p1>MAX_NAMELEN) module_error("name_too_long");
166
    memmove(stk->varname,p1,p2-p1);
167
    stk->varname[p2-p1]=0;
168
    p1=find_word_start(p2); if(*p1==0) goto syntax;
169
    if(*p1=='=') {
7379 bpr 170
      p1++;
171
     assign:
172
     stk->from=0;
173
     p2=wordchr(p1,"to");
174
     if(p2==NULL) p2=strstr(p1,"..");
175
     if(p2==NULL) goto syntax;
176
     *p2=0; p2+=2;
177
     p3=wordchr(p2,"step");
178
     if(p3!=NULL) {
179
        *p3=0; p3+=strlen("step");
180
        step=evalue(p3);
181
        if(step==0) module_error("zero_step");
182
     }
183
     else step=1;
184
     v1=evalue(p1); v2=evalue(p2);
185
     float2str(v1,buf); setvar(stk->varname, buf);
186
     if((step>0 && v1>v2) || (step<0 && v1<v2) ) {  /* condition not met */
10 reyssat 187
  loop_out:
7379 bpr 188
        goto_for_end();
189
      }
190
     else {
191
        stk->varval=v1; stk->varend=v2; stk->step=step;
192
        stk->lineno=m_file.linepointer;
193
        m_file.for_idx++;
194
     }
195
     *p=0; return;
10 reyssat 196
    }
197
    if(memcmp(p1,"from",strlen("from"))==0 && isspace(*(p1+strlen("from")))) {
7379 bpr 198
      p1+=strlen("from"); goto assign;
10 reyssat 199
    }
200
    if(memcmp(p1,"in",strlen("in"))==0 && isspace(*(p1+strlen("in")))) {
7379 bpr 201
      stk->from=1; p1+=strlen("in");
202
      p1=find_word_start(p1); if(*p1==0) goto loop_out;
203
      p2=xmalloc(MAX_LINELEN+1);
204
      mystrncpy(p2,p1,MAX_LINELEN);
205
      substit(p2);
206
      strip_trailing_spaces(p2);
207
      if(*p2==0) goto loop_out;
208
      p1=strparchr(p2,','); stk->bufpt=p2;
209
      if(p1!=NULL) {
210
        *p1=0; stk->list_pt=find_word_start(p1+1);
211
      }
212
      else stk->list_pt=NULL;
213
      strip_trailing_spaces(p2); setvar(stk->varname,p2);
214
      stk->lineno=m_file.linepointer;
215
      m_file.for_idx++; *p=0; return;
10 reyssat 216
    }
217
    goto syntax;
218
}
219
 
8213 bpr 220
/* break a for loop */
10 reyssat 221
void exec_break(char *p)
222
{
223
    FOR_STACK *stk;
224
    if(m_file.for_idx>0) {
7379 bpr 225
      stk=&(m_file.for_stack[m_file.for_idx-1]);
226
      if(stk->varname[0]=='?') _skip_contents(0);
227
      else goto_for_end();
228
      m_file.for_idx--;
10 reyssat 229
    }
230
    *p=0; return;
231
}
232
 
8213 bpr 233
/* next */
10 reyssat 234
void exec_next(char *p)
235
{
236
    double v1, v2, step;
237
    char *p1, *p2;
238
    char buf[MAX_LINELEN+1];
239
    FOR_STACK *stk;
240
    if(m_file.for_idx<=0) module_error("next_without_for");
241
    stk=&(m_file.for_stack[m_file.for_idx-1]);
242
    if(stk->varname[0]=='?') module_error("next_without_for");
243
    if(stk->from) { /* list style */
7379 bpr 244
      if(stk->list_pt==NULL) {
245
        free(stk->bufpt);
246
        m_file.for_idx--;
247
        *p=0; return;
248
      }
249
      p1=strchr(stk->list_pt,',');
250
      if(p1!=NULL) {
251
        *p1=0; p2=find_word_start(p1+1);
252
      }
253
      else p2=NULL;
254
      strip_trailing_spaces(stk->list_pt);
255
      setvar(stk->varname,stk->list_pt);
256
      stk->list_pt=p2; goto loop_back;
10 reyssat 257
    }
258
    v1=stk->varval; v2=stk->varend; step=stk->step;
259
    v1+=step; stk->varval=v1;
260
    float2str(v1,buf);
261
    setvar(stk->varname, buf);
262
    if((step>0 && v1<=v2) || (step<0 && v1>=v2)) { /* loop */
7379 bpr 263
  loop_back:
264
      m_file.linepointer=stk->lineno;
265
      executed_gotos++;
266
      if(executed_gotos>=GOTO_LIMIT) module_error("too_many_gotos");
10 reyssat 267
    }
268
    else m_file.for_idx--;
269
    *p=0; return;
270
}
271
 
8213 bpr 272
/* Execution of a file in the module directory,
273
 * only for trusted modules.
274
 */
10 reyssat 275
void exec_mexec(char *p)
276
{
277
    direct_exec=1;
278
    calc_mexec(p);
279
    direct_exec=0;
280
}
281
 
8213 bpr 282
/* call shell. */
10 reyssat 283
void _exec_ex(char *p, char *arg0, char *arg1, int n)
284
{
285
    char *abuf[8];
286
    char errorfname[MAX_FNAME+1];
287
 
288
    if(robot_access) {
7379 bpr 289
      *p=0; return;
10 reyssat 290
    }
291
    if(!noout || !trusted_module() || is_class_module) {
7379 bpr 292
      _calc_exec(p,arg0,arg1,n); if(outputing) output0(p);
293
      return;
10 reyssat 294
    }
295
    mkfname(errorfname,"%s/exec.err",tmp_dir);
296
    abuf[0]=arg0; abuf[1]=arg1; abuf[n]=p; abuf[n+1]=NULL;
297
    wrapexec=1; exportall();
298
    execredirected(abuf[0],NULL,NULL,errorfname,abuf);
299
}
300
 
8213 bpr 301
/* call shell. */
10 reyssat 302
void exec_sh(char *p)
303
{
304
    _exec_ex(p,"sh","-c",2);
305
}
306
 
8213 bpr 307
/* call perl. */
10 reyssat 308
void exec_perl(char *p)
309
{
310
    _exec_ex(p,"perl","-e",2);
311
}
312
 
8213 bpr 313
/* file should not be cached */
10 reyssat 314
void exec_nocache(char *p)
315
{    m_file.nocache|=1; *p=0; }
316
 
8213 bpr 317
/* Read another file. */
10 reyssat 318
void exec_read(char *p)
319
{
320
    WORKING_FILE save;
321
    char parmsave[MAX_LINELEN+1];
322
    char *pp,*ps;
323
    int t,cache;
7379 bpr 324
 
10 reyssat 325
    strip_trailing_spaces(p);p=find_word_start(p);
326
    if(*p==0) return;
327
    pp=find_word_end(p); if(*pp) *pp++=0;
328
    pp=find_word_start(pp);
329
    ps=getvar("wims_read_parm"); if(ps==NULL) ps="";
330
    mystrncpy(parmsave,ps,sizeof(parmsave));
331
    setvar("wims_read_parm",pp);
332
    memmove(&save,&m_file,sizeof(WORKING_FILE));
333
    cache=1; if(p[0]=='.' && p[1]=='/') {p+=2; cache=0;}
334
    t=untrust;
335
    if(strncmp(p,"wimshome/",9)==0) {
7379 bpr 336
      if((untrust&255)!=0 &&
337
        (m_file.name[0]=='/' || strncmp(m_file.name,"wimshome/",9)==0))
338
        module_error("Illegal_file_access");
339
        untrust|=0x200;
10 reyssat 340
    }
341
    if((untrust&0x202)!=0) {
7379 bpr 342
      pp=getvar("wims_trustfile");
343
      if(pp!=NULL && *pp!=0 && wordchr(pp,p)!=NULL)
344
        untrust&=0xfdfd;
10 reyssat 345
    }
346
    readnest++; if(readnest>MAX_READNEST) module_error("too_many_nested_read");
347
    if(outputing) phtml_put(p,cache); else var_proc(p,cache);
348
    readnest--; untrust=t;
349
    memmove(&m_file,&save,sizeof(WORKING_FILE));
350
    setvar("wims_read_parm",parmsave);
351
}
352
 
8213 bpr 353
/* read a variable processing file */
10 reyssat 354
void exec_readproc(char *p)
355
{
356
    int o=outputing; outputing=0; exec_read(p); outputing=o;
357
}
358
 
359
void exec_defread(char *p)
360
{
361
    int t,o;
362
    secure_exec();
363
    t=untrust; untrust|=0x400;
364
    o=outputing; outputing=0;
365
    exec_read(p); untrust=t; outputing=o;
366
}
367
 
8213 bpr 368
/* Change to another file (no return) */
10 reyssat 369
void exec_changeto(char *p)
370
{
371
    m_file.linepointer=m_file.linecnt;
372
    exec_read(p);
373
}
374
 
375
int header_executed=0, tail_executed=0;
376
 
8213 bpr 377
/* internal routine: get other language versions */
10 reyssat 378
void other_langs(void)
379
{
380
    int i,j,k;
381
    char *p, lbuf[4], pbuf[MAX_FNAME+1], *phtml;
382
    char namebuf[MAX_FNAME+1], listbuf[4*MAX_LANGUAGES];
383
    static int otherlangs_got=0;
384
 
385
    if(otherlangs_got) return;
386
    mystrncpy(namebuf,module_prefix,sizeof(namebuf));
387
    listbuf[0]=0;j=strlen(namebuf)-3; p=listbuf;
388
    if(j>=2 && strcmp("light",namebuf+j-2)==0) {
7379 bpr 389
      setvar("wims_light_module","yes");
390
      phtml=getvar("phtml");
391
      if(phtml==NULL || *phtml==0) return;
392
      mystrncpy(pbuf,phtml,sizeof(pbuf));
393
      j=strlen(pbuf)-3;
394
      if(pbuf[j]!='.') return;
395
      j++; ovlstrcpy(lbuf,pbuf+j); pbuf[j]=0;
396
      j=strlen(namebuf);
397
      snprintf(namebuf+j,MAX_FNAME-j-10,"/pages/%s",pbuf);
398
      j=strlen(namebuf);
399
      for(i=k=0;i<available_lang_no;i++) {
400
        if(strcmp(lbuf,available_lang[i])==0) continue;
401
        mystrncpy(namebuf+j,available_lang[i],MAX_FNAME-j);
402
        if(ftest(namebuf)<0) continue;
403
        if(k>0) *p++=',';
404
        mystrncpy(p,available_lang[i],sizeof(listbuf)-4-(p-listbuf));
405
        p+=strlen(p);
406
        k++;
407
      }
408
    goto end;
10 reyssat 409
    }
410
    if(j>0 && namebuf[j]=='.') {
7379 bpr 411
      setvar("wims_light_module","");
412
      j++; ovlstrcpy(lbuf,namebuf+j); namebuf[j]=0;
413
      for(i=k=0;i<available_lang_no;i++) {
414
        if(strcmp(lbuf,available_lang[i])==0) continue;
415
        snprintf(namebuf+j,MAX_FNAME-j,"%s/main.phtml",
416
             available_lang[i]);
417
        if(ftest(namebuf)<0) continue;
418
        if(k>0) *p++=',';
419
        mystrncpy(p,available_lang[i],sizeof(listbuf)-4-(p-listbuf));
420
        p+=strlen(p);
421
        k++;
422
      }
10 reyssat 423
    }
424
    end: setvar("wims_otherlangs",listbuf); otherlangs_got=1;
425
}
426
 
8213 bpr 427
/* Standardised reference to wims home */
10 reyssat 428
void exec_homeref(char *p)
429
{
430
    char *ref, *user;
7379 bpr 431
 
10 reyssat 432
    if(ismhelp || tail_executed) return;
433
    setvar("wims_homeref_parm",p); *p=0;
434
    user=getvar("wims_user");
435
    if(user==NULL) user="";
436
    if(*user==0 || robot_access) ref=home_referer;
437
    else {
7379 bpr 438
      if(strcmp(user,"supervisor")==0) ref=home_referer_supervisor;
439
      else ref=home_referer_user;
10 reyssat 440
    }
441
    if(user[0]==0 && !robot_access) other_langs();
442
    phtml_put_base(ref,0); tail_executed=1;
443
}
444
 
8213 bpr 445
/* Standardised header menu */
10 reyssat 446
void exec_headmenu(char *p)
447
{
448
    char *ref, *user;
7379 bpr 449
 
10 reyssat 450
    if(header_executed) return;
451
    setvar("wims_headmenu_parm",p); *p=0;
452
    user=getvar("wims_user");
453
    if(user==NULL) user="";
454
    if(*user==0 || robot_access) ref=header_menu;
455
    else {
7379 bpr 456
      if(strcmp(user,"supervisor")==0) ref=header_menu_supervisor;
457
      else ref=header_menu_user;
10 reyssat 458
    }
459
    if(user[0]==0 && !robot_access) other_langs();
460
    phtml_put_base(ref,0); header_executed=1;
461
}
462
 
8213 bpr 463
/* uniformized title */
10 reyssat 464
void exec_title(char *p)
465
{
466
    char *s;
467
    *p=0;
468
    if(!outputing) return;
469
    s=getvar("wims_title_title");
470
    if(s==NULL || *s==0) {
7379 bpr 471
      s=getvar("module_title");
472
      if(s==NULL || *s==0) return;
473
      force_setvar("wims_title_title",s);
10 reyssat 474
    }
475
    phtml_put_base(title_page,0);
476
}
477
 
8213 bpr 478
/* standardized html tail */
10 reyssat 479
void exec_tail(char *p)
480
{
481
    if(!outputing || tail_executed) {
7379 bpr 482
      *p=0; return;
10 reyssat 483
    }
484
    if(!ismhelp) exec_homeref(p); *p=0;
485
    _output_("</body></html>");
486
    tail_executed=1;
487
}
488
 
5925 bpr 489
void exec_formend(char *p)
490
{
491
    _output_("\n</div></form>");
492
}
493
 
10 reyssat 494
void determine_font(char *l);
495
 
7379 bpr 496
void _headmathjax ( char *p)
497
{
7380 bpr 498
   _output_("\n<script type=\"text/javascript\">/*<![CDATA[*/if(\
7379 bpr 499
navigator.userAgent.toLowerCase().indexOf(\"firefox\") == -1 &&\
7370 bpr 500
navigator.userAgent.toLowerCase().indexOf(\"opera\") == -1 &&\
7379 bpr 501
(navigator.userAgent.toLowerCase().indexOf(\"safari\") == -1 || navigator.userAgent.toLowerCase().indexOf(\"chrome\") > 0)\
502
){var script = document.createElement(\"script\");\
7370 bpr 503
script.type = \"text/javascript\";\
7379 bpr 504
script.src  = \"scripts/js/mathjax/MathJax.js?config=MML_HTMLorMML-full.js\";\
7370 bpr 505
document.body.appendChild(script);\
7380 bpr 506
}/*]]>*/</script>\n");
7370 bpr 507
}
508
 
8213 bpr 509
/* standardized header */
1050 bpr 510
void _header(char *p, int option)
10 reyssat 511
{
512
    char *s1, *s2, hbuf[MAX_LINELEN+1], *ws="", *ws2="", *bo, *ol;
513
    char wsbuf[MAX_LINELEN+1],wsbuf2[MAX_LINELEN+1];
514
    setvar("wims_header_parm",p); *p=0;
515
    if(!outputing || header_executed) return;
516
    s1=getvar("wims_window");
517
    if(mode==mode_popup) {
7370 bpr 518
      if(s1!=NULL && *s1!=0) {
7379 bpr 519
        char *p1, *p2;
520
        int t1,t2/*,t3,t4*/;
521
        p1=find_word_start(s1);
522
        for(p2=p1; myisdigit(*p2); p2++);
523
        *p2=0; t1=atoi(p1); p1=p2+1;
524
        while(!myisdigit(*p1) && *p1) p1++;
525
        for(p2=p1; myisdigit(*p2); p2++);
526
        *p2=0; t2=atoi(p1); p1=p2+1;
527
/*        while(!myisdigit(*p1) && *p1) p1++;
528
        for(p2=p1; myisdigit(*p2); p2++);
529
        *p2=0; t3=atoi(p1); p1=p2+1;
530
        while(!myisdigit(*p1) && *p1) p1++;
531
        for(p2=p1; myisdigit(*p2); p2++);
532
        *p2=0; t4=atoi(p1); p1=p2+1;
533
        while(!myisdigit(*p1) && *p1) p1++;
534
        for(p2=p1; myisdigit(*p2); p2++);
535
        if(t3<5) t3=5; if(t4<20) t4=20;
536
*/      snprintf(wsbuf,sizeof(wsbuf),
537
          "window.focus();window.resizeTo(%d,%d);",t1,t2); ws=wsbuf;
538
/*      snprintf(wsbuf,sizeof(wsbuf),
539
             "window.focus();window.resizeto(%d,%d);window.moveto(%d,%d);",
540
             t1,t2,t3,t4); ws=wsbuf;
541
*/    }
10 reyssat 542
    }
543
    else {
7379 bpr 544
     if(s1!=NULL && strcmp(s1,"new")==0)
545
      ws="window.focus();window.resizeTo(800,640);window.moveTo(15,35);";
10 reyssat 546
    }
547
    if(strstr(session_prefix,"_exam")!=NULL) {
7379 bpr 548
/*    char buf[64]; */
549
      if(*ws==0) ws="window.focus();";
550
      else ws= "window.focus();window.moveTo(5,70);";
551
/*    snprintf(buf,sizeof(buf),"name.phtml.%s",lang);
552
      phtml_put_base(buf);
553
      phtml_put_base("jsclock.phtml"); */
10 reyssat 554
    }
555
    s1=getvar("wims_html_header"); if(s1==NULL) s1="";
556
    determine_font(getvar("module_language"));
557
    s2=getvar("module_title"); if(s2!=NULL && *s2!=0) {
7379 bpr 558
      mystrncpy(hbuf,s2,sizeof(hbuf)); calc_detag(hbuf);
559
      setvar("module_title2",hbuf);
10 reyssat 560
    }
561
    mystrncpy(hbuf,s1,sizeof(hbuf)); substit(hbuf);
562
    s2=getvar("wims_htmlbody"); if(s2==NULL) s2="";
563
    bo=getvar("wims_html_bodyoption"); if(bo==NULL) bo="";
564
    ws2=getvar("wims_html_onload"); if(ws2==NULL) ws2="";
565
    snprintf(wsbuf2,sizeof(wsbuf2),"%s%s",ws,ws2);
566
    setvar("wims_html_onload",wsbuf2);
567
    if(wsbuf2[0]) ol=" onload="; else ol="";
568
/*    output("<html xmlns=\"http://www.w3.org/1999/xhtml\"><head>%s\n\
569
</head><body %s %s%s %s>\n", */
256 bpr 570
/*    output("<html>\n\
10 reyssat 571
<head>%s\n\
572
</head><body %s %s%s %s>\n",
7370 bpr 573
       hbuf,s2,ol,wsbuf2,bo);*/
574
       /*http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd*/
575
     if(ol[0]) {
576
        output("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN\" \"http://www.w3.org/Math/DTD/mathml2/xhtml-math11-f.dtd\">\
577
        \n<html xml:lang=\"%s\"\
578
        xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:mathml=\"http://www.w3.org/1998/Math/MathML\"><head>%s\n\
579
     </head>\n<body %s %s\"%s\" %s>", lang,hbuf,s2,ol,wsbuf2,bo);}
580
     else {
581
       output("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN\" \"http://www.w3.org/Math/DTD/mathml2/xhtml-math11-f.dtd\">\
582
        \n<html xml:lang=\"%s\" xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:mathml=\"http://www.w3.org/1998/Math/MathML\"><head>%s\n\
583
        </head>\n<body %s %s%s %s>", lang,hbuf,s2,ol,wsbuf2,bo);
584
    }
585
    _headmathjax(p);
10 reyssat 586
    exec_headmenu(p);
1050 bpr 587
    if(option) exec_title(p);
10 reyssat 588
    if(cmd_type==cmd_help) {
7370 bpr 589
      char *s=getvar("special_parm");
590
      if(s==NULL) s="";
591
      m_file.linepointer=m_file.linecnt;
592
      if(strcmp(s,"about")==0) ovlstrcpy(hbuf,"about.phtml");
593
      else ovlstrcpy(hbuf,"help.phtml");
594
      exec_read(hbuf); exec_tail(p); /* param of exec_...() must be readable */
595
     return;
10 reyssat 596
    }
597
    header_executed=1;
598
}
599
 
1050 bpr 600
void exec_header(char *p) { _header(p,1);}
601
void exec_header1(char *p) { _header(p,0);}
602
 
10 reyssat 603
char href_target[128];
604
char jsbuf[512];
5729 bpr 605
#define jsstr " onclick=\"%s=window.open('','%s','status=no,toolbar=no,location=no,menubar=no,scrollbars=yes,resizable=yes')\""
10 reyssat 606
int ref_mhelp=0;
607
int follow_list[]={
608
    ro_session, ro_lang, ro_useropts, ro_module
609
};
610
#define follow_no (sizeof(follow_list)/sizeof(follow_list[0]))
611
 
612
void _httpfollow(char b1[], char *wn, int new)
613
{
614
    int i;
615
    char *p1, *s, *ss, sb[MAX_LINELEN+1], qbuf[MAX_LINELEN+1];
616
 
617
    sb[0]=0;
618
    for(i=0;i<follow_no;i++) {
7379 bpr 619
      if(robot_access && follow_list[i]==ro_session) continue;
620
      if(!new && follow_list[i]!=ro_session
621
       && follow_list[i]!=ro_module && follow_list[i]!=ro_lang)
622
       continue;
623
      if(follow_list[i]==ro_module) {
624
        char *pp;
625
        if(new) continue;
626
        pp=strstr(b1,"cmd=");
627
        if(pp==NULL) continue;
628
        pp+=strlen("cmd=");
629
        if(memcmp(pp,"intro",strlen("intro"))==0 ||
630
           memcmp(pp,"new",strlen("new"))==0) continue;
631
      }
632
      s=getvar(ro_name[follow_list[i]]);
633
      ss=strstr(b1,ro_name[follow_list[i]]);
634
      if(s!=NULL && *s!=0 &&
635
        (ss==NULL || (ss>b1 && *(ss-1)!='&')
636
         || *(ss+strlen(ro_name[follow_list[i]]))!='=')) {
637
        if(follow_list[i]==ro_session && memcmp(href_target,"wims_",5)==0) {
638
         char st[MAX_LINELEN+1];
639
         char *s1;
640
         s1=getvar("wims_session");
641
         if(s1==NULL) internal_error("exec_href() error.\n");
642
         if(ref_mhelp) {
643
            if(strstr(s1,"_mhelp")!=0)
644
              snprintf(st,sizeof(st),"%s",s1);
645
            else
646
              snprintf(st,sizeof(st),"%s_mhelp",s1);
647
            }
648
        else snprintf(st,sizeof(st),"%.10s%s",s1,href_target+4);
649
          s=st;
650
        }
651
        snprintf(sb+strlen(sb),MAX_LINELEN-strlen(sb),"%s=%s&",
652
             ro_name[follow_list[i]],s);
653
        if(ismhelp && follow_list[i]==ro_session &&
654
           strstr(sb,"_mhelp")==NULL)
655
          snprintf(sb+strlen(sb)-1,MAX_LINELEN-strlen(sb)+1,"_mhelp&");
656
       }
10 reyssat 657
    }
658
    snprintf(qbuf,MAX_LINELEN,"%s%s%s",wn,sb,b1);
7379 bpr 659
    /* cleaning up query string */
10 reyssat 660
    for(p1=qbuf;*p1;p1++) {
7379 bpr 661
      if(*p1=='"') string_modify(qbuf,p1,p1+1,"%22");
662
      if(*p1=='&' && isalpha(*(p1+1))) {
663
        p1++; string_modify(qbuf,p1,p1,"+");
664
      }
10 reyssat 665
    }
666
    mystrncpy(b1,qbuf,MAX_LINELEN);
667
}
668
 
8213 bpr 669
/* Restart with a new module, using http code 302. */
10 reyssat 670
void exec_restart(char *p)
671
{
672
    char buf[MAX_LINELEN+1], *rfn, buf2[MAX_LINELEN+1];
673
/*    long int t; */
7379 bpr 674
 
10 reyssat 675
    if(robot_access || outputing || !trusted_module() || is_class_module) return;
676
/*    accessfile(buf,"r","%s/restart.time",s2_prefix);
7379 bpr 677
    t=atoi(buf); if(t==nowtime) return;    */ /* possible looping */
10 reyssat 678
    mystrncpy(buf,find_word_start(p),sizeof(buf));
679
    *find_word_end(buf)=0;
680
    _httpfollow(buf,"",0);
681
    nph_header(301);
682
    rfn=strchr(ref_name,':'); if(rfn==NULL) {
7379 bpr 683
      usual: snprintf(buf2,sizeof(buf2),"%s?%s",ref_name,buf);
10 reyssat 684
    }
685
    else {
7379 bpr 686
      char *p;
687
      p=getvar("wims_protocol");
688
      if(p!=NULL && strcmp(p,"https")==0) {
689
        snprintf(buf2,sizeof(buf2),"https%s?%s",rfn,buf);
690
      }
691
      else goto usual;
10 reyssat 692
    }
693
    printf("Location: %s\r\n\r\n\
4957 obado 694
<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\
10 reyssat 695
<html><body><a href=\"%s\">%s</a></body></html>",buf2,buf2,buf2);
696
    close_working_file(&m_file,0); write_logs();
697
    snprintf(buf,sizeof(buf),"%ld",nowtime);
698
/*    accessfile(buf,"w","%s/restart.time",s2_prefix);
699
*/    delete_pid(); exit(0);
700
}
701
 
8213 bpr 702
/* extract target tag from parm string. */
10 reyssat 703
void href_find_target(char *p)
704
{
705
    char *pp, *pe,buf1[MAX_LINELEN+1];
706
    href_target[0]=0; jsbuf[0]=0; ref_mhelp=0;
707
    for(pp=find_word_start(p);*pp!=0;pp=find_word_start(pe)) {
7379 bpr 708
      pe=find_word_end(pp);
709
      if(strncasecmp(pp,"target=wims_",strlen("target=wims_"))!=0) continue;
710
      memmove(buf1,pp,pe-pp); buf1[pe-pp]=0; substit(buf1);
711
      if(strncasecmp(buf1,"target=wims_mhelp",strlen("target=wims_mhelp"))==0) {
712
        if(*pe!=0) *pe++=0; ovlstrcpy(href_target,"wims_help");
713
        ref_mhelp=1;
714
      }
715
      else {
716
        if(*pe!=0) *pe++=0;
717
          mystrncpy(href_target,buf1+strlen("target="),sizeof(href_target));
718
      }
719
      snprintf(jsbuf,sizeof(jsbuf),jsstr,href_target,href_target);
720
      ovlstrcpy(pp,pe);return;
10 reyssat 721
    }
722
    pp=getvar("module_help");
723
    if(href_target[0]==0 && pp!=NULL && strcmp(pp,"popup")==0 &&
724
       (pe=strstr(p,"cmd=help"))!=NULL) {
7379 bpr 725
      if(pe==p || *(pe-1)=='&') {
726
        ovlstrcpy(href_target,"wims_help"); ref_mhelp=1;
727
        snprintf(jsbuf,sizeof(jsbuf),jsstr,href_target,href_target);
728
      }
10 reyssat 729
    }
730
}
731
 
732
void _href_getdef(char src[], char vname[], char buf[], int buflen)
733
{
734
    char *p1, *p2, *p3;
735
    buf[0]=0;
736
    for(p1=strstr(src,vname); p1; p1=strstr(p2,vname)) {
7379 bpr 737
      p2=p1+strlen(vname); if(*p2!='=') continue;
738
      if(p1>src && *(p1-1)!='&') continue;
739
      p2++; p3=strchr(p2,'&'); if(p3==NULL) p3=p2+strlen(p2);
740
      if(p3-p2>=buflen) return; /* too long */
741
      memmove(buf,p2, p3-p2); buf[p3-p2]=0; return;
10 reyssat 742
    }
743
}
744
 
8213 bpr 745
/* Create href to wims requests. subst() is not done. */
10 reyssat 746
void exec_href(char *p)
747
{
2026 bpr 748
    char *s, st[128], sti[128], stc[128], stt[128], *p1, *p2, *p3, *wn="";
6186 bpr 749
    char *U="<span style=\"color:#A0A0C0;text-decoration:underline;\">%s</span>";
10 reyssat 750
    char b1[MAX_LINELEN+1], b2[MAX_LINELEN+1];
751
    int new=0;
752
    if(!outputing) return;
753
    href_find_target(p);
754
    p1=find_word_start(p);
755
    p2=find_word_end(p1); if(*p2) *(p2++)=0;
756
    mystrncpy(b1,p1,sizeof(b1));
757
    mystrncpy(b2,find_word_start(p2),sizeof(b2));
758
    substit(b1); substit(b2);
7379 bpr 759
    /* standard reference */
10 reyssat 760
    if(*b2==0 && strchr(b1,'=')==NULL) {
7379 bpr 761
      char b[MAX_LINELEN+1], *ll;
762
      p1=find_word_start(b1); *find_word_end(p1)=0;
763
      if(*p1==0 || strlen(p1)>64) return;
764
      ll=getvar("module_language");
765
      if(ll==NULL || *ll==0 || *(ll+1)==0 || *(ll+2)!=0) ll=lang;
766
      accessfile(b,"r","html/href.%s",ll);
767
      memmove(p1+1,p1,64); *p1='\n'; strcat(p1,"        ");
768
      p2=strstr(b,p1); if(p2==NULL) return;
769
      p1=find_word_start(p2+strlen(p1)); p2=find_word_end(p1);
770
      if(*p2) *(p2++)=0;
771
      p3=strchr(p2,'\n'); if(p3!=NULL) *p3=0;
772
      mystrncpy(b1,p1,sizeof(b1));
773
      mystrncpy(b2,find_word_start(p2),sizeof(b2));
774
      substit(b1); substit(b2);
10 reyssat 775
    }
7379 bpr 776
    /* for robots: only references without defining cmd. */
10 reyssat 777
    if(robot_access && strstr(b1,"cmd=")!=NULL &&
778
       strstr(b1,"module=adm/doc")==NULL) {
7379 bpr 779
      _output_(b2); return;
10 reyssat 780
    }
781
    if(robot_access && strstr(aliased_cgi,"yes")!=NULL) {
7379 bpr 782
      char mbuf[256], lbuf[16];
783
      _href_getdef(b1,"module",mbuf,sizeof(mbuf));
784
      if(mbuf[0]==0) mystrncpy(mbuf,home_module,sizeof(mbuf));
785
      _href_getdef(b1,"lang",lbuf,sizeof(lbuf));
786
      if(strlen(lbuf)!=2) {mystrncpy(lbuf,lang,4);lbuf[2]=0;}
787
      if(strncmp(mbuf,"adm/doc",strlen("adm/doc"))==0) {
788
        char dbuf[256], bbuf[256];
789
        _href_getdef(b1,"doc",dbuf,sizeof(dbuf));
790
        _href_getdef(b1,"block",bbuf,sizeof(bbuf));
791
        if(!myisdigit(dbuf[0])) dbuf[0]=0;
792
        if(dbuf[0]!=0 && bbuf[0]==0) snprintf(bbuf,sizeof(bbuf),"main");
793
        if(dbuf[0]==0)
794
          output("<a href=\"%s%s_doc~.html\">%s</a>", ref_base,lbuf,b2);
795
        else
796
          output("<a href=\"%s%s_doc~%s~%s.html\">%s</a>",
797
             ref_base,lbuf,dbuf,bbuf,b2);
798
      }
799
      else {
800
        for(s=strchr(mbuf,'/'); s!=NULL; s=strchr(s+1,'/')) *s='~';
801
        output("<a href=\"%s%s_%s.html\">%s</a>", ref_base,lbuf,mbuf,b2);
802
      }
803
    return;
10 reyssat 804
    }
1363 bpr 805
    s=getvar("wims_ref_id");
806
    if(s!=NULL && *s!=0 && !isspace(*s)) {
7379 bpr 807
      snprintf(sti,sizeof(sti)," id=\"%s\"",s);
1363 bpr 808
    }
809
    else sti[0]=0;
7379 bpr 810
 
1363 bpr 811
    s=getvar("wims_ref_class");
812
    if(s!=NULL && *s!=0 && !isspace(*s)) {
7379 bpr 813
      snprintf(stc,sizeof(stc)," class=\"%s\"",s);
1363 bpr 814
    }
815
    else stc[0]=0;
7379 bpr 816
 
2026 bpr 817
    s=getvar("wims_ref_title");
818
    if(s!=NULL && *s!=0 && !isspace(*s)) {
7379 bpr 819
      snprintf(stt,sizeof(stt)," title=\"%s\"",s);
2026 bpr 820
    }
821
    else stt[0]=0;
7379 bpr 822
 
10 reyssat 823
    s=getvar("wims_ref_target");
824
    if(href_target[0]!=0) s=href_target;
825
    if(s!=NULL && *s!=0 && !isspace(*s)) {
7379 bpr 826
      snprintf(st,sizeof(st)," target=\"%s\"",s);
827
      if(strcmp(s,"_parent")!=0) {
828
         new=1; wn="wims_window=new&";
829
      }
10 reyssat 830
    }
831
    else st[0]=0;
832
    _httpfollow(b1,wn,new);
833
    tohttpquery(b1);
834
    if(strstr(session_prefix,"_check")!=NULL) {
7379 bpr 835
      if(*b2) output(U,b2);
836
    else _output_("<a id=\"0\"></a>");
837
      return;
10 reyssat 838
    }
839
    if(jsbuf[0]==0 && st[0]==0 && strstr(session_prefix,"_exam")!=NULL) {
7407 bpr 840
      p1=strstr(b1,"cmd=");
7379 bpr 841
      if(p1!=NULL) {
842
        p1+=strlen("cmd=");
843
        if(strncmp(p1,"new",3)==0 || strncmp(p1,"renew",5)==0 ||
844
           strncmp(p1,"intro",5)==0) {
845
         if(*b2) output(U,b2);
846
         else _output_("<a id=\"#\"></a>");
847
          return;
848
        }
849
      }
10 reyssat 850
    }
851
    if(*b2)
2026 bpr 852
      output("<a href=\"%s?%s\"%s%s %s %s %s>%s</a>",
7379 bpr 853
         ref_name, b1, st, jsbuf,sti,stc,stt,b2);
10 reyssat 854
    else
2026 bpr 855
      output("<a href=\"%s?%s\"%s%s %s %s %s>",ref_name, b1, st, jsbuf,sti,stc,stt);
856
    setvar("wims_ref_id","");
857
    setvar("wims_ref_class","");
858
    setvar("wims_ref_title","");
10 reyssat 859
}
860
 
8213 bpr 861
/* Create form refering to the page. */
10 reyssat 862
void exec_form(char *p)
863
{
864
    char *s, *p1, *p2, *a, *m, *opt, st[128], *wn="";
865
    char abuf[128];
866
    int i, new=0;
867
    if(!outputing) return;
868
    href_find_target(p);
869
    s=getvar("wims_ref_target");
870
    if(href_target[0]!=0) s=href_target;
871
    if(s!=NULL && *s!=0 && !isspace(*s)) {
7379 bpr 872
      snprintf(st,sizeof(st)," target=\"%s\"",s);
873
      if(strcmp(s,"_parent")!=0) {
874
        new=1; wn="<input type=\"hidden\" name=\"wims_window\" value=\"yes\" />\n";
875
      }
10 reyssat 876
    }
877
    else st[0]=0;
878
    a=getvar("wims_ref_anchor"); if(a==NULL) a="";
879
    opt=find_word_start(find_word_end(find_word_start(p)));
880
    m=getvar("wims_form_method");
881
    if(m!=NULL) {
7379 bpr 882
      m=find_word_start(m);
883
      if(strncasecmp(m,"post",4)==0) m="post";
884
      else if(strncasecmp(m,"get",3)==0) m="get";
885
        else if(strncasecmp(m,"file",4)==0) {
886
         m="post\" enctype=\"multipart/form-data";
887
        snprintf(abuf,sizeof(abuf),"?form-data%ld%s",random(),a); a=abuf;
888
        force_setvar("wims_form_method","");
889
     }
890
      else m=default_form_method;
10 reyssat 891
    }
892
    else m=default_form_method;
893
    if(strstr(session_prefix,"_check")!=NULL) {
7379 bpr 894
      output("<form action=\"NON_EXISTING_PAGE\" onsubmit=\"window.close();\" %s>\n",
895
           opt);
896
      return;
10 reyssat 897
    }
7557 obado 898
    output("<form action=\"%s%s\"%s method=\"%s\" %s>\n<div class='wims_form'>%s",ref_name,a,st,m,opt,wn);
10 reyssat 899
    if(a!=abuf && a[0]) force_setvar("wims_ref_anchor","");
900
    for(i=0;i<follow_no;i++) {
7379 bpr 901
      if(robot_access && follow_list[i]==ro_session) continue;
902
      if(!new && follow_list[i]!=ro_session
903
       && follow_list[i]!=ro_module && follow_list[i]!=ro_lang)
904
        continue;
905
      if(follow_list[i]==ro_module) continue;
906
      s=getvar(ro_name[follow_list[i]]);
907
      if(s!=NULL && *s!=0) {
908
        if(follow_list[i]==ro_session && memcmp(href_target,"wims_",5)==0) {
909
          char st[MAX_LINELEN+1];
910
          char *s1;
911
          s1=getvar("wims_session");
912
          if(s1==NULL) internal_error("exec_form() error.\n");
913
          snprintf(st,sizeof(st),"%.10s%s",s1,href_target+4);
914
          s=st;
915
        }
916
        output("<input type=\"hidden\" name=\"%s\" value=\"%s\" />\n",
917
           ro_name[follow_list[i]],s);
918
      }
10 reyssat 919
    }
920
    p1=find_word_start(p);p2=find_word_end(p1);
921
    if(p2>p1) {
7379 bpr 922
      char buf[64];
923
      int i;
924
      i=p2-p1; if(i>60) i=60;
925
      memmove(buf,p1,i);buf[i]=0;
926
      for(i=0;i<CMD_NO && strcmp(buf,commands[i]);i++);
927
      if(i<CMD_NO) {
928
        output("<input type=\"hidden\" name=\"cmd\" value=\"%s\" />\n",buf);
929
        if(i!=cmd_intro && i!=cmd_new)
930
          output("<input type=\"hidden\" name=\"module\" value=\"%s\" />\n",
931
             getvar(ro_name[ro_module]));
932
      }
933
   }
10 reyssat 934
}
935
 
8213 bpr 936
/* Creat link to trap robot access, an internal command
937
 * which should not be documented
938
 */
10 reyssat 939
void exec_robottrap(char *p)
940
{
941
    char buf[MAX_LINELEN+1];
942
    if(robot_access) return;
3718 reyssat 943
    ovlstrcpy(buf,"session=$wims_session.1&module=adm/trap");
7557 obado 944
    _output_("<!-- "); exec_href(buf);_output_("Robot trapper, do not click!</a> -->");
945
    _output_("<div class='wimstrap'>");exec_href(buf); _output_("<span></span></a></div>");
10 reyssat 946
}
947
 
8213 bpr 948
/* set definitions in a file. Trusted modules only. */
10 reyssat 949
void exec_setdef(char *p)
950
{
951
    char *p1, *pp;
952
    char nbuf[MAX_LINELEN+1], fbuf[MAX_LINELEN+1], tbuf[MAX_LINELEN+1];
953
    if(robot_access || !trusted_module() || is_class_module) return;
954
    p1=wordchr(p,"in"); if(p1==NULL) module_error("syntax_error");
955
    *p1=0; p1=find_word_start(p1+strlen("in"));
3718 reyssat 956
    ovlstrcpy(nbuf,p);
10 reyssat 957
    mystrncpy(tbuf,p1,sizeof(tbuf));
958
    substit(nbuf); substit(tbuf);
959
    if(find_module_file(tbuf,fbuf,1)) return;
960
    pp=find_word_start(nbuf); p1=find_word_start(fbuf); *find_word_end(p1)=0;
961
    strip_trailing_spaces(pp);
962
    setdef(p1,pp);
963
}
964
 
8213 bpr 965
/* Set a variable. */
10 reyssat 966
void exec_set(char *name)
967
{
968
    char *p, *defn, *parm;
969
    char tbuf2[MAX_LINELEN+1], namebuf[MAX_LINELEN+1];
970
    int i;
971
 
972
    p=strchr(name,'=');
973
    if(p==NULL) return; /* warning or error! */
974
    *p=0; defn=find_word_start(p+1);
975
    *find_word_end(name)=0;
976
    mystrncpy(namebuf,find_word_start(name),sizeof(namebuf));
8213 bpr 977
    /* we allow substit in names, to implement array */
7379 bpr 978
    substit(namebuf); *find_word_end(namebuf)=0;
10 reyssat 979
    if(*defn!=calc_prefix_char) {
7379 bpr 980
    /* substitute by default */
981
      mystrncpy(tbuf2,defn,sizeof(tbuf2));
982
      substit(tbuf2); setvar(namebuf,tbuf2); return;
10 reyssat 983
    }
7379 bpr 984
    /* called from !readdef */
10 reyssat 985
    if((untrust&4)!=0) module_error("not_trusted");
7379 bpr 986
    /* definition is a command  */
987
    parm=find_word_end(defn+1);
10 reyssat 988
    if( *parm != 0 ) { *parm=0; parm=find_word_start(parm+1); }
989
    i=m_file.lines[m_file.l].varcode;
990
    if(i<0) {
7379 bpr 991
      i=search_list(calc_routine,CALC_FN_NO,sizeof(calc_routine[0]),defn+1);
992
      m_file.lines[m_file.l].varcode=i;
10 reyssat 993
    }
994
    if(i<0) {
7379 bpr 995
        /* replace by warning? */
996
      setvar(error_data_string,defn+1); module_error("bad_cmd");
997
      return;
10 reyssat 998
    }
999
    mystrncpy(tbuf2,parm,sizeof(tbuf2)); execnt++;
1000
    if(calc_routine[i].tag==0) substit(tbuf2);
1001
    tbuf2[sizeof(tbuf2)-1]=0; calc_routine[i].routine(tbuf2);
7379 bpr 1002
        /* remove trailing new line */
10 reyssat 1003
    tbuf2[sizeof(tbuf2)-1]=0;
1004
    if(tbuf2[strlen(tbuf2)-1]=='\n') tbuf2[strlen(tbuf2)-1]=0;
1005
    setvar(namebuf,tbuf2);
1006
}
1007
 
8213 bpr 1008
/* set but do not overwrite. */
10 reyssat 1009
void exec_default(char *p)
1010
{
1011
    char *start, *end, c, *pp;
1012
    char namebuf[MAX_LINELEN+1];
1013
    start=find_word_start(p);
1014
    for(end=start;*end!=0 && !isspace(*end) && *end!='='; end++);
1015
    c=*end; *end=0;
1016
    if(end-start<=MAX_LINELEN-1) {
7379 bpr 1017
      memmove(namebuf,start,end-start+1); substit(namebuf);
1018
      pp=getvar(namebuf);
1019
      if(pp!=NULL && *pp!=0) return;
10 reyssat 1020
    }
1021
    *end=c; exec_set(p);
1022
}
1023
 
8213 bpr 1024
/* Does nothing; just a comment. */
10 reyssat 1025
void exec_comment(char *p)
1026
{
1027
    return;
1028
}
1029
 
8213 bpr 1030
/* Exit the file under interpretation */
10 reyssat 1031
void exec_exit(char *p)
1032
{
1033
    m_file.linepointer=m_file.linecnt;
1034
    return;
1035
}
1036
 
8213 bpr 1037
/* output a file. Undocumented. Aliases:
7379 bpr 1038
     * getfile, outfile, fileout */
10 reyssat 1039
void exec_getfile(char *p)
1040
{
1041
    char *s, *p1, url[MAX_LINELEN+1];
1042
    char *prompt;
7379 bpr 1043
 
10 reyssat 1044
    p=find_word_start(p); prompt=find_word_end(p);
1045
    if(*prompt!=0) *prompt++=0;
1046
    prompt=find_word_start(prompt);
1047
    if(*p==0 || !outputing) return;
1048
    if(!trusted_module() || is_class_module) return;
1049
    s=getvar(ro_name[ro_session]);
1050
    if(s==NULL || *s==0 || strstr(s,"robot")!=NULL) return;
1051
    mystrncpy(url,ref_name,sizeof(url));
1052
    for(p1=url+strlen(url);p1>url && *(p1-1)!='/'; p1--);
1053
    if(good_httpd) snprintf(p1,sizeof(url)+p1-url,
7379 bpr 1054
                "getfile/%s?&+session=%s&+modif=%ld",
1055
                p,s,nowtime);
10 reyssat 1056
    else snprintf(url,sizeof(url),
7379 bpr 1057
          "%s?cmd=getfile&+session=%s&+special_parm=%s&+modif=%ld",
1058
          ref_name,s,p,nowtime);
10 reyssat 1059
    snprintf(jsbuf,sizeof(jsbuf),jsstr,"wims_file","wims_file");
1050 bpr 1060
    if(*prompt) output("<a href=\"%s\">%s</a>\n", url,prompt);
1119 bpr 1061
    else output("<a href=\"%s\"></a>",url);
10 reyssat 1062
}
1063
 
8213 bpr 1064
/* internal */
10 reyssat 1065
void count_insert(void)
1066
{
1067
    insert_no++;
1068
    if(insert_no>=INS_LIMIT) module_error("too_many_ins");
1069
}
1070
 
1071
int animated_ins=0;
1072
int grouped_ins=0;
1073
 
8185 bpr 1074
/* generic insertion */
10 reyssat 1075
void _exec_ins(char *p, char *script_name,char *format)
1076
{
1077
    char *s, *b, *at, *tag, *tag2, *al, *fmt, *mh;
1078
    char *p1, *pt;
1079
    char buf[1024],buf2[1024],url[MAX_LINELEN+1],altbuf[1024];
1080
    char outbuf[1024];
1081
    int border, middle, vspace;
1082
    long int tel;
1083
 
1084
    if(robot_access) return;
1085
    count_insert(); outbuf[0]=0;
1086
    setenv("ins_source",p,1); /* value kept from user tamper */
1087
    if(animated_ins) fmt=getvar("anim_format"); else fmt=format;
1088
    if(fmt==NULL) fmt="gif";
1089
    if(ismhelp) mh="mh"; else mh="";
1090
    snprintf(buf,sizeof(buf),"%s/insert%s-%d.%s",s2_prefix,mh,insert_no,fmt);
1091
    if(grouped_ins) {unlink(buf); goto grouped;}
1092
    exportall();
1093
    call_ssh("%s/%s %d %s >%s/ins.out 2>%s/ins.err",
7379 bpr 1094
        bin_dir,script_name,insert_no,tmp_dir,tmp_dir,tmp_dir);
10 reyssat 1095
    unlink(buf); wrapexec=1;
1096
    if(trusted_module()) setenv("trusted_module","yes",1);
1097
    else if(untrust) setenv("trusted_module","no",1);
1098
    call_ssh("mv %s/insert%s-%d.%s %s >/dev/null 2>/dev/null",
7379 bpr 1099
         tmp_dir,mh,insert_no,fmt,s2_prefix);
10 reyssat 1100
    tel=filelength("%s", buf);
1101
    if(tel<=5) {
7379 bpr 1102
      char bbuf[MAX_LINELEN+1];
1103
      accessfile(bbuf,"r","%s/ins.err",tmp_dir);
1104
      snprintf(url,sizeof(url),"gifs/badins.gif");
1105
      for(p1=bbuf;p1<bbuf+512 && *p1;p1++)
1106
      if(*p1=='<' || *p1=='>') *p1='?';
1107
      *p1=0;
1108
      if(bbuf[0]==0) snprintf(bbuf,sizeof(bbuf),"Fail");
1109
      snprintf(outbuf+strlen(outbuf),sizeof(outbuf)-strlen(outbuf),
1110
         " <img src=\"%s\" alt=\"Error\" /> <small><pre>%s</pre></small> <br /> ",
1111
         url,bbuf);
1112
      setvar("ins_warn","fail");
1113
      setvar("ins_cnt","0");
1114
      goto reset;
10 reyssat 1115
    }
1116
    grouped:
1117
    s=getvar(ro_name[ro_session]);
1118
    b=getvar("ins_border"); at=getvar("ins_attr");
1119
    tag=getvar("ins_tag");  al=getvar("ins_align");
1120
    if(at==NULL) at="";
1121
    if(tag==NULL) tag="";
1122
    if(al==NULL) al="";al=find_word_start(al);
6265 bpr 1123
    if(*al!=0) snprintf(buf2,sizeof(buf2),"vertical-align:%s",al); else buf2[0]=0;
10 reyssat 1124
    if(strcasecmp(al,"middle")==0) middle=1; else middle=0;
1125
    tag2=""; vspace=0;
1126
    if(*tag!=0) {
7379 bpr 1127
      mystrncpy(buf,tag,sizeof(buf)); tag=find_word_start(buf);
1128
      tag2=find_word_end(tag);
1129
      if(*tag2!=0) *tag2++=0;
1130
      tag2=find_word_start(tag2);
10 reyssat 1131
    }
1132
    if(b==NULL || *b==0) border=0;
1133
    else border=atoi(b);
1134
    if(border<0) border=0; if(border>100) border=100;
1135
    if(middle) {
7379 bpr 1136
      snprintf(outbuf+strlen(outbuf),
1137
         sizeof(outbuf)-strlen(outbuf),"%s",mathalign_sup1);
1138
      vspace=2;
10 reyssat 1139
    }
1140
    mystrncpy(url,ref_name,sizeof(url));
1141
    for(p1=url+strlen(url);p1>url && *(p1-1)!='/'; p1--);
1142
    snprintf(p1,sizeof(url)+p1-url,
7379 bpr 1143
         "wims.%s?cmd=getins&+session=%s&+special_parm=insert%s-%d.%s&+modif=%ld",
1144
         fmt,s,mh,insert_no,fmt,nowtime);
10 reyssat 1145
    if(strchr(ins_alt,'"')!=NULL || strlen(ins_alt)>256) ins_alt[0]=0;
1146
    pt=getvar("wims_ins_alt"); if(pt==NULL) pt="";
1147
    if(ins_alt[0] && strcmp(pt,"none")!=0)
3522 bpr 1148
      snprintf(altbuf,sizeof(altbuf)," alt=\"%s\"",ins_alt);
1149
    else snprintf(altbuf,sizeof(altbuf)," alt=\"\"");
10 reyssat 1150
    if(strcasecmp(tag,"form")!=0) {
7379 bpr 1151
      snprintf(outbuf+strlen(outbuf),sizeof(outbuf)-strlen(outbuf),
1152
         "<img src=\"%s\" style=\"border:solid;border-width:%dpx;margin-bottom:%dpx;%s\" %s %s />",
1153
         url, border, vspace, buf2, at, altbuf);
10 reyssat 1154
    }
1155
    else {
7379 bpr 1156
      char *n, *nend;
6168 bpr 1157
/* fix: add quotes at name=" " */
7379 bpr 1158
      if(*tag2!=0) {n="name=\"" ; nend="\"";} else {n=""; nend="";}
1159
      snprintf(outbuf+strlen(outbuf),sizeof(outbuf)-strlen(outbuf),
1160
         "<input type=\"image\" %s%s%s src=\"%s\" style=\"border:solid;border-width:%dpx;margin-bottom:%dpx;%s\" %s %s />",
1161
         n,tag2,nend,url,border,vspace,buf2,at,altbuf);
10 reyssat 1162
    }
1163
    if(middle) snprintf(outbuf+strlen(outbuf),
7379 bpr 1164
            sizeof(outbuf)-strlen(outbuf),"%s",mathalign_sup2);
10 reyssat 1165
    setvar("ins_warn",""); ins_alt[0]=0;
1166
    setvar("ins_cnt",int2str(insert_no));
1167
    reset:
1168
    if(outputing) _output_(outbuf);
1169
    setvar("ins_out",outbuf);
1170
    setvar("ins_attr",""); setvar("ins_tag","");
1171
    setvar("ins_url",url);
1172
    snprintf(buf2,sizeof(buf2),"insert%s-%d.%s",mh,insert_no,fmt);
1173
    setvar("ins_filename",buf2);
1174
    animated_ins=0;
1175
}
1176
 
8155 bpr 1177
/* instex: dynamically insert tex outputs */
10 reyssat 1178
void exec_instex(char *p)
1179
{
1180
    char *ts, *tc, *f, *mh, buf[MAX_FNAME+1];
7379 bpr 1181
 
10 reyssat 1182
    if(robot_access) {
7379 bpr 1183
      *p=0; return;
10 reyssat 1184
    }
1185
    f=instex_check_static(p); substit(p);
1186
    if(f==NULL) {
8155 bpr 1187
/* Use static instex if there is no real substitution
1188
 * and the source file is not in sessions directory.
1189
 */
7379 bpr 1190
      calc_instexst(p); if(outputing) _output_(p);
1191
      return;
10 reyssat 1192
    }
1193
    if(ismhelp) mh="mh"; else mh="";
1194
    fix_tex_size(); f="gif";
1195
    setenv("texgif_style",instex_style,1);
3415 bpr 1196
    tc=getvar("instex_texheader"); if (tc) { setenv("texgif_texheader",tc,1);}
10 reyssat 1197
    setenv("texgif_tmpdir",tmp_dir,1);
1198
    setenv("texgif_src",p,1);
1199
    if(ins_alt[0]==0) mystrncpy(ins_alt,p,sizeof(ins_alt));
1200
    mkfname(buf,"%s/insert%s-%d.gif",tmp_dir,mh,insert_no+1);
1201
    setenv("texgif_outfile",buf,1);
1202
    ts=getvar("wims_texsize"); tc=getvar("instex_color");
7379 bpr 1203
    if(lastout_file!=-1 && (tc==NULL || *tc==0) &&
10 reyssat 1204
       (ts==NULL || *ts==0 || strcmp(ts,"0")==0) &&
1205
       strstr(p,"\\begin{")==NULL) {
7379 bpr 1206
      int ls, ln;
1207
      char *pagebreak;
1208
      ls=strlen(instex_src); ln=strlen(instex_fname);
1209
      if(ls+strlen(p)>=MAX_LINELEN-256 ||
1210
       ln+strlen(buf)>=MAX_LINELEN-16) {
1211
        instex_flush(); ls=ln=0;
1212
      }
1213
      if(instex_cnt>0) pagebreak="\\pagebreak\n"; else pagebreak="";
1214
      snprintf(instex_src+ls,MAX_LINELEN-ls,"%s %s %s %s\n",
1215
         pagebreak,instex_style,p,instex_style);
1216
      snprintf(instex_fname+ln,MAX_LINELEN-ln,"%s\n",buf);
1217
      grouped_ins=1;
10 reyssat 1218
    }
1219
    mkfname(buf,"%s/texgif.dvi",tmp_dir); unlink(buf);
1220
    wrapexec=0; _exec_ins(p,instex_processor,f);
1221
    if(grouped_ins) instex_cnt++;
1222
    grouped_ins=0;
1223
}
1224
 
8152 bpr 1225
/* patches the gnuplot integer division (mis)feature. */
10 reyssat 1226
void gnuplot_patch(char *p,int oneline)
1227
{
1228
    char *pp;
1229
    for(pp=strchr(p,'/');pp!=NULL;pp=strchr(pp+1,'/')) {
7379 bpr 1230
      char *p1;
1231
      if(pp<=p || !myisdigit(*(pp-1)) || !myisdigit(*(pp+1))) continue;
1232
      for(p1=pp-2;p1>=p && myisdigit(*p1);p1--);
1233
      if(p1>=p && *p1=='.') continue;
1234
      for(p1=pp+2;*p1 && myisdigit(*p1);p1++);
1235
      if(*p1=='.') continue;
1236
      string_modify(p,p1,p1,".0");
10 reyssat 1237
    }
1238
    for(pp=strchr(p,'^');pp!=NULL;pp=strchr(pp+1,'^'))
1239
      string_modify(p,pp,pp+1,"**");
8155 bpr 1240
/* disallow new lines and ';' */
10 reyssat 1241
    if(oneline)
1242
      for(pp=p;*pp!=0;pp++) if(*pp==';' || *pp=='\n') *pp=' ';
1243
}
1244
 
8152 bpr 1245
/* This is to disable pipe in the gnuplot plotting function.
1246
 * We do not allow ' followed by < .
1247
 */
10 reyssat 1248
void prepare_insplot_parm(char *p)
1249
{
1250
    int i,j,multanim; char *pp, *s;
1251
    double d;
1252
    char setbuf[MAX_LINELEN+10],buf[MAX_LINELEN+1];
7379 bpr 1253
 
10 reyssat 1254
    j=strlen(p);
8155 bpr 1255
/* pipe in plot command */
10 reyssat 1256
    for(i=0;i<j;i++) {
7379 bpr 1257
      if(*(p+i)!='\'' && *(p+i)!='"') continue;
1258
      pp=find_word_start(p+i+1); if(*pp=='<') module_error("illegal_plot_cmd");
10 reyssat 1259
    }
1260
    gnuplot_patch(p,1);
8155 bpr 1261
/* multiplot */
10 reyssat 1262
    multanim=0;
1263
    pp=getvar("insplot_split");
1264
    if(pp!=NULL) i=linenum(pp); else i=0;
8155 bpr 1265
/* arbitrary limit: 16 multiplots */
10 reyssat 1266
    if(i>16) i=16;
1267
    if(i>1) {
7379 bpr 1268
      char tbuf[MAX_LINELEN*(i+1)+100], bbuf[MAX_LINELEN+1];
1269
      tbuf[0]=0;
1270
      if(*p!=0) snprintf(tbuf,sizeof(tbuf),"%s\n",p);
1271
      snprintf(buf,sizeof(buf),"%d",i); setenv("multiplot",buf,1);
1272
      for(j=1;j<=i;j++) {
1273
        snprintf(buf,sizeof(buf),"insplot_parm_%d",j);
1274
        pp=getvar(buf);
1275
        if(pp==NULL || *pp==0) {
1276
          if(j==1 && *p!=0) continue;
1277
          pp="";
1278
        }
1279
        else {
1280
          mystrncpy(bbuf,pp,sizeof(bbuf));
1281
          gnuplot_patch(bbuf,1);
1282
        }
1283
        strcat(tbuf,bbuf);strcat(tbuf,"\n");
1284
     }
1285
    setenv("insplot_source",tbuf,1);
1286
    if(varchr(tbuf,"s")!=NULL) multanim=1;
10 reyssat 1287
    }
8155 bpr 1288
/* no illegal chaining */
10 reyssat 1289
    pp=getvar("insplot_font"); if(pp!=NULL) {
7379 bpr 1290
      for(s=pp;s<pp+MAX_LINELEN && *s;s++)
1291
      if(*s==';' || *s=='\n' || *s==' ') *s=0;
1292
      if(s>=pp+MAX_LINELEN) *s=0;
1293
      setvar("insplot_font",pp);
10 reyssat 1294
    }
1295
    pp=getvar("insplot_set"); if(pp!=NULL) {
7379 bpr 1296
      char tbuf[MAX_LINELEN+1];
1297
      mystrncpy(tbuf,pp,sizeof(tbuf));
1298
      i=strlen(tbuf)-1;
1299
      while(i>0 && isspace(tbuf[i])) i--;
1300
      if(tbuf[i]==';') tbuf[i]=0;
1301
      gnuplot_patch(tbuf,0);pp=tbuf;
1302
      ovlstrcpy(setbuf,"set "); j=strlen("set ");
1303
      for(i=0; *(pp+i)!=0 && j<MAX_LINELEN; i++) {
1304
        if(*(pp+i)=='\n') {setbuf[j++]=' '; continue;}
1305
        if(*(pp+i)!=';') {setbuf[j++]=*(pp+i); continue;}
1306
        ovlstrcpy(setbuf+j,"\nset "); j+=strlen("\nset ");
1307
      }
1308
      setbuf[j]=0;
1309
      setenv("insplot_set",setbuf,1);
10 reyssat 1310
    }
1311
    else setenv("insplot_set","",1);
8155 bpr 1312
/* frames of animation */
10 reyssat 1313
    pp=getvar("ins_anim_frames");
1314
    if(pp!=NULL) i=evalue(pp); else i=1;
1315
    if(i>=ANIM_LIMIT) i=ANIM_LIMIT-1; if(i<1) i=1;
1316
    if(strstr(setbuf,"step")==NULL && strstr(p,"step")==NULL
1317
       && varchr(setbuf,"s")==NULL && varchr(p,"s")==NULL && !multanim) i=1;
1318
    setenv("ins_anim_frames",int2str(i),1);
1319
    setvar("ins_anim_frames","");
1320
    if(i>1) {setvar("ins_animation","yes");animated_ins=1;}
1321
    else setvar("ins_animation","no");
8155 bpr 1322
/* delay of animation */
10 reyssat 1323
    pp=getvar("ins_anim_delay");
1324
    if(pp!=NULL) d=evalue(pp); else d=0;
1325
    if(d>=10) d=10; if(d<0) d=0;
1326
    setenv("ins_anim_delay",int2str(d*100),1);
1327
}
1328
 
8152 bpr 1329
/* Insert dynamic 2d plot */
10 reyssat 1330
void exec_insplot(char *p)
1331
{
1332
    char *fmt;
1333
    if(robot_access) {
7379 bpr 1334
      *p=0; return;
10 reyssat 1335
    }
1336
    fmt=getvar("ins_format"); if(fmt==NULL || *fmt==0) fmt=DEFAULT_INS_FORMAT;
1337
    prepare_insplot_parm(p); setenv("insplot_method","2D",1);
1338
    _exec_ins(p,insplot_processor,fmt);
1339
    wrapexec=1;
1340
/*    call_ssh("mv %s/insplot_cmd %s 2>/dev/null",tmp_dir,s2_prefix); */
1341
    unsetenv("multiplot"); setvar("insplot_split","");
1342
}
1343
 
8213 bpr 1344
/* Insert dynamic 3d plot */
10 reyssat 1345
void exec_insplot3d(char *p)
1346
{
1347
    char *fmt;
1348
    if(robot_access) {
7370 bpr 1349
     *p=0; return;
10 reyssat 1350
    }
1351
    fmt=getvar("ins_format"); if(fmt==NULL || *fmt==0) fmt=DEFAULT_INS_FORMAT;
1352
    prepare_insplot_parm(p); setenv("insplot_method","3D",1);
1353
    _exec_ins(p,insplot_processor,fmt);
1354
    wrapexec=1;
1355
/*     call_ssh("mv %s/insplot_cmd %s 2>/dev/null",tmp_dir,s2_prefix); */
1356
    unsetenv("multiplot");setvar("insplot_split","");
1357
}
1358
 
8155 bpr 1359
/* Insert dynamic gif draw. The parm preparation is specific to fly. */
10 reyssat 1360
void exec_insdraw(char *p)
1361
{
1362
    char *pp, *fmt;
1363
    int i;
1364
    double d;
7379 bpr 1365
 
10 reyssat 1366
    if(robot_access) {
7370 bpr 1367
      *p=0; return;
10 reyssat 1368
    }
7370 bpr 1369
/*    calc_tolower(p);*/
10 reyssat 1370
    fmt=getvar("ins_format"); if(fmt==NULL || *fmt==0) fmt=DEFAULT_INS_FORMAT;
1371
    while((pp=wordchr(p,"output"))!=NULL) memmove(pp,"zqkwfx",6);
8155 bpr 1372
/* frames of animation */
10 reyssat 1373
    pp=getvar("ins_anim_frames");
1374
    if(pp!=NULL) i=evalue(pp); else i=1;
1375
    if(i>=ANIM_LIMIT) i=ANIM_LIMIT-1; if(i<1) i=1;
1376
    if(i>1 && varchr(p,"s")==NULL && varchr(p,"animstep")==NULL
1377
       && varchr(p,"step")==NULL) i=1;
1378
    setenv("ins_anim_frames",int2str(i),1);
1379
    setvar("ins_anim_frames","");
1380
    if(i>1) {setvar("ins_animation","yes");animated_ins=1;}
1381
    else setvar("ins_animation","no");
8155 bpr 1382
/* delay of animation */
10 reyssat 1383
    pp=getvar("ins_anim_delay");
1384
    if(pp!=NULL) d=evalue(pp); else d=0;
1385
    if(d>=10) d=10; if(d<0) d=0;
1386
    setenv("ins_anim_delay",int2str(d*100),1);
1387
    pp=getvar("insdraw_filebase");
1388
    if(pp!=NULL && strstr(pp,parent_dir_string)!=NULL)
1389
      setvar("insdraw_filebase","");
1390
    _exec_ins(p,insdraw_processor,fmt);
1391
}
1392
 
1393
void exec_increase(char *p)
1394
{
1395
    char *p1, *p2;
1396
    p1=find_word_start(p); p2=find_word_end(p1);
1397
    if(p2<=p1) {
7370 bpr 1398
      *p=0; return;
10 reyssat 1399
    }
1400
    *p2=0;p2=getvar(p1);
1401
    if(p2==NULL) p2="";
1402
    setvar(p1,int2str(atoi(p2)+1)); *p=0;
1403
}
1404
 
7370 bpr 1405
/* bound a variable */
10 reyssat 1406
void exec_bound(char *p)
1407
{
1408
    char *p1, *p2, *p3;
1409
    int doub,i,bcnt,defaulted;
1410
    double d1,d2,dd,val;
1411
    char nbuf[MAX_LINELEN+1],lbuf[MAX_LINELEN+1],dbuf[MAX_LINELEN+1];
1412
    char vbuf[MAX_LINELEN+1];
1413
    char *blist[2048];
7379 bpr 1414
 
10 reyssat 1415
    p1=find_word_start(p); p2=find_word_end(p1);
1416
    if(*p2==0) {
7379 bpr 1417
      syntax: module_error("syntax_error");
10 reyssat 1418
    }
3718 reyssat 1419
    *p2=0; ovlstrcpy(nbuf,p1);substit(nbuf); p1=find_word_start(p2+1);
10 reyssat 1420
    p2=getvar(nbuf);if(p2==NULL) p2="";
1421
    mystrncpy(vbuf,find_word_start(p2),sizeof(vbuf));
1422
    strip_trailing_spaces(vbuf);
1423
    p2=find_word_end(p1); if(*p2==0) goto syntax;
1424
    *p2=0;p2++;
1425
    p3=wordchr(p2,"default");
1426
    if(p3!=NULL) {
7379 bpr 1427
      *p3=0; defaulted=1;
1428
      p3=find_word_start(p3+strlen("default"));
1429
      ovlstrcpy(dbuf,p3); substit(dbuf);
10 reyssat 1430
    }
1431
    else defaulted=0;
1432
    if(strcmp(p1,"between")==0) {
7379 bpr 1433
      p1=find_word_start(p2);
1434
      i=strlen("integer");
1435
      if(strncmp(p1,"integer",i)==0 &&
1436
       (isspace(*(p1+i)) || (*(p1+i)=='s' && isspace(*(p1+i+1))))) {
1437
        doub=0; p1=find_word_start(find_word_end(p1));
1438
        val=rint(evalue(vbuf));
1439
        if(vbuf[0]) float2str(val,vbuf);
1440
      }
1441
      else {
1442
        doub=1;val=evalue(vbuf);
1443
      }
1444
      p2=wordchr(p1,"and"); p3=p2+strlen("and");
1445
      if(p2==NULL) {
1446
       p2=strchr(p1,','); p3=p2+1;
1447
      }
1448
     if(p2==NULL) goto syntax;
1449
     *p2=0;p2=find_word_start(p3);
1450
     if(*p1==0 || *p2==0) goto syntax;
1451
     d1=evalue(p1);d2=evalue(p2);
8171 bpr 1452
     if(!isfinite(d1) || !isfinite(d2) ||
7379 bpr 1453
       abs(d1)>(double)(1E10) || abs(d2)>(double)(1E10)) goto syntax;
1454
     if(d1>d2) {
1455
        dd=d1;d1=d2;d2=dd;
1456
     }
1457
     if(vbuf[0] && val<=d2 && val>=d1) {
1458
        if(!doub) setvar(nbuf,vbuf);
1459
        *p=0; return;
1460
     }
1461
     if(defaulted) ovlstrcpy(p,dbuf);
1462
     else {
1463
      if(!doub) {
1464
       d1=ceil(d1);d2=floor(d2);
1465
      }
1466
      if(vbuf[0]==0 || val<d1) val=d1;
1467
      else val=d2;
1468
      float2str(val,p);
1469
     }
1470
     setvar(nbuf,p); *p=0; return;
10 reyssat 1471
    }
1472
    else {
7379 bpr 1473
    if(strcmp(p1,"within")==0 || strcmp(p1,"among")==0) {
1474
        ovlstrcpy(lbuf,p2);substit(lbuf);
1475
        bcnt=cutitems(lbuf,blist,2048);
1476
        if(bcnt<=0) {
1477
          *p=0; return;
1478
        }
1479
        for(i=0;i<bcnt;i++) {
1480
          if(strcmp(blist[i],vbuf)==0) {
1481
            *p=0; return;
1482
          }
1483
        }
1484
        if(defaulted) ovlstrcpy(p,dbuf); else ovlstrcpy(p,blist[0]);
1485
        setvar(nbuf,p); *p=0;
1486
        return;
10 reyssat 1487
    }
7379 bpr 1488
    else goto syntax;
1489
    }
10 reyssat 1490
}
1491
 
8155 bpr 1492
/* detrust the module. */
10 reyssat 1493
void exec_detrust(char *p)
7379 bpr 1494
{    untrust|=1; *p=0; }
10 reyssat 1495
 
1496
void exec_warn(char *p)
1497
{
1498
    char *p1,*p2;
1499
    char buf[MAX_FNAME+1];
1500
    WORKING_FILE save;
1501
 
1502
    if(!outputing) goto end;
1503
    p1=find_word_start(p);p2=find_word_end(p1);
1504
    if(p2<=p1) goto end;
1505
    *p2=0;
1506
    snprintf(buf,sizeof(buf),"wims_warn_%s",p1);
1507
    p2=getvar(buf);
1508
    if(p2==NULL || *p2==0) goto end;
1509
    p2=getvar("module_language");if(p2==NULL) p2="en";
1510
    mkfname(buf,"msg/warn_%s.phtml.%s",p1,p2);
1511
    memmove(&save,&m_file,sizeof(WORKING_FILE));
1512
    if(open_working_file(&m_file,buf)==0) phtml_put(NULL,0);
1513
    memmove(&m_file,&save,sizeof(WORKING_FILE));
1514
    end:
1515
    *p=0; return;
1516
}
1517
 
8155 bpr 1518
/* write an error message. */
10 reyssat 1519
void exec_msg(char *p)
1520
{
1521
    char *p1,*p2, buf[64], *l;
1522
    secure_exec();
1523
    p1=find_word_start(p); p2=find_word_end(p1);
1524
    if(*p2) {
7379 bpr 1525
      *p2=0; p2=find_word_start(p2+1);
10 reyssat 1526
    }
1527
    force_setvar("wims_error",p1); force_setvar("wims_error_parm",p2);
1528
    l=getvar("module_language");
1529
    if(l!=NULL && strlen(l)==2) {
7379 bpr 1530
      snprintf(buf,sizeof(buf),"msg.phtml.%s",l);
1531
      phtml_put_base(buf,0);
10 reyssat 1532
    }
1533
    *p=0;
1534
}
1535
 
8185 bpr 1536
struct distr_cmd distr_cmd[]={
7379 bpr 1537
      {"char",      NULL},
1538
      {"charof",    NULL},
1539
      {"chars",     NULL},
1540
      {"charsof",   NULL},
1541
      {"item",      cutitems},
1542
      {"itemof",    cutitems},
1543
      {"items",     cutitems},
1544
      {"itemsof",   cutitems},
1545
      {"line",      cutlines},
1546
      {"lineof",    cutlines},
1547
      {"lines",     cutlines},
1548
      {"linesof",   cutlines},
1549
      {"list",      cutitems},
1550
      {"word",      cutwords},
1551
      {"wordof",    cutwords},
1552
      {"words",     cutwords},
1553
      {"wordsof",   cutwords}
10 reyssat 1554
};
1555
 
8185 bpr 1556
int distr_cmd_no=(sizeof(distr_cmd)/sizeof(distr_cmd[0]));
10 reyssat 1557
 
8155 bpr 1558
/* distribute a number of lines, items, etc. into a list of vars. */
10 reyssat 1559
void exec_distribute(char *p)
1560
{
1561
    int i,k,n;
1562
    char *p1, *p2;
1563
    char bf1[MAX_LINELEN+1],bf2[MAX_LINELEN+1];
1564
    char *names[4096],*vals[4096];
1565
    p1=find_word_start(p); p2=find_word_end(p1);
1566
    if(p2<=p1 || *p2==0) module_error("syntax_error");
1567
    *p2++=0;
1568
    i=search_list(distr_cmd,distr_cmd_no,sizeof(distr_cmd[0]),p1);
1569
    if(i<0) module_error("syntax_error");
1570
    p2=find_word_start(p2); p1=wordchr(p2,"into");
1571
    if(p1==NULL) module_error("syntax_error");
1572
    *p1=0;mystrncpy(bf1,p2,sizeof(bf1));
1573
    p1=find_word_start(p1+strlen("into"));
1574
    mystrncpy(bf2,p1,sizeof(bf2));
1575
    substit(bf1);substit(bf2);
1576
    strip_trailing_spaces(bf1);
1577
    items2words(bf2); n=cutwords(bf2,names,4096);
1578
    if(distr_cmd[i].routine!=NULL) {
7379 bpr 1579
      k=distr_cmd[i].routine(bf1,vals,n);
1580
      for(i=0;i<k;i++) setvar(names[i],vals[i]);
1581
      for(;i<n;i++) setvar(names[i],"");
10 reyssat 1582
    }
1583
    else {
7379 bpr 1584
      char buf[2];
1585
      buf[1]=0;
1586
      for(p1=bf1,i=0;i<n;i++) {
1587
        buf[0]=*p1; if(*p1) p1++;
1588
        setvar(names[i],buf);
1589
      }
10 reyssat 1590
    }
1591
}
1592
 
8155 bpr 1593
/* reset variables */
10 reyssat 1594
void exec_reset(char *p)
1595
{
1596
    char *p1, *p2;
1597
 
1598
    items2words(p);
1599
    for(p1=find_word_start(p); *p1; p1=find_word_start(p2)) {
7379 bpr 1600
      p2=find_word_end(p1); if(*p2) *p2++=0;
1601
      setvar(p1,"");
10 reyssat 1602
    }
1603
}
1604
 
8155 bpr 1605
/* exchange the values of two variables */
10 reyssat 1606
void exec_exchange(char *p)
1607
{
1608
    char buf[MAX_LINELEN+1],b1[MAX_LINELEN+1],b2[MAX_LINELEN+1];
1609
    char *p1,*p2,*pb;
1610
    p1=wordchr(p,"and");
1611
    if(p1!=NULL) {
7379 bpr 1612
      *p1=0; p2=find_word_start(p1+strlen("and"));
10 reyssat 1613
    }
1614
    else {
7379 bpr 1615
      p1=strchr(p,',');
1616
      if(p1==NULL) module_error("syntax_error");
1617
      *p1=0; p2=find_word_start(p1+1);
10 reyssat 1618
    }
1619
    p1=find_word_start(p);
1620
    mystrncpy(b1,p1,sizeof(b1)); substit(b1); *find_word_end(b1)=0;
1621
    mystrncpy(b2,p2,sizeof(b2)); substit(b2); *find_word_end(b2)=0;
1622
    if(*b1==0 || *b2==0) module_error("syntax_error");
1623
    pb=getvar(b1);if(pb==NULL) pb="";
1624
    mystrncpy(buf,pb,sizeof(buf));
1625
    pb=getvar(b2);if(pb==NULL) pb="";
1626
    setvar(b1,pb); setvar(b2,buf);
1627
}
1628
 
8155 bpr 1629
/* Send a mail */
10 reyssat 1630
void exec_mailto(char *p)
1631
{
1632
    char *p1,*p2,*pp;
1633
 
1634
    if(!trusted_module() || is_class_module) return;
1635
    p1=strchr(p,'\n'); if(p1==NULL) return;
1636
    *p1++=0; p=find_word_start(p);
1637
    if(*p==0) return;
1638
    p2=strchr(p1,'\n'); if(p2==NULL) return;
1639
    *p2++=0;
1640
    for(pp=p1;*pp;pp++) if(*pp=='"' || *pp=='\n') *pp=' ';
1641
    accessfile(p2,"w","%s/mail.body",tmp_dir);
1642
    wrapexec=1;
1643
    call_sh("mail %s -s \" %s \" %s <%s/mail.body; chmod og-rwx %s/mail.body",
7379 bpr 1644
        mail_opt, p1,p,tmp_dir,tmp_dir);
10 reyssat 1645
    mail_log(p);
1646
    *p=0;
1647
}
1648
 
8155 bpr 1649
/* Generates a user error. Internal and undocumented. */
10 reyssat 1650
void exec_usererror(char *p)
1651
{
1652
    if(trusted_module()) user_error(p);
1653
}
1654
 
8155 bpr 1655
/* stop output. */
10 reyssat 1656
void exec_directout(char *p)
1657
{
1658
    if(outputing || !trusted_module()) return;
1659
    printf("%s",p);
1660
    noout=1;
1661
}
1662
 
1663
enum {
1664
      EXEC_IF, EXEC_JUMP, EXEC_ELSE, EXEC_ENDIF, EXEC_EXEC,
1665
      EXEC_WHILE, EXEC_ENDWHILE,
1666
      EXEC_FOR, EXEC_VAR, EXEC_DEBUG, EXEC_DAEMON,
1667
      EXEC_SET, EXEC_DEFAULT, EXEC_COMMENT, EXEC_READ, EXEC_HREF,
1668
      EXEC_INS, EXEC_STRING, EXEC_PEDIA, EXEC_DIR,
1669
      EXEC_TRUST, EXEC_WARN, EXEC_ERROR, EXEC_SQL, EXEC_SCORE,
1670
      EXEC_MAIL, EXEC_OTHER
1671
} EXEC_TYPES;
1672
#define EXEC_SUBST 0x1000
1673
#define EXEC_USECALC 0x2000
1674
#define EXEC_PROCTOO 0x4000
1675
MYFUNCTION exec_routine[]={
7379 bpr 1676
      {"!",        EXEC_COMMENT,        exec_comment},
1677
      {"TeXmath",  EXEC_STRING|EXEC_SUBST|EXEC_USECALC,texmath},
1678
      {"add",      EXEC_STRING|EXEC_USECALC,calc_sum},
1679
      {"advance",  EXEC_VAR|EXEC_SUBST,   exec_increase},
1680
      {"append",   EXEC_STRING|EXEC_USECALC,calc_append},
1681
      {"appendfile",EXEC_DIR|EXEC_SUBST,    fileappend},
1682
      {"bound",     EXEC_STRING,       exec_bound},
1683
      {"break",     EXEC_FOR,        exec_break},
1684
      {"call",      EXEC_EXEC|EXEC_SUBST|EXEC_PROCTOO|EXEC_USECALC,    calc_exec},
1685
      {"changeto",  EXEC_READ|EXEC_SUBST,    exec_changeto},
1686
      {"char",      EXEC_STRING|EXEC_USECALC,calc_charof},
1687
      {"chars",     EXEC_STRING|EXEC_USECALC,calc_charof},
1688
      {"checkhost", EXEC_STRING|EXEC_USECALC|EXEC_SUBST,calc_checkhost},
1689
      {"column",    EXEC_STRING|EXEC_USECALC,calc_columnof},
1690
      {"columns",   EXEC_STRING|EXEC_USECALC,calc_columnof},
1691
      {"comment",   EXEC_COMMENT,        exec_comment},
1692
      {"daemon",    EXEC_DAEMON|EXEC_USECALC|EXEC_SUBST,calc_daemon},
1693
      {"date",      EXEC_STRING|EXEC_USECALC|EXEC_SUBST,calc_date},
1694
      {"deaccent",  EXEC_STRING|EXEC_USECALC|EXEC_SUBST,deaccent},
1695
      {"debug",     EXEC_DEBUG,        calc_debug},
1696
      {"declosing", EXEC_STRING|EXEC_USECALC|EXEC_SUBST,calc_declosing},
1697
      {"def",       EXEC_SET,        exec_set},
1698
      {"default",   EXEC_SET,        exec_default},
1699
      {"define",    EXEC_SET,        exec_set},
1700
      {"definitionof", EXEC_SCORE|EXEC_USECALC,calc_defof},
1701
      {"defof",     EXEC_SCORE|EXEC_USECALC,calc_defof},
1702
      {"defread",   EXEC_READ|EXEC_SUBST,    exec_defread},
1703
      {"detag",     EXEC_STRING|EXEC_USECALC|EXEC_SUBST,calc_detag},
1704
      {"detrust",   EXEC_TRUST,        exec_detrust},
1705
/*      {"dictionary",EXEC_STRING|EXEC_USECALC,calc_dictionary},    */
1706
      {"dir",       EXEC_DIR|EXEC_SUBST|EXEC_USECALC,calc_listfile},
1707
      {"distribute",EXEC_STRING,        exec_distribute},
1708
      {"distrust",  EXEC_TRUST,        exec_detrust},
1709
      {"else",      EXEC_ELSE,        exec_else},
1710
      {"embraced",  EXEC_STRING|EXEC_USECALC,calc_embraced},
1711
      {"encyclo",   EXEC_PEDIA|EXEC_SUBST|EXEC_USECALC,pedia},
1712
      {"encyclopedia",EXEC_PEDIA|EXEC_SUBST|EXEC_USECALC,pedia},
1713
      {"endif",     EXEC_ENDIF,        exec_endif},
1714
      {"endwhile",  EXEC_ENDWHILE,        exec_endwhile},
1715
      {"evalsubst", EXEC_STRING|EXEC_USECALC,calc_evalsubst},
1716
      {"evalsubstit",EXEC_STRING|EXEC_USECALC,calc_evalsubst},
10 reyssat 1717
      {"evalsubstitute",EXEC_STRING|EXEC_USECALC,calc_evalsubst},
7379 bpr 1718
      {"evaluesubst",EXEC_STRING|EXEC_USECALC,calc_evalsubst},
1719
      {"evaluesubstit",EXEC_STRING|EXEC_USECALC,calc_evalsubst},
10 reyssat 1720
      {"evaluesubstitute",EXEC_STRING|EXEC_USECALC,calc_evalsubst},
7379 bpr 1721
      {"examscore", EXEC_SCORE|EXEC_SUBST|EXEC_USECALC,calc_examscore},
1722
      {"exchange",  EXEC_STRING,        exec_exchange},
1723
      {"exec",      EXEC_EXEC|EXEC_SUBST|EXEC_PROCTOO|EXEC_USECALC,    calc_exec},
1724
      {"execute",   EXEC_EXEC|EXEC_SUBST|EXEC_PROCTOO|EXEC_USECALC,    calc_exec},
1725
      {"exit",      EXEC_JUMP,        exec_exit},
1726
      {"fileappend",EXEC_DIR|EXEC_SUBST,    fileappend},
1727
      {"filelist",  EXEC_DIR|EXEC_SUBST|EXEC_USECALC,calc_listfile},
1728
      {"fileout",   EXEC_HREF|EXEC_SUBST,    exec_getfile},
1729
      {"filewrite", EXEC_DIR|EXEC_SUBST,    filewrite},
1730
      {"for",       EXEC_FOR,        exec_for},
1731
      {"form",      EXEC_HREF|EXEC_SUBST,    exec_form},
1732
      {"formbar",   EXEC_HREF,        exec_formbar},
1733
      {"formcheckbox",EXEC_HREF,        exec_formcheckbox},
1734
      {"formend",   EXEC_STRING,    exec_formend},
1735
      {"formradio", EXEC_HREF,        exec_formradio},
1736
      {"formradiobar",EXEC_HREF,        exec_formbar},
1737
      {"formselect",EXEC_HREF,        exec_formselect},
1738
      {"getdef",    EXEC_SCORE|EXEC_USECALC,calc_defof},
1739
      {"getfile",   EXEC_HREF|EXEC_SUBST,    exec_getfile},
1740
      {"getscore",  EXEC_SCORE|EXEC_SUBST|EXEC_USECALC,calc_getscore},
7638 bpr 1741
      {"getscorebest",EXEC_SCORE|EXEC_SUBST|EXEC_USECALC,calc_getscorebest},
7602 bpr 1742
      {"getscorelast",EXEC_SCORE|EXEC_SUBST|EXEC_USECALC,calc_getscorelast},
7657 bpr 1743
      {"getscorelevel",EXEC_SCORE|EXEC_SUBST|EXEC_USECALC,calc_getscorelevel},
7379 bpr 1744
      {"getscoremean",EXEC_SCORE|EXEC_SUBST|EXEC_USECALC,calc_getscoremean},
10 reyssat 1745
      {"getscorepercent",EXEC_SCORE|EXEC_SUBST|EXEC_USECALC,calc_getscorepercent},
7657 bpr 1746
      {"getscorequality",EXEC_SCORE|EXEC_SUBST|EXEC_USECALC,calc_getscoremean},
10 reyssat 1747
      {"getscoreremain",EXEC_SCORE|EXEC_SUBST|EXEC_USECALC,calc_getscoreremain},
1748
      {"getscorerequire",EXEC_SCORE|EXEC_SUBST|EXEC_USECALC,calc_getscorerequire},
7602 bpr 1749
      {"getscoretry",EXEC_SCORE|EXEC_SUBST|EXEC_USECALC,calc_getscoretry},
10 reyssat 1750
      {"getscoreweight",EXEC_SCORE|EXEC_SUBST|EXEC_USECALC,calc_getscoreweight},
7379 bpr 1751
      {"goto",      EXEC_JUMP|EXEC_SUBST,    exec_goto},
1752
      {"header",    EXEC_HREF,        exec_header},
1753
      {"header1",   EXEC_HREF,        exec_header1},
1754
      {"headmenu",  EXEC_HREF,        exec_headmenu},
1755
      {"hex",       EXEC_STRING|EXEC_SUBST|EXEC_USECALC,calc_hex},
1756
      {"homeref",   EXEC_HREF,        exec_homeref},
1757
      {"href",      EXEC_HREF,        exec_href},
1758
      {"htmlbar",   EXEC_HREF,        exec_formbar},
1759
      {"htmlcheckbox",EXEC_HREF,        exec_formcheckbox},
1760
      {"htmlheader",EXEC_HREF,        exec_header},
1761
      {"htmlmath",  EXEC_STRING|EXEC_SUBST|EXEC_USECALC,htmlmath},
1762
      {"htmlradio", EXEC_HREF,        exec_formradio},
1763
      {"htmlradiobar",EXEC_HREF,        exec_formbar},
1764
      {"htmlselect",EXEC_HREF,        exec_formselect},
1765
      {"htmltail",  EXEC_HREF,        exec_tail},
1766
      {"htmltitle", EXEC_HREF,        exec_title},
1767
      {"if",        EXEC_IF,        exec_if},
1768
      {"ifval",     EXEC_IF,        exec_ifval},
1769
      {"ifvalue",   EXEC_IF,        exec_ifval},
1770
      {"imgrename", EXEC_STRING|EXEC_USECALC|EXEC_SUBST,calc_imgrename},
1771
      {"include",   EXEC_READ|EXEC_SUBST,   exec_read},
1772
      {"increase",  EXEC_VAR|EXEC_SUBST,    exec_increase},
1773
      {"input",     EXEC_READ|EXEC_SUBST,    exec_read},
1774
      {"insdraw",   EXEC_INS|EXEC_SUBST,    exec_insdraw},
1775
      {"insmath",   EXEC_INS,        insmath},
1776
      {"inspaint",  EXEC_INS|EXEC_SUBST,    exec_insdraw},
1777
      {"insplot",   EXEC_INS|EXEC_SUBST,    exec_insplot},
1778
      {"insplot3d", EXEC_INS|EXEC_SUBST,    exec_insplot3d},
1779
      {"instex",    EXEC_INS,        exec_instex},
1780
      {"instexst",  EXEC_INS|EXEC_USECALC,    calc_instexst},
1781
      {"instexstatic",EXEC_INS|EXEC_USECALC,    calc_instexst},
1782
      {"item",        EXEC_STRING|EXEC_USECALC,calc_itemof},
1783
      {"items",     EXEC_STRING|EXEC_USECALC,calc_itemof},
1784
      {"items2lines", EXEC_STRING|EXEC_SUBST|EXEC_USECALC,items2lines},
1785
      {"items2words",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,items2words},
1786
      {"itemstolines",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,items2lines},
1787
      {"itemstowords",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,items2words},
1788
      {"let",        EXEC_SET,        exec_set},
1789
      {"leveldata",  EXEC_STRING|EXEC_USECALC,calc_leveldata},
1790
      {"levelpoints",EXEC_STRING|EXEC_USECALC,calc_leveldata},
1791
      {"line",       EXEC_STRING|EXEC_USECALC,calc_lineof},
1792
      {"lines",      EXEC_STRING|EXEC_USECALC,calc_lineof},
1793
      {"lines2items",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,lines2items},
1794
      {"lines2list", EXEC_STRING|EXEC_SUBST|EXEC_USECALC,lines2items},
1795
      {"lines2words",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,lines2words},
1796
      {"linestoitems",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,lines2items},
1797
      {"linestolist",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,lines2items},
1798
      {"linestowords",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,lines2words},
1799
      {"list2lines", EXEC_STRING|EXEC_SUBST|EXEC_USECALC,items2lines},
1800
      {"list2words", EXEC_STRING|EXEC_SUBST|EXEC_USECALC,items2words},
1801
      {"listfile",   EXEC_DIR|EXEC_SUBST|EXEC_USECALC,calc_listfile},
1802
      {"listfiles",  EXEC_DIR|EXEC_SUBST|EXEC_USECALC,calc_listfile},
1803
      {"listintersect",EXEC_STRING|EXEC_USECALC,calc_listintersect},
10 reyssat 1804
      {"listintersection", EXEC_STRING|EXEC_USECALC,calc_listintersect},
7379 bpr 1805
      {"listtolines",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,items2lines},
1806
      {"listtowords",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,items2words},
1807
      {"listunion",  EXEC_STRING|EXEC_USECALC,calc_listunion},
1808
      {"listuniq",   EXEC_STRING|EXEC_SUBST|EXEC_USECALC,calc_listuniq},
1809
      {"listunique", EXEC_STRING|EXEC_SUBST|EXEC_USECALC,calc_listuniq},
1810
      {"listvar",    EXEC_STRING|EXEC_SUBST|EXEC_USECALC,mathvarlist},
1811
      {"lookup",     EXEC_STRING|EXEC_USECALC,    calc_lookup},
1812
      {"lower",      EXEC_STRING|EXEC_SUBST|EXEC_USECALC,calc_tolower},
1813
      {"lowercase",  EXEC_STRING|EXEC_SUBST|EXEC_USECALC,calc_tolower},
1814
      {"ls",         EXEC_DIR|EXEC_SUBST|EXEC_USECALC,calc_listfile},
1815
      {"mailto",     EXEC_MAIL|EXEC_SUBST,    exec_mailto},
1816
      {"mailurl",    EXEC_MAIL|EXEC_SUBST|EXEC_USECALC,calc_mailurl},
1817
      {"makelist",   EXEC_STRING|EXEC_USECALC,calc_makelist},
1818
      {"math2html",  EXEC_STRING|EXEC_SUBST|EXEC_USECALC,htmlmath},
1819
      {"math2mathml",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,mathmlmath},
1820
      {"math2tex",   EXEC_STRING|EXEC_SUBST|EXEC_USECALC,texmath},
1821
      {"mathmlmath", EXEC_STRING|EXEC_SUBST|EXEC_USECALC,mathmlmath},
1822
      {"mathsubst",  EXEC_STRING|EXEC_USECALC,calc_mathsubst},
1823
      {"mathsubstit",EXEC_STRING|EXEC_USECALC,calc_mathsubst},
10 reyssat 1824
      {"mathsubstitute",EXEC_STRING|EXEC_USECALC,calc_mathsubst},
7379 bpr 1825
      {"mexec",     EXEC_EXEC|EXEC_SUBST,    exec_mexec},
1826
      {"module",    EXEC_STRING|EXEC_SUBST|EXEC_USECALC,calc_module},
1827
      {"msg",       EXEC_EXEC|EXEC_SUBST,exec_msg},
1828
      {"multiply",  EXEC_STRING|EXEC_USECALC,calc_product},
1829
      {"next",      EXEC_FOR,        exec_next},
1830
      {"nocache",   EXEC_READ,        exec_nocache},
1831
      {"non_empty", EXEC_STRING|EXEC_SUBST|EXEC_USECALC,calc_nonempty},
1832
      {"nonempty",  EXEC_STRING|EXEC_SUBST|EXEC_USECALC,calc_nonempty},
1833
      {"nospace",   EXEC_STRING|EXEC_SUBST|EXEC_USECALC,nospace},
1834
      {"outfile",   EXEC_HREF|EXEC_SUBST,    exec_getfile},
1835
      {"pedia",     EXEC_PEDIA|EXEC_SUBST|EXEC_USECALC,pedia},
1836
      {"perl",      EXEC_EXEC|EXEC_PROCTOO|EXEC_SUBST,exec_perl},
1837
      {"position",  EXEC_STRING|EXEC_USECALC,calc_pos},
1838
      {"positionof",EXEC_STRING|EXEC_USECALC,calc_pos},
1839
      {"positions", EXEC_STRING|EXEC_USECALC,calc_pos},
1840
      {"prod",      EXEC_STRING|EXEC_USECALC,calc_product},
1841
      {"product",   EXEC_STRING|EXEC_USECALC,calc_product},
1842
      {"rawmath",   EXEC_STRING|EXEC_SUBST|EXEC_USECALC,rawmath},
1843
      {"rawmatrix", EXEC_STRING|EXEC_SUBST|EXEC_USECALC,rawmatrix},
1844
      {"reaccent",  EXEC_STRING|EXEC_USECALC|EXEC_SUBST,reaccent},
1845
      {"read",      EXEC_READ|EXEC_SUBST,    exec_read},
1846
      {"readdef",   EXEC_READ|EXEC_SUBST,    exec_defread},
1847
      {"readproc",  EXEC_READ|EXEC_SUBST,    exec_readproc},
1848
      {"record",    EXEC_STRING|EXEC_USECALC,calc_recordof},
1849
      {"records",   EXEC_STRING|EXEC_USECALC,calc_recordof},
1850
      {"recursion", EXEC_STRING|EXEC_USECALC,calc_recursion},
1851
      {"reinput",   EXEC_STRING|EXEC_USECALC|EXEC_SUBST,calc_reinput},
1852
      {"rem",       EXEC_COMMENT,        exec_comment},
1853
      {"remark",    EXEC_COMMENT,        exec_comment},
1854
      {"replace",   EXEC_STRING|EXEC_USECALC,calc_replace},
1855
      {"reset",     EXEC_SET|EXEC_SUBST,    exec_reset},
1856
      {"restart",   EXEC_JUMP|EXEC_SUBST,    exec_restart},
1857
      {"return",    EXEC_JUMP,        exec_exit},
1858
      {"robotrap",  EXEC_HREF|EXEC_SUBST,    exec_robottrap},
1859
      {"robottrap", EXEC_HREF|EXEC_SUBST,    exec_robottrap},
1860
      {"rootof",    EXEC_STRING|EXEC_USECALC,calc_solve},
1861
      {"row",       EXEC_STRING|EXEC_USECALC,calc_rowof},
1862
      {"rows",      EXEC_STRING|EXEC_USECALC,calc_rowof},
1863
      {"rows2lines",EXEC_STRING|EXEC_USECALC|EXEC_SUBST,calc_rows2lines},
1864
      {"run",       EXEC_EXEC|EXEC_SUBST|EXEC_PROCTOO|EXEC_USECALC,    calc_exec},
1865
      {"select",    EXEC_STRING|EXEC_USECALC,calc_select},
1866
      {"set",       EXEC_SET,        exec_set},
1867
      {"setdef",    EXEC_OTHER,        exec_setdef},
1868
      {"sh",        EXEC_EXEC|EXEC_PROCTOO|EXEC_SUBST,exec_sh},
1869
      {"shortout",  EXEC_JUMP|EXEC_SUBST,    exec_directout},
1870
      {"singlespace",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,singlespace},
1871
      {"solve",     EXEC_STRING|EXEC_USECALC,calc_solve},
1872
      {"sort",      EXEC_STRING|EXEC_USECALC, calc_sort},
1873
/*      {"sql",     EXEC_SQL|EXEC_SUBST|EXEC_USECALC, calc_sql}, */
1874
      {"staticinstex",EXEC_INS|EXEC_USECALC,    calc_instexst},
1875
      {"stinstex",  EXEC_INS|EXEC_USECALC,    calc_instexst},
1876
      {"sum",       EXEC_STRING|EXEC_USECALC,calc_sum},
1877
      {"system",    EXEC_EXEC|EXEC_PROCTOO|EXEC_SUBST,exec_sh},
1878
      {"tail",      EXEC_HREF,        exec_tail},
1879
      {"test",      EXEC_DEBUG,        exec_test},
1880
      {"texmath",   EXEC_STRING|EXEC_SUBST|EXEC_USECALC,texmath},
1881
      {"text",      EXEC_STRING|EXEC_USECALC,text},
1882
      {"title",     EXEC_HREF,        exec_title},
1883
      {"tohex",     EXEC_STRING|EXEC_SUBST|EXEC_USECALC,calc_hex},
1884
      {"tolower",   EXEC_STRING|EXEC_SUBST|EXEC_USECALC,calc_tolower},
1885
      {"toupper",   EXEC_STRING|EXEC_SUBST|EXEC_USECALC,calc_toupper},
1886
      {"translate", EXEC_STRING|EXEC_USECALC,calc_translate},
1887
      {"trim",      EXEC_STRING|EXEC_USECALC,calc_trim},
1888
      {"upper",     EXEC_STRING|EXEC_SUBST|EXEC_USECALC,calc_toupper},
1889
      {"uppercase", EXEC_STRING|EXEC_SUBST|EXEC_USECALC,calc_toupper},
1890
      {"usererror", EXEC_WARN|EXEC_SUBST,    exec_usererror},
1891
      {"values",    EXEC_STRING|EXEC_USECALC,calc_values},
1892
      {"varlist",   EXEC_STRING|EXEC_SUBST|EXEC_USECALC,mathvarlist},
1893
      {"warn",      EXEC_WARN|EXEC_SUBST,    exec_warn},
1894
      {"warning",   EXEC_WARN|EXEC_SUBST,    exec_warn},
1895
      {"while",     EXEC_WHILE,        exec_while},
1896
      {"whileval",  EXEC_WHILE,        exec_whileval},
1897
      {"whilevalue",EXEC_WHILE,        exec_whileval},
1898
      {"wimsheader",EXEC_HREF,        exec_header},
1899
      {"wimsref",   EXEC_HREF,        exec_homeref},
1900
      {"wimstail",  EXEC_HREF,        exec_tail},
1901
      {"wimstitle", EXEC_HREF,        exec_title},
1902
      {"word",      EXEC_STRING|EXEC_USECALC,calc_wordof},
1903
      {"words",     EXEC_STRING|EXEC_USECALC,calc_wordof},
1904
      {"words2items",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,words2items},
1905
      {"words2lines",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,words2lines},
1906
      {"words2list",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,words2items},
1907
      {"wordstoitems",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,words2items},
1908
      {"wordstolines",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,words2lines},
1909
      {"wordstolist",EXEC_STRING|EXEC_SUBST|EXEC_USECALC,words2items},
1910
      {"writefile", EXEC_DIR|EXEC_SUBST,    filewrite},
10 reyssat 1911
};
8185 bpr 1912
int EXEC_FN_NO=(sizeof(exec_routine)/sizeof(exec_routine[0]));
10 reyssat 1913
 
8155 bpr 1914
/* internal: to skip the content of a false if/while. */
10 reyssat 1915
static void _skip_contents(int isif)
1916
{
1917
    char buf[MAX_NAMELEN+8], *p1;
1918
    int i,j,loop;
1919
    loop=0;
1920
    while(m_file.linepointer<m_file.linecnt) {
7379 bpr 1921
      j=m_file.linepointer;
1922
      if((m_file.lines[j].isstart&2)==0) {
1923
        m_file.linepointer++; continue;
1924
      }
7407 bpr 1925
      i=m_file.lines[j].execcode;
7379 bpr 1926
      if(i<0) {
1927
        if(wgetline(buf,MAX_NAMELEN+4,&m_file)==EOF) return;
1928
        p1=buf+1; if(*p1!='i' && *p1!='e' && *p1!='w') continue;
1929
        *find_word_end(p1)=0;
1930
        i=search_list(exec_routine,EXEC_FN_NO,sizeof(exec_routine[0]),p1);
1931
        if(i>=0) m_file.lines[j].execcode=i;
1932
      }
1933
      else m_file.linepointer++;
1934
      if(i<0) continue;
1935
      switch(exec_routine[i].tag & 0xffff) {
1936
        case EXEC_WHILE:
1937
          if(!isif) loop++; break;
1938
        case EXEC_IF:
1939
          if(isif) loop++; break;
1940
        case EXEC_ELSE: {
1941
          if(!isif) break;
1942
          if(loop<=0) return; else break;
1943
        }
1944
        case EXEC_ENDIF: {
1945
          if(!isif) break;
1946
          if(loop>0) {
1947
            loop--; break;
1948
          }
1949
         else return;
1950
        }
1951
        case EXEC_ENDWHILE: {
1952
          if(isif) break;
1953
          if(loop>0) {
1954
              loop--; break;
1955
          }
1956
          else return;
1957
        }
1958
        default: break;
1959
      }
10 reyssat 1960
    }
1961
}
1962
 
8155 bpr 1963
/* Execute a command defined by !. Returns 0 if OK. */
10 reyssat 1964
void exec_main(char *p)
1965
{
1966
    int i,j;
1967
    char *pp;
1968
    char tbuf2[MAX_LINELEN+1];
1969
 
7379 bpr 1970
    pp=find_word_end(p);
10 reyssat 1971
    if(*pp!=0) {
7379 bpr 1972
      *(pp++)=0; pp=find_word_start(pp);
10 reyssat 1973
    }
1974
    i=m_file.lines[m_file.l].execcode;
1975
    if(i<0) {
7379 bpr 1976
      i=search_list(exec_routine,EXEC_FN_NO,sizeof(exec_routine[0]),p);
1977
      m_file.lines[m_file.l].execcode=i;
10 reyssat 1978
    }
1979
    if(i<0) {
7379 bpr 1980
      setvar(error_data_string,p); module_error("bad_cmd");
10 reyssat 1981
    }
8155 bpr 1982
/* called from !readdef, no right other than set; bail out */
10 reyssat 1983
    execnt++;
1984
    if((untrust&4)!=0 && (j=(exec_routine[i].tag&0xffff))!=EXEC_SET) {
7379 bpr 1985
      tbuf2[0]=0; exec_exit(tbuf2);
10 reyssat 1986
    }
3718 reyssat 1987
    ovlstrcpy(tbuf2,pp); j=exec_routine[i].tag;
10 reyssat 1988
    if(j&EXEC_SUBST) substit(tbuf2);
1989
    if(j&EXEC_USECALC) {
7379 bpr 1990
      if(!outputing && (j&EXEC_PROCTOO)==0) return;
1991
      exec_routine[i].routine(tbuf2); if(outputing) output0(tbuf2);
10 reyssat 1992
    }
1993
    else exec_routine[i].routine(tbuf2);
1994
    return;
1995
}
1996