Subversion Repositories wimsdev

Rev

Rev 9229 | Rev 12247 | 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_head2, t_lang, 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_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}
  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.  
  126. /* Debug output */
  127. void oef_debug(void)
  128. {
  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(", ");
  136.       }
  137.       printf("\n");
  138.     }
  139. }
  140.  
  141. /* get one input file */
  142. long int getinp(char fname[])
  143. {
  144.     FILE *input;
  145.     long int siz;
  146.     int i;
  147.  
  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;
  163. }
  164.  
  165. /* Processes input file */
  166. void process(void)
  167. {
  168.     char *p, *pe, *pp;
  169.     int i,j;
  170.  
  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=""; 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=='{') {
  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.       }
  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) {
  200.             pe=find_matching(pp+1,'}'); if(pe==NULL) oef_error("Unmatched parentheses?");
  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.           }
  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;
  225.           }
  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);
  248.                 }
  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;
  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: {
  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.           }
  299.       }
  300.       define_no++; p=pe;
  301.     }
  302. }
  303.  
  304. /* Output one category */
  305. void _out(int typ)
  306. {
  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.     }
  314. }
  315.  
  316. /* Output the result */
  317. void output(void)
  318. {
  319.     int i,k;
  320. /* no statement, nothing to do */
  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\
  332. !goto $wims_read_parm\n\
  333. !endif\n");
  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,",");
  345.       }
  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,
  368.           conditioncnt,feedbackcnt,format);
  369.     varcnt=start_varcnt; deftag=0;
  370.     _out(t_def);
  371.     _out(t_step);
  372. /*    _out(t_wims); */
  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");
  383. /* second run to output execution codes */
  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);
  405. }
  406.  
  407. int main(int argc, char *argv[])
  408. {
  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;
  445. }
  446.  
  447.