Subversion Repositories wimsdev

Rev

Rev 8148 | Rev 8918 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

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