Subversion Repositories wimsdev

Rev

Rev 11123 | Rev 13380 | 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 {
12247 bpr 57
  char *name;
58
  int type, parmcnt;
59
  void (*processor)(char *p[MAX_PARM]);
10 reyssat 60
} directives[]={
12247 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},
70
  {"description", t_head, 1, p_description},
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},
91
  {"nextstep", t_step, 1, p_nextstep},
92
  {"observation", t_head, 1, p_observation},
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},
100
  {"solution", t_sol, 1, p_solution},
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 {
12247 bpr 121
  char *parm[MAX_PARM];
122
  short int type, tag;
10 reyssat 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
{
12247 bpr 129
  int i,j,n;
130
  for(i=0;i<define_no;i++) {
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(", ");
10 reyssat 136
    }
12247 bpr 137
    printf("\n");
138
  }
10 reyssat 139
}
140
 
7677 bpr 141
/* get one input file */
10 reyssat 142
long int getinp(char fname[])
143
{
12247 bpr 144
  FILE *input;
145
  long int siz;
146
  int i;
7677 bpr 147
 
12247 bpr 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) {
152
    fclose(input);
153
    if(siz==0) return 0; else return -1;
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;
160
  for(i=0;i<siz;i++)
161
    if(inpbuf[i]==13 || (inpbuf[i]>=0 && inpbuf[i]<=6)) inpbuf[i]=' ';
162
  return siz;
10 reyssat 163
}
164
 
7677 bpr 165
/* Processes input file */
10 reyssat 166
void process(void)
167
{
12247 bpr 168
  char *p, *pe, *pp;
169
  int i,j;
7677 bpr 170
 
12247 bpr 171
  for(p=inpbuf,define_no=0;define_no<MAX_DEFINE && p<inpend;p++) {
172
    if(*p!='\\' && *p!='{' && (*p>6 || *p<0)) continue;
173
    if(*p>0 && *p<=6) {
174
      pe="";
175
      switch(*p) {
176
        case elsechar: pe="else"; break;
177
        case endifchar: pe="endif"; break;
178
        case nextchar: pe="next"; break;
179
        case whilechar: pe="endwhile"; break;
7677 bpr 180
      }
12247 bpr 181
      define[define_no].tag=posttag;
182
      define[define_no++].type=search_list(directives,dir_no,sizeof(directives[0]),pe);
183
      continue;
184
    }
185
    if(*p=='{') {
186
      if((p=find_matching(p+1,'}'))==NULL) oef_error("Unmatched parentheses???");
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
    }
7677 bpr 196
/*c=*pe; */*pe=0;
12247 bpr 197
    i=search_list(directives,dir_no,sizeof(directives[0]),p);
198
    if(i<0) {
199
      if(wordchr(mdef,p)!=NULL) {
200
        pe=find_matching(pp+1,'}'); if(pe==NULL) oef_error("Unmatched parentheses?");
201
        *pe=0;define[define_no].type=
7677 bpr 202
              search_list(directives,dir_no,sizeof(directives[0]),"mdef");
12247 bpr 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;
7677 bpr 209
      }
12247 bpr 210
      if((p=find_matching(pp+1,'}'))==NULL) oef_error("Unmatched parentheses?");
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;
217
      if((pe=find_matching(pp+1,'}'))==NULL) oef_error("Unmatched parentheses?");
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;
7677 bpr 225
      }
12247 bpr 226
      case t_head2: case t_lang: {
227
        define[define_no].parm[1]=directives[i].name;
228
        break;
229
      }
230
      case t_ans: {
231
        if(aocnt<256) ao[aocnt++]=t_ans;
232
        answercnt++; goto checkeq;
233
      }
234
      case t_step: {
235
        if(step_defined) oef_error("Multiple definition of steps.");
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,'}');
246
            if(pt2==NULL) oef_error("Unmatched parentheses?");
247
            pt3=find_word_start(pt2+1);
7677 bpr 248
          }
12247 bpr 249
          if(strcmp(directives[i].name,"if")==0 || strcmp(directives[i].name,"ifval")==0) {
250
            if(*pt3=='{') {
251
              *pt2=elsechar; *pt3=' ';
252
              pt2=find_matching(pt3,'}');
253
              if(pt2==NULL) oef_error("Unmatched parentheses?");
254
            }
255
            *pt2=endifchar;
7677 bpr 256
          }
12247 bpr 257
          else {
258
            if(strcmp(directives[i].name,"while")==0) *pt2=whilechar;
259
            else {
260
              varcnt++; *pt2=nextchar;
7677 bpr 261
            }
262
          }
12247 bpr 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;
7677 bpr 273
      }
12247 bpr 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: {
282
        if(posttag) oef_error("Multiple definition of statement.");
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
      }
10 reyssat 299
    }
12247 bpr 300
    define_no++; p=pe;
301
  }
10 reyssat 302
}
303
 
7677 bpr 304
/* Output one category */
10 reyssat 305
void _out(int typ)
306
{
12247 bpr 307
  int i, t;
308
  for(i=0;i<define_no;i++) {
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);
313
  }
10 reyssat 314
}
315
 
7677 bpr 316
/* Output the result */
10 reyssat 317
void output(void)
318
{
12247 bpr 319
  int i,k;
7677 bpr 320
/* no statement, nothing to do */
12247 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.");
323
  if(title_no>=0 && *(define[title_no].parm[0])!=0) {
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);
327
  }
328
  else {
329
    fprintf(outf,"!set title=No title\n");
330
  }
331
  fprintf(outf,"!if $wims_read_parm!=$empty\n\
10 reyssat 332
 !goto $wims_read_parm\n\
333
!endif\n");
12247 bpr 334
  fprintf(outf,"oef2wims_version=%s\n",VERSION);
335
  _out(t_head2);
336
  _out(t_head);
337
  _out(t_lang);
338
  if(aocnt>0) {
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,",");
10 reyssat 345
    }
12247 bpr 346
  }
347
  if(prevarcnt<varcnt) post=varcnt-prevarcnt; else post=0;
348
  fprintf(outf,"\n\
10 reyssat 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);
12247 bpr 369
  varcnt=start_varcnt; deftag=0;
370
  _out(t_def);
371
  _out(t_step);
7677 bpr 372
/*    _out(t_wims); */
12247 bpr 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);
381
  _out(t_latex);
382
  fprintf(outf,"\n!goto stat\n");
7677 bpr 383
/* second run to output execution codes */
12247 bpr 384
  p_statement(NULL);
385
  p_hint(NULL);
386
  p_help(NULL);
387
  p_solution(NULL);
388
  p_latex(NULL);
389
  if(post) {
390
    fprintf(outf,"\n!exit\n\n:postdef\n"); _out(t_def);
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++) {
398
    if(param[i].save==0) continue;
399
    if(k>0) fprintf(outf,",");
400
    k++;
401
    fprintf(outf,"%d",i);
402
  }
403
  fprintf(outf,"\nembedcnt=%d\n",embedcnt);
404
  fclose(outf);
10 reyssat 405
}
406
 
407
int main(int argc, char *argv[])
408
{
12247 bpr 409
  int t;
410
  sp_error=oef_error;
411
  substitute=substit;
412
  if(argc<=1) return 0; /* no input file */
413
  if(argc==2 && strcmp(argv[1],"table")==0) {
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;
417
  }
418
  if(argc>2) snprintf(outfname,sizeof(outfname),"%s",argv[2]);
419
  else {
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");
425
  }
426
  mdef=getenv("oef2wims_mdef"); if(mdef==NULL) mdef="";
427
  printf("%s..",argv[1]);
428
  t=getinp(argv[1]);
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.");
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;
10 reyssat 445
}