Subversion Repositories wimsdev

Rev

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

Rev Author Line No. Line
9095 bpr 1
/*  Copyright (C) 1998-2003 XIAO, Gang of Universite de Nice - Sophia Antipolis
10 reyssat 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
9095 bpr 10
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 reyssat 11
 *  GNU General Public License for more details.
12
 *
13
 *  You should have received a copy of the GNU General Public License
14
 *  along with this program; if not, write to the Free Software
15
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16
 */
17
 
18
 /* This program translates oef format exercises into wims internal data format. */
19
 
9095 bpr 20
#define MAX_TITLEN 60
8135 bpr 21
 
9095 bpr 22
#define MAX_PARM 10
23
#define MAX_PARAM 1024
24
#define MAX_DEFINE 1024
10 reyssat 25
#define MAX_FLEN 199999
8135 bpr 26
 
10 reyssat 27
#define VERSION "3.22"
28
 
8135 bpr 29
 
10 reyssat 30
#include "../Lib/libwims.h"
8135 bpr 31
#include "oef2wims.h"
10 reyssat 32
 
33
FILE *outf;
34
int choicecnt=0, answercnt=0, feedbackcnt=0, varcnt=0, conditioncnt=0, condans=0, has_plot=0;
35
char *primitive_dir="oef";
36
int has_help=0;
37
int posttag=0, prevarcnt=-1, post=0, deftag, prevars;
38
int start_varcnt=0;
39
int step_defined=0;
40
int embedcnt=0;
41
char *badpar=NULL;
7677 bpr 42
char *mdef; /* external definition */
10 reyssat 43
char *format="html";
44
 
45
int ao[256];
46
int aocnt=0;
47
 
8135 bpr 48
struct param param[MAX_PARAM+32];
10 reyssat 49
 
50
char *inpbuf, *inpend;
51
char outfname[1024];
52
 
9095 bpr 53
enum {t_tit, t_head, t_head2, t_lang, t_def, t_wims, t_form, t_main, t_plot, t_hint,
2656 bpr 54
      t_ans, t_choi, t_cond, t_cond2, t_sol, t_feedback, t_help, t_step, t_latex};
10 reyssat 55
 
56
struct {
57
    char *name;
9095 bpr 58
    int type, parmcnt;
10 reyssat 59
    void (*processor)(char *p[MAX_PARM]);
60
} directives[]={
9095 bpr 61
      {"answer", t_ans, 5, p_answer},
62
      {"author", t_head2, 1, p_header},
63
      {"choice", t_choi, 5, p_choice},
64
      {"complex", t_def, 2, p_complex},
65
      {"computeanswer", t_head, 1, p_computeanswer},
66
      {"condition", t_cond, 4, p_condition},
67
      {"conditions", t_cond2, 1, p_conditions},
68
      {"credits", t_def, 2, p_credits},
69
      {"css", t_head, 1, p_css},
9229 bpr 70
      {"description", t_head, 1, p_description},
9095 bpr 71
      {"else", t_def, 0, p_else},
72
      {"email", t_head2, 1, p_header},
73
      {"endif", t_def, 0, p_endif},
74
      {"endwhile", t_def, 0, p_endwhile},
75
      {"feedback", t_feedback, 2, p_feedback},
76
      {"for", t_def, 1, p_for},
77
      {"format", t_form, 1, empty},
78
      {"function", t_def, 2, p_func},
79
      {"help", t_help, 1, p_help},
80
      {"hint", t_hint, 1, p_hint},
81
      {"if", t_def, 1, p_if},
82
      {"ifval", t_def, 1, p_ifval},
83
      {"int", t_def, 2, p_int},
84
      {"integer", t_def, 2, p_int},
85
      {"keywords", t_head2, 1, p_header},
86
      {"language", t_head, 1, p_language},
87
      {"latex", t_latex, 1, p_latex},
88
      {"matrix", t_def, 2, p_matrix},
89
      {"mdef", t_def, 2, p_mdef},
90
      {"next", t_def, 0, p_next},
7677 bpr 91
      {"nextstep", t_step, 1, p_nextstep},
9229 bpr 92
      {"observation", t_head, 1, p_observation},
9095 bpr 93
      {"parameter", t_def, 2, p_parm},
94
      {"plot", t_plot, 3, p_plot},
95
      {"precision", t_head, 1, p_precision},
96
      {"range", t_head, 1, p_range},
97
      {"rational", t_def, 2, p_rational},
98
      {"real", t_def, 2, p_real},
99
      {"reply", t_ans, 5, p_answer},
7677 bpr 100
      {"solution", t_sol, 1, p_solution},
9095 bpr 101
      {"statement", t_main, 1, p_statement},
102
      {"steps", t_step, 1, p_steps},
103
      {"text", t_def, 2, p_text},
104
      {"title", t_tit, 1, empty},
105
      {"title_ca", t_lang, 1, p_header},
106
      {"title_cn", t_lang, 1, p_header},
107
      {"title_en", t_lang, 1, p_header},
108
      {"title_es", t_lang, 1, p_header},
109
      {"title_fr", t_lang, 1, p_header},
110
      {"title_it", t_lang, 1, p_header},
111
      {"title_nl", t_lang, 1, p_header},
112
      {"title_si", t_lang, 1, p_header},
113
      {"variable", t_def, 2, p_parm},
114
      {"while", t_def, 1, p_while},
115
      {"wims", t_wims, 1, p_wims}
10 reyssat 116
};
117
 
118
#define dir_no (sizeof(directives)/sizeof(directives[0]))
119
 
120
struct {
121
    char *parm[MAX_PARM];
122
    short int type, tag;
123
} define[MAX_DEFINE];
124
int define_no, title_no=-1, statement_no=-1;
125
 
7677 bpr 126
/* Debug output */
8918 bpr 127
void oef_debug(void)
10 reyssat 128
{
129
    int i,j,n;
130
    for(i=0;i<define_no;i++) {
7677 bpr 131
      printf("%s:       ",directives[define[i].type].name);
132
      n=directives[define[i].type].parmcnt;
133
      for(j=0;j<n;j++) {
134
          printf("%s",define[i].parm[j]);
135
          if(j<n-1) printf(", ");
136
      }
137
      printf("\n");
10 reyssat 138
    }
139
}
140
 
7677 bpr 141
/* get one input file */
10 reyssat 142
long int getinp(char fname[])
143
{
144
    FILE *input;
145
    long int siz;
146
    int i;
7677 bpr 147
 
10 reyssat 148
    input=fopen(fname,"r");
149
    if(input==NULL) return 0;
150
    fseek(input,0L,SEEK_END); siz=ftell(input);
151
    if(siz<=0 || siz>=MAX_FLEN) {
7677 bpr 152
      fclose(input);
153
      if(siz==0) return 0; else return -1;
10 reyssat 154
    }
155
    fseek(input,0L,SEEK_SET);
156
    inpbuf=xmalloc(siz+10);
157
    siz=fread(inpbuf,1,siz,input); fclose(input);
158
    if(siz<=0) return -1;
159
    inpend=inpbuf+siz; *inpend=0;
7677 bpr 160
    for(i=0;i<siz;i++)
10 reyssat 161
      if(inpbuf[i]==13 || (inpbuf[i]>=0 && inpbuf[i]<=6)) inpbuf[i]=' ';
162
    return siz;
163
}
164
 
7677 bpr 165
/* Processes input file */
10 reyssat 166
void process(void)
167
{
6790 bpr 168
    char *p, *pe, *pp;
10 reyssat 169
    int i,j;
7677 bpr 170
 
10 reyssat 171
    for(p=inpbuf,define_no=0;define_no<MAX_DEFINE && p<inpend;p++) {
7677 bpr 172
      if(*p!='\\' && *p!='{' && (*p>6 || *p<0)) continue;
173
      if(*p>0 && *p<=6) {
174
          pe=""; switch(*p) {
175
            case elsechar: pe="else"; break;
176
            case endifchar: pe="endif"; break;
177
            case nextchar: pe="next"; break;
178
            case whilechar: pe="endwhile"; break;
179
          }
180
          define[define_no].tag=posttag;
181
          define[define_no++].type=
182
            search_list(directives,dir_no,sizeof(directives[0]),pe);
183
          continue;
184
      }
185
      if(*p=='{') {
8195 bpr 186
          if((p=find_matching(p+1,'}'))==NULL) oef_error("Unmatched parentheses???");
7677 bpr 187
          continue;
188
      }
189
      p++;
190
      for(pe=p;isalnum(*pe) || *pe=='_'; pe++);
191
      pp=find_word_start(pe);
192
      if(*pp!='{') {
193
          if(pp>p) p=pp-1;
194
          continue;
195
      }
196
/*c=*pe; */*pe=0;
197
      i=search_list(directives,dir_no,sizeof(directives[0]),p);
198
      if(i<0) {
199
          if(wordchr(mdef,p)!=NULL) {
8195 bpr 200
            pe=find_matching(pp+1,'}'); if(pe==NULL) oef_error("Unmatched parentheses?");
7677 bpr 201
            *pe=0;define[define_no].type=
202
              search_list(directives,dir_no,sizeof(directives[0]),"mdef");
203
            replace_newline(pp+1);
204
            define[define_no].tag=posttag;
205
            define[define_no].parm[0]=p;
206
            define[define_no].parm[1]=pp+1;
207
            define_no++; p=pe;
208
            continue;
209
          }
8195 bpr 210
          if((p=find_matching(pp+1,'}'))==NULL) oef_error("Unmatched parentheses?");
7677 bpr 211
          continue;
212
      }
213
      define[define_no].type=i;
214
      define[define_no].tag=posttag;
215
      for(j=0;j<MAX_PARM && j<directives[i].parmcnt;j++,pp=find_word_start(pe+1)) {
216
          if(j>0 && *pp!='{') break;
8195 bpr 217
          if((pe=find_matching(pp+1,'}'))==NULL) oef_error("Unmatched parentheses?");
7677 bpr 218
          *pe=0; replace_newline(pp+1);
219
          define[define_no].parm[j]=pp+1;
220
      }
221
      for(;j<MAX_PARM;j++) define[define_no].parm[j]="";
222
      switch(directives[i].type) {
223
          case t_tit: {
224
            title_no=define_no; break;
225
          }
9095 bpr 226
          case t_head2: case t_lang: {
227
           define[define_no].parm[1]=directives[i].name;
9227 bpr 228
          break;
229
         }
7677 bpr 230
          case t_ans: {
231
            if(aocnt<256) ao[aocnt++]=t_ans;
232
            answercnt++; goto checkeq;
233
          }
234
          case t_step: {
8195 bpr 235
            if(step_defined) oef_error("Multiple definition of steps.");
7677 bpr 236
            step_defined=1; break;
237
          }
238
          case t_def: {
239
            char *pt;
240
            if(directives[i].parmcnt<2) {
241
                char *pt2, *pt3;
242
                pt=find_word_start(pe+1); pt3="";
243
                if(*pt!='{') pt2=pt;
244
                else {
245
                  *pt=' '; pt2=find_matching(pt,'}');
8195 bpr 246
                  if(pt2==NULL) oef_error("Unmatched parentheses?");
7677 bpr 247
                  pt3=find_word_start(pt2+1);
248
                }
8367 bpr 249
                if(strcmp(directives[i].name,"if")==0 || strcmp(directives[i].name,"ifval")==0) {
7677 bpr 250
                  if(*pt3=='{') {
251
                      *pt2=elsechar; *pt3=' ';
252
                      pt2=find_matching(pt3,'}');
8195 bpr 253
                      if(pt2==NULL) oef_error("Unmatched parentheses?");
7677 bpr 254
                  }
255
                  *pt2=endifchar;
256
                }
257
                else {
258
                  if(strcmp(directives[i].name,"while")==0) *pt2=whilechar;
259
                  else {
260
                      varcnt++; *pt2=nextchar;
261
                  }
262
                }
263
                break;
264
            }
265
            varcnt++;
266
            checkeq:
267
            if(*(define[define_no].parm[1])==0 &&
268
               (pt=strchr(define[define_no].parm[0],'='))!=NULL) {
269
                if(*(pt-1)==':') *(pt-1)=0;
270
                *pt=0; define[define_no].parm[1]=pt+1;
271
            }
272
            break;
273
          }
274
          case t_choi: {
275
            if(aocnt<256) ao[aocnt++]=t_choi;
276
            choicecnt++; break;
277
          }
278
          case t_cond: {
279
            conditioncnt++; break;
280
          }
281
          case t_main: {
8195 bpr 282
            if(posttag) oef_error("Multiple definition of statement.");
7677 bpr 283
            posttag=1; if(prevarcnt<0) prevarcnt=varcnt;
284
            statement_no=define_no; break;
285
          }
286
          case t_plot: {
287
            has_plot=1; break;
288
          }
289
          case t_form: {
290
            char *s=define[define_no].parm[0];
291
            s=find_word_start(s);*find_word_end(s)=0;
292
            if(strcasecmp(s,"html")==0) format="html";
293
            if(strcasecmp(s,"tex")==0) format="tex";
294
            break;
295
          }
296
          case t_feedback: {
297
            feedbackcnt++; break;
298
          }
299
      }
300
      define_no++; p=pe;
10 reyssat 301
    }
302
}
303
 
7677 bpr 304
/* Output one category */
10 reyssat 305
void _out(int typ)
306
{
307
    int i, t;
308
    for(i=0;i<define_no;i++) {
7677 bpr 309
      t=define[i].type;
310
      if(directives[t].type!=typ) continue;
311
      if(typ==t_def && define[i].tag!=deftag) continue;
312
      directives[t].processor(define[i].parm);
10 reyssat 313
    }
314
}
315
 
7677 bpr 316
/* Output the result */
10 reyssat 317
void output(void)
318
{
319
    int i,k;
7677 bpr 320
/* no statement, nothing to do */
8195 bpr 321
    if(statement_no<0) oef_error("No statement defined.");
322
    outf=fopen(outfname,"w"); if(outf==NULL) oef_error("Unable to open output file.");
10 reyssat 323
    if(title_no>=0 && *(define[title_no].parm[0])!=0) {
7677 bpr 324
      char *p=define[title_no].parm[0];
325
      if(strlen(p)>MAX_TITLEN) *(p+MAX_TITLEN)=0;
326
      fprintf(outf,"!set title=%s\n",p);
10 reyssat 327
    }
328
    else {
7677 bpr 329
      fprintf(outf,"!set title=No title\n");
10 reyssat 330
    }
331
    fprintf(outf,"!if $wims_read_parm!=$empty\n\
332
 !goto $wims_read_parm\n\
333
!endif\n");
334
    fprintf(outf,"oef2wims_version=%s\n",VERSION);
9095 bpr 335
    _out(t_head2);
10 reyssat 336
    _out(t_head);
9095 bpr 337
    _out(t_lang);
10 reyssat 338
    if(aocnt>0) {
7677 bpr 339
      int i;
340
      fprintf(outf,"\nansorder=");
341
      for(i=0;i<aocnt;i++) {
342
          if(ao[i]==t_ans) fprintf(outf,"r");
343
          else fprintf(outf,"c");
344
          if(i<aocnt-1) fprintf(outf,",");
345
      }
10 reyssat 346
    }
347
    if(prevarcnt<varcnt) post=varcnt-prevarcnt; else post=0;
348
    fprintf(outf,"\n\
349
varcnt=%d\n\
350
prevarcnt=%d\n\
351
postvarcnt=%d\n\
352
replycnt=%d\n\
353
choicecnt=%d\n\
354
conditioncnt=%d\n\
355
feedbackcnt=%d\n\
356
format=%s\n\n\
357
val1=$imagedir\n\
358
val2=$confparm1\n\
359
val3=$confparm2\n\
360
val4=$confparm3\n\
361
val5=$confparm4\n\n\
362
!if $testcondition=yes\n\
363
 !goto test\n\
364
!endif\n\
365
!if $status=waiting\n\
366
 !exit\n\
367
!endif\n\n",varcnt+1,prevarcnt,post,answercnt,choicecnt,
7677 bpr 368
          conditioncnt,feedbackcnt,format);
10 reyssat 369
    varcnt=start_varcnt; deftag=0;
370
    _out(t_def);
371
    _out(t_step);
7677 bpr 372
/*    _out(t_wims); */
10 reyssat 373
    _out(t_plot);
374
    answercnt=1; _out(t_ans);
375
    choicecnt=1; _out(t_choi);
376
    deftag=1; prevars=varcnt;
377
    _out(t_main);
378
    _out(t_hint);
379
    _out(t_help);
380
    _out(t_sol);
2656 bpr 381
    _out(t_latex);
10 reyssat 382
    fprintf(outf,"\n!goto stat\n");
7677 bpr 383
/* second run to output execution codes */
10 reyssat 384
    p_statement(NULL);
385
    p_hint(NULL);
386
    p_help(NULL);
387
    p_solution(NULL);
2656 bpr 388
    p_latex(NULL);
10 reyssat 389
    if(post) {
7677 bpr 390
      fprintf(outf,"\n!exit\n\n:postdef\n"); _out(t_def);
10 reyssat 391
    }
392
    fprintf(outf,"\n!exit\n\n:feedback\n");
393
    _out(t_feedback);
394
    fprintf(outf,"\n!exit\n\n:test\n");
395
    _out(t_cond2); conditioncnt=1; _out(t_cond);
396
    fprintf(outf,"\n!exit\n\n:stat\nvsavelist=");
397
    for(k=0,i=1;i<prevars;i++) {
7677 bpr 398
      if(param[i].save==0) continue;
11123 georgesk 399
      if(k>0) fprintf(outf,",");
400
      k++;
7677 bpr 401
      fprintf(outf,"%d",i);
10 reyssat 402
    }
403
    fprintf(outf,"\nembedcnt=%d\n",embedcnt);
404
    fclose(outf);
405
}
406
 
407
int main(int argc, char *argv[])
408
{
409
    int t;
8195 bpr 410
    sp_error=oef_error;
10 reyssat 411
    substitute=substit;
412
    if(argc<=1) return 0; /* no input file */
413
    if(argc==2 && strcmp(argv[1],"table")==0) {
7677 bpr 414
      if(verify_order(directives, dir_no, sizeof(directives[0]))) return -1;
415
      if(verify_order(specialfn, specialfn_no, sizeof(specialfn[0]))) return -1;
416
      puts("Table orders OK."); return 0;
10 reyssat 417
    }
418
    if(argc>2) snprintf(outfname,sizeof(outfname),"%s",argv[2]);
419
    else {
7677 bpr 420
      char *fe;
421
      snprintf(outfname,sizeof(outfname)-10,"%s",argv[1]);
422
      fe=outfname+strlen(outfname)-strlen(".oef");
423
      if(strcasecmp(fe,".oef")==0) *fe=0;
424
      strcat(fe,".def");
10 reyssat 425
    }
426
    mdef=getenv("oef2wims_mdef"); if(mdef==NULL) mdef="";
427
    printf("%s..",argv[1]);
428
    t=getinp(argv[1]);
8195 bpr 429
    if(t<0) oef_error("Source file bad or too long.");
430
    if(t==0) oef_error("Empty source file.");
431
    if(checkparentheses(inpbuf,1)!=0) oef_error("Unmatched parentheses");
432
    outf=fopen(outfname,"w"); if(outf==NULL) oef_error("Unable to open output file.");
10 reyssat 433
    fclose(outf); remove(outfname);
434
    vbuf_statement[0]=vbuf_hint[0]=vbuf_help[0]=vbuf_solution[0]=0;
435
    param[1].name="imagedir";param[1].type=pt_text;
436
    param[2].name="confparm1";param[2].type=pt_text;
437
    param[3].name="confparm2";param[3].type=pt_text;
438
    param[4].name="confparm3";param[4].type=pt_text;
439
    param[5].name="confparm4";param[5].type=pt_text;
440
    start_varcnt=6;
441
    process();
442
    output();
443
    printf(" -> %s\n",outfname);
444
    return 0;
445
}
446