Subversion Repositories wimsdev

Rev

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