Subversion Repositories wimsdev

Rev

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