Subversion Repositories wimsdev

Rev

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