Subversion Repositories wimsdev

Rev

Rev 13590 | 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. #include "../Lib/libwims.h"
  18. #include "oef2wims.h"
  19. int prepcnt;
  20. int ex_statement=0, ex_hint=0, ex_help=0, ex_solution=0, ex_latex=0;
  21.  
  22. const size_t MAX_KEY_LEN=128;
  23. char vbuf_statement[MAX_LINELEN+1];
  24. char vbuf_hint[MAX_LINELEN+1];
  25. char vbuf_help[MAX_LINELEN+1];
  26. char vbuf_solution[MAX_LINELEN+1];
  27. char vbuf_latex[MAX_LINELEN+1];
  28.  
  29. /* empty processor, template. */
  30. void empty(char *p[MAX_PARM]) {}
  31.  
  32. void p_header(char *p[MAX_PARM])
  33. {
  34.     p[0]=find_word_start(p[0]);
  35.     if(strlen(p[0])>MAX_KEY_LEN) p[0][MAX_KEY_LEN]=0;
  36.     fprintf(outf,"%s=%s\n", p[1], p[0]);
  37. }
  38.  
  39. void p_computeanswer(char *p[MAX_PARM])
  40. {
  41.     p[0]=find_word_start(p[0]);
  42.     *find_word_end(p[0])=0;
  43.     if(strcasecmp(p[0],"yes"))
  44.       fprintf(outf,"computeanswer=no\n");
  45.     else fprintf(outf,"computeanswer=%s\n",p[0]);
  46. }
  47.  
  48. void p_precision(char *p[MAX_PARM])
  49. {
  50.     int pr;
  51.     pr=atoi(p[0]);
  52.     if(pr<0 || pr>100000000) return;
  53.     fprintf(outf,"precision=%d\n",pr);
  54. }
  55. void p_gen2(char *name_gen, char *p[MAX_PARM])
  56. {
  57.     char vbuf_gen[MAX_LINELEN+1];
  58.     if(p==NULL) return;
  59.     snprintf(vbuf_gen,sizeof(vbuf_gen),"%s",p[0]); subst(vbuf_gen);
  60.     singlespace(vbuf_gen);
  61.     fprintf(outf,"%s=%s\n", name_gen, vbuf_gen);
  62. }
  63. void p_css(char *p[MAX_PARM]) {p_gen2("oefcss", p);}
  64. void p_credits(char *p[MAX_PARM]){p_gen2("credits", p);}
  65. void p_description(char *p[MAX_PARM]){p_gen2("oefdescription", p);}
  66. void p_observation(char *p[MAX_PARM]){p_gen2("oefobservation", p);}
  67.  
  68. void p_wims(char *p[MAX_PARM])
  69. {
  70.     char vbuf[MAX_LINELEN+1];
  71.     snprintf(vbuf,sizeof(vbuf),"%s",p[0]); subst(vbuf);
  72. /* the second condition could be removed?
  73.  * To be very careful! */
  74.     if(strchr(vbuf,'=')==NULL || strchr(vbuf,'!')!=NULL) return;
  75.     fprintf(outf,"%s\n",vbuf);
  76. }
  77.  
  78. void p_mdef(char *p[MAX_PARM])
  79. {
  80.     char vbuf[MAX_LINELEN+1];
  81.     if(wordchr(mdef,p[0])==NULL) return;
  82.     snprintf(vbuf,sizeof(vbuf),"%s",p[1]); subst(vbuf);
  83. /* the second condition could be removed?
  84.  * To be very careful! */
  85.     if(strchr(vbuf,'!')!=NULL) return;
  86.     fprintf(outf,"m_%s=%s\n",p[0],vbuf);
  87. }
  88.  
  89. void p_range(char *p[MAX_PARM])
  90. {
  91.     double left, right;
  92.     char *pp;
  93.     pp=strstr(p[0],"..");
  94.     if(pp==NULL) return;
  95.     *pp=0;pp+=strlen("..");
  96.     left=atof(p[0]); right=atof(pp);
  97.     if(left>=right-1E-50 || left<-1E50 || right>1E50) return;
  98.     fprintf(outf,"leftrange=%f\nrightrange=%f\n",left,right);
  99. }
  100.  
  101. void p_language(char *p[MAX_PARM])
  102. {
  103.     p[0]=find_word_start(p[0]);
  104.     *find_word_end(p[0])=0;
  105.     if(strlen(p[0])==2) fprintf(outf,"language=%s\n",p[0]);
  106. }
  107.  
  108. void p_statement(char *p[MAX_PARM])
  109. {
  110.     if(ex_statement<0) return;
  111.     if(ex_statement>0 || p==NULL) {
  112.       out_exec(vbuf_statement,"question");
  113.       ex_statement=-1; return;
  114.     }
  115.     if(p==NULL) return;
  116.     snprintf(vbuf_statement,sizeof(vbuf_statement),"%s",p[0]);
  117.     subst(vbuf_statement);
  118.     if(strcmp(format,"html")!=0) {
  119.       fprintf(outf,"question=!nosubst %s\n",vbuf_statement);
  120.       ex_statement=-1;
  121.     }
  122.     else {
  123.       fprintf(outf,"question=%s\n",executed_str);
  124.       ex_statement=1;
  125.     }
  126. }
  127. void p_latex(char *p[MAX_PARM])
  128. {
  129.     if(ex_latex<0) return;
  130.     if(ex_latex>0 || p==NULL) {
  131.       out_exec(vbuf_latex,"latex");
  132.       ex_latex=-1; return;
  133.     }
  134.     snprintf(vbuf_latex,sizeof(vbuf_latex),"%s",p[0]);
  135.     subst(vbuf_latex);
  136.     singlespace(vbuf_latex);
  137.     fprintf(outf,"latex=!nosubst %s\n\n", vbuf_latex);
  138. }
  139. void p_gen(int *ex_gen, char vbuf_gen[], char *name_gen, char *p[MAX_PARM])
  140. {
  141.     if(*ex_gen<0) return;
  142.     if(*ex_gen>0 || p==NULL) {
  143.       out_exec(vbuf_gen, name_gen);
  144.       *ex_gen=-1; return;
  145.     }
  146.     snprintf(vbuf_gen,MAX_LINELEN,"%s",p[0]); subst(vbuf_gen);
  147.     if(strchr(vbuf_gen,'\\')!=NULL) {
  148.       fprintf(outf,"%s=%s\n", name_gen, executed_str);
  149.       *ex_gen=1;
  150.     }
  151.     else {
  152.       singlespace(vbuf_gen);
  153.       fprintf(outf,"%s=!nosubst %s\n\n", name_gen, vbuf_gen);
  154.     }
  155. }
  156.  
  157. void p_hint(char *p[MAX_PARM]) {p_gen(&ex_hint, vbuf_hint, "hint", p);}
  158. void p_help(char *p[MAX_PARM]) {p_gen(&ex_help, vbuf_help, "help", p);}
  159. void p_solution(char *p[MAX_PARM]) {p_gen(&ex_solution, vbuf_solution, "solution", p);}
  160.  
  161. enum {typ_default, typ_num, typ_func, typ_units, typ_text,
  162.       typ_formal,typ_matrix,typ_vector,typ_set,typ_equation,
  163.       typ_case, typ_nocase, typ_atext, typ_wlist, typ_comp,
  164.       typ_algexp, typ_litexp, typ_menu, typ_coord, typ_fill,
  165.       typ_raw, typ_symtext,
  166.       typ_java, typ_src, typ_chem
  167. };
  168.  
  169. struct {
  170.     char *name;
  171.     int  type;
  172.     char *def;
  173. } anstype[]={
  174.       {"algexp", typ_algexp, "algexp"},
  175.       {"aset",  typ_set, "aset"},
  176.       {"atext",  typ_atext, "atext"},
  177.       {"case",  typ_case, "case"},
  178.       {"checkbox", typ_menu, "checkbox"},
  179.       {"chemeq",        typ_chem,       "chemeq"},
  180.       {"chset",  typ_atext, "chset"},
  181.       {"click",  typ_menu, "click"},
  182.       {"clickfill", typ_fill, "clickfill"},
  183.       {"code",  typ_src, "code"},
  184.       {"compose", typ_comp, "compose"},
  185.       {"coord",  typ_coord, "coord"},
  186.       {"coordinates", typ_coord, "coord"},
  187.       {"corresp", typ_comp, "correspond"},
  188.       {"correspond", typ_comp, "correspond"},
  189.       {"default", typ_default, "default"},
  190.       {"dragfill", typ_fill, "dragfill"},
  191.       {"equation", typ_equation, "equation"},
  192.       {"expalg", typ_algexp, "algexp"},
  193.       {"formal", typ_formal, "formal"},
  194.       {"fset",  typ_set, "fset"},
  195.       {"function", typ_func, "function"},
  196.       {"imgcomp", typ_comp, "imgcomp"},
  197.       {"javacurve", typ_java, "javacurve"},
  198.       {"link",  typ_menu, "click"},
  199.       {"litexp", typ_litexp, "litexp"},
  200.       {"mark",  typ_menu, "mark"},
  201.       {"matrix", typ_matrix, "matrix"},
  202.       {"menu",  typ_menu, "menu"},
  203.       {"nocase", typ_nocase, "nocase"},
  204.       {"number", typ_num, "numeric"},
  205.       {"numeric", typ_num, "numeric"},
  206.       {"numexp", typ_algexp, "numexp"},
  207.       {"radio",  typ_menu, "radio"},
  208.       {"range",  typ_func, "range"},
  209.       {"ranges", typ_func, "range"},
  210.       {"raw",  typ_raw, "raw"},
  211.       {"reorder", typ_comp, "reorder"},
  212.       {"select", typ_menu, "menu"},
  213.       {"set",  typ_set, "set"},
  214.       {"sigunits", typ_units, "sigunits"},
  215.       {"symtext", typ_symtext, "symtext"},
  216.       {"text",  typ_text, "case"},
  217.       {"textcomp", typ_comp, "textcomp"},
  218.       {"unit",  typ_units, "units"},
  219.       {"units",  typ_units, "units"},
  220.       {"vector", typ_vector, "vector"},
  221.       {"wlist",  typ_wlist, "wlist"},
  222.       {"wordcomp", typ_comp, "textcomp"}
  223. };
  224.  
  225. #define anstype_no (sizeof(anstype)/sizeof(anstype[0]))
  226.  
  227. void p_answer(char *p[MAX_PARM])
  228. {
  229.   char *pp, vbuf[MAX_LINELEN+1],nbuf[MAX_LINELEN+1];
  230.   int i,j,k,typ;
  231.  
  232. /* look for type definition */
  233.   typ=typ_default;
  234.   for(i=0;i<5;i++) {
  235.     if(p[i]==NULL || p[i][0]==0) continue;
  236.     p[i]=find_word_start(p[i]);
  237.     if(strncasecmp(p[i],"type",strlen("type"))==0) {
  238.       char *tt;
  239.       tt=find_word_start(p[i]+strlen("type"));
  240.       if(*tt=='=') {
  241.         for(j=i;j<6;j++) p[j]=p[j+1];
  242.         i--;
  243.         tt=find_word_start(tt+1); *find_word_end(tt)=0;
  244.         k=search_list(anstype,anstype_no,sizeof(anstype[0]),tt);
  245. /* unknown type is now substituted */
  246.         if(k>=0) {
  247.           fprintf(outf,"replytype%d=%s\n",
  248.                       answercnt,anstype[k].def);
  249.           typ=anstype[k].type;
  250.         }
  251.         else {
  252.           snprintf(nbuf,sizeof(nbuf),"%s",tt); subst(nbuf);
  253.           fprintf(outf,"replytype%d=%s\n\n",answercnt,nbuf);
  254.         }
  255.       }
  256.       continue;
  257.     }
  258.     if(strncasecmp(p[i],"option",strlen("option"))==0) {
  259.       char *tt, *tv;
  260.       tt=p[i]+strlen("option");
  261.       if(*tt=='s' || *tt=='S') tt++;
  262.       tt=find_word_start(tt);
  263.       if(*tt=='=') {
  264.         for(j=i;j<6;j++) p[j]=p[j+1];
  265.         i--;
  266.         snprintf(nbuf,sizeof(nbuf),"%s",tt+1); subst(nbuf);
  267.         /* comma and semicolumn are replaced by spaces in replyoption */
  268.         for(tv=nbuf; *tv; tv++) if(*tv==',' || *tv==';') *tv=' ';
  269.         strip_trailing_spaces(nbuf);
  270.         fprintf(outf,"replyoption%d=%s \n",answercnt,
  271.               find_word_start(nbuf));
  272.       }
  273.       continue;
  274.     }
  275.     if(strncasecmp(p[i],"weight",strlen("weight"))==0) {
  276.       char *tt;
  277.       tt=p[i]+strlen("weight");
  278.       tt=find_word_start(tt);
  279.       if(*tt=='=') {
  280.         for(j=i;j<6;j++) p[j]=p[j+1];
  281.         i--;
  282.         snprintf(nbuf,sizeof(nbuf),"%s",tt+1); subst(nbuf);
  283.         strip_trailing_spaces(nbuf);
  284.         fprintf(outf,"replyweight%d=%s \n",answercnt,
  285.               find_word_start(nbuf));
  286.       }
  287.       continue;
  288.     }
  289.   }
  290.   p[0]=find_word_start(p[0]);
  291.   strncpy(nbuf,p[0],MAX_LINELEN); nbuf[MAX_LINELEN]=0; subst(nbuf);
  292.   strip_trailing_spaces(nbuf);singlespace(nbuf);
  293.   if (strlen(nbuf)>= MAX_PROMPTLEN) oef_error("Answer prompt too long");
  294.   nbuf[MAX_PROMPTLEN]=0;
  295.   pp=nbuf+strlen(nbuf)-1;
  296.   if(*pp=='=') *pp=0;
  297.   p[1]=find_word_start(p[1]);
  298.   if(*p[1]=='\\' && (isalnum(*(p[1]+1)) || *(p[1]+1)=='_')) {
  299. /* check for analyzed answers */
  300.     int i,n; char *pt;
  301.     strncpy(vbuf,p[1]+1,MAX_LINELEN); vbuf[MAX_LINELEN]=0;
  302.     pt=strchr(vbuf,';'); if(pt!=NULL) *pt=0;
  303.     strip_trailing_spaces(vbuf); n=strlen(vbuf);
  304.     if(n>=MAX_NAMELEN) goto normal;
  305.     for(i=0;i<n && (isalnum(vbuf[i]) || vbuf[i]=='_');i++);
  306.     if(i<n) goto normal;
  307.     for(i=varcnt-1;i>=1 && strcmp(vbuf,param[i].name)!=0;i--);
  308.     if(i<1) { /* unused name; the answer should be analyzed */
  309.       char *pm;
  310.       pm=xmalloc(MAX_NAMELEN+2);
  311.       ovlstrcpy(pm,vbuf); param[varcnt].name=pm;
  312.       if(pt) {
  313.         *pt=';';
  314.         ovlstrcpy(vbuf,pt); subst(vbuf); pt=vbuf;
  315.       }
  316.       else pt="";
  317.       param[varcnt].type=pt_real;
  318.       param[varcnt].save=1;
  319.       fprintf(outf,"replyname%d=%s\nreplygood%d=?analyze %d%s\n",
  320.               answercnt,nbuf,answercnt,varcnt,pt);
  321.       condans++; answercnt++; varcnt++; return;
  322.     }
  323.   }
  324.   normal:
  325.   strncpy(vbuf,p[1],MAX_LINELEN); vbuf[MAX_LINELEN]=0;
  326.   subst(vbuf);
  327.   switch(typ) {
  328.     default:
  329.     case typ_default: {
  330.       fprintf(outf,"replyname%d=%s\nreplygood%d=%s\n",
  331.               answercnt,nbuf,answercnt,vbuf);
  332.       break;
  333.     }
  334.     case typ_num: {
  335.       fprintf(outf,"replyname%d=%s\nreplygood%d=$[%s]\n",
  336.               answercnt,nbuf,answercnt,vbuf);
  337.       break;
  338.     }
  339.     case typ_equation:
  340.     case typ_func: {
  341.       fprintf(outf,"replyname%d=%s\nreplygood%d=!rawmath %s\n",
  342.               answercnt,nbuf,answercnt,vbuf);
  343.       break;
  344.     }
  345.     case typ_units: {
  346.       fprintf(outf,"replyname%d=%s\nreplygood%d=%s\n",
  347.                 answercnt,nbuf,answercnt,vbuf);
  348.       break;
  349.     }
  350.   }
  351.   answercnt++;
  352. }
  353.  
  354. void p_choice(char *p[MAX_PARM])
  355. {
  356.   int i,j;
  357.   char buf1[MAX_LINELEN+1],buf2[MAX_LINELEN+1],nbuf[MAX_LINELEN+1];
  358.   for(i=0;i<5;i++) {
  359.     if(p[i]==NULL || p[i][0]==0) continue;
  360.     p[i]=find_word_start(p[i]);
  361.     if(strncasecmp(p[i],"option",strlen("option"))==0) {
  362.       char *tt, *tv;
  363.       tt=p[i]+strlen("option");
  364.       if(*tt=='s' || *tt=='S') tt++;
  365.       tt=find_word_start(tt);
  366.       if(*tt=='=') {
  367.         for(j=i;j<6;j++) p[j]=p[j+1];
  368.         i--;
  369.         snprintf(nbuf,sizeof(nbuf),"%s",tt+1); subst(nbuf);
  370.         for(tv=nbuf; *tv; tv++) if(*tv==',' || *tv==';') *tv=' ';
  371.         strip_trailing_spaces(nbuf);
  372.         fprintf(outf,"choiceoption%d=%s \n",choicecnt,
  373.               find_word_start(nbuf));
  374.       }
  375.       continue;
  376.     }
  377.     if(strncasecmp(p[i],"weight",strlen("weight"))==0) {
  378.       char *tt;
  379.       tt=p[i]+strlen("weight");
  380.       tt=find_word_start(tt);
  381.       if(*tt=='=') {
  382.         for(j=i;j<6;j++) p[j]=p[j+1];
  383.         i--;
  384.         snprintf(nbuf,sizeof(nbuf),"%s",tt+1); subst(nbuf);
  385.         strip_trailing_spaces(nbuf);
  386.         fprintf(outf,"choiceweight%d=%s \n",choicecnt,
  387.               find_word_start(nbuf));
  388.       }
  389.       continue;
  390.     }
  391.   }
  392.   p[0]=find_word_start(p[0]);
  393.   snprintf(buf1,sizeof(buf1),"%s",p[1]); subst(buf1);
  394.   snprintf(buf2,sizeof(buf2),"%s",p[2]); subst(buf2);
  395.   snprintf(nbuf,sizeof(nbuf),"%s",p[0]); subst(nbuf);
  396.   nbuf[MAX_PROMPTLEN]=0;
  397.   fprintf(outf,"choicename%d=%s\nchoicegood%d=%s\nchoicebad%d=%s\n",
  398.         choicecnt,nbuf,choicecnt,buf1,choicecnt,buf2);
  399.   choicecnt++;
  400. }
  401.  
  402. void putval(char *p, int n, int ptype)
  403. {
  404.   switch(ptype) {
  405.     case pt_int: {
  406.       fprintf(outf,"val%d=$[rint(%s)]\n",n,p);
  407.       break;
  408.     }
  409.     case pt_real: {
  410.       fprintf(outf,"val%d=$[%s]\n",n,p);
  411.       break;
  412.     }
  413.     case pt_func: {
  414.       fprintf(outf,"val%d=!rawmath %s\n",n,p);
  415.       break;
  416.     }
  417.     case pt_complex: {
  418.       fprintf(outf,"t_=!rawmath %s\nt_=!exec pari print($t_)\n\
  419. val%d=!mathsubst I=i in $t_\n",p,n);
  420.       break;
  421.     }
  422.     case pt_matrix: {
  423.       fprintf(outf,"tmp=!trim %s\n\
  424. val%d=!translate internal $     \\\n$ to ;; in $tmp\n",p,n);
  425.       break;
  426.     }
  427.     case pt_rat: {
  428.       fprintf(outf,"t_=!rawmath %s\n\
  429. val%d=!exec pari print($t_)\n",p,n);
  430.       break;
  431.     }
  432.     default: {
  433.       fprintf(outf,"val%d=%s\n",n,p);
  434.       break;
  435.     }
  436.   }
  437. }
  438.  
  439. void parm(char *p[MAX_PARM], int ptype)
  440. {
  441.   char *pp, *p2;
  442.   char vbuf[MAX_LINELEN+1];
  443.   int i;
  444.  
  445.   p[0]=find_word_start(p[0]);
  446.   if(*p[0]=='\\') p[0]++;
  447. /* bad name */
  448.   if(!isalpha(*p[0])) return;
  449.   strip_trailing_spaces(p[0]);
  450.   for(pp=p[0];*pp;pp++) if(!isalnum(*pp) && *pp!='_') {
  451. /* bad name and security risk */
  452.     if(!isspace(*pp)) return;
  453.     ovlstrcpy(pp,pp+1); pp--;
  454.   }
  455.   for(i=1;i<varcnt && strcmp(p[0],param[i].name)!=0;i++);
  456.   p[1]=find_word_start(p[1]);
  457.   snprintf(vbuf,sizeof(vbuf),"%s",p[1]); subst(vbuf);
  458.   if(deftag) repsubst(vbuf);
  459.   if((pp=strparchr(vbuf,'?'))!=NULL && pp[1]!='?') {
  460.     char buf[MAX_LINELEN+1];
  461.     if(check_compare(vbuf)==0) goto noif;
  462.     p2=strparchr(pp,':'); *pp++=0; if(p2!=NULL) *p2++=0;
  463.     snprintf(buf,sizeof(buf),"%s",vbuf);
  464.     prepcnt=0; parmprep(buf,ptype);
  465.     fprintf(outf,"\n!ifval %s\n",buf);
  466.     snprintf(buf,sizeof(buf),"%s",pp);
  467.     parmprep(buf,ptype); putval(buf,i,ptype);
  468.     if(p2!=NULL) {
  469.       fprintf(outf,"!else\n");
  470.       snprintf(buf,sizeof(buf),"%s",p2);
  471.       parmprep(buf,ptype); putval(buf,i,ptype);
  472.     }
  473.     fprintf(outf,"!endif\n");
  474.   }
  475.   else {
  476. noif:
  477.     prepcnt=0; parmprep(vbuf, ptype);
  478.     putval(vbuf,i,ptype);
  479.   }
  480.   if(i>=varcnt && i<MAX_PARAM) {
  481.     param[varcnt].name=p[0];
  482.     param[varcnt].type=ptype;
  483.     param[varcnt].save=0;
  484.     varcnt++;
  485.   }
  486. }
  487.  
  488. void p_int(char *p[MAX_PARM]) {parm(p,pt_int);}
  489. void p_rational(char *p[MAX_PARM]) {parm(p,pt_rat);}
  490. void p_real(char *p[MAX_PARM]) {parm(p,pt_real);}
  491. void p_complex(char *p[MAX_PARM]) {parm(p,pt_complex);}
  492. void p_func(char *p[MAX_PARM]) {parm(p,pt_func);}
  493. void p_text(char *p[MAX_PARM]) {parm(p,pt_text);}
  494. void p_matrix(char *p[MAX_PARM]) {parm(p,pt_matrix);}
  495.  
  496. void p_parm(char *p[MAX_PARM])
  497. {
  498.     parm(p,pt_real);
  499. }
  500.  
  501. void _p_if(char *p[MAX_PARM], int type)
  502. {
  503.   char vbuf[MAX_LINELEN+1];
  504.   snprintf(vbuf,sizeof(vbuf),"%s",p[0]); subst(vbuf);
  505.   if(deftag) repsubst(vbuf);
  506.   prepcnt=0; parmprep(vbuf, pt_real);
  507.   switch(type) {
  508.     case 0: fprintf(outf,"!if %s \n",vbuf); break;
  509.     case 1: fprintf(outf,"!ifval %s \n",vbuf);
  510.   }
  511. }
  512. void p_if(char *p[MAX_PARM]) { return _p_if(p, 0);}
  513. void p_ifval(char *p[MAX_PARM]) { return _p_if(p, 1);}
  514.  
  515. void p_else(char *p[MAX_PARM])
  516. {
  517.   fprintf(outf,"!else\n");
  518. }
  519.  
  520. void p_endif(char *p[MAX_PARM])
  521. {
  522.   fprintf(outf,"!endif\n");
  523. }
  524.  
  525.  
  526. void p_while(char *p[MAX_PARM])
  527. {
  528.   char vbuf[MAX_LINELEN+1];
  529.   snprintf(vbuf,sizeof(vbuf),"%s",p[0]); subst(vbuf);
  530.   if(deftag) repsubst(vbuf);
  531.   prepcnt=0; parmprep(vbuf, pt_real);
  532.   fprintf(outf,"!while %s \n",vbuf);
  533. }
  534.  
  535. void p_endwhile(char *p[MAX_PARM])
  536. {
  537.   fprintf(outf,"!endwhile\n");
  538. }
  539.  
  540. void p_for(char *p[MAX_PARM])
  541. {
  542.   char *p1, *p2, buf[256];
  543.   char vbuf[MAX_LINELEN+1];
  544.   int i;
  545.  
  546.   p1=find_word_start(p[0]);
  547.   if(!isalpha(*p1)) return;
  548.   for(p2=p1; isalnum(*p2); p2++);
  549.   if(p2-p1>64) return;
  550.   memmove(buf,p1,p2-p1); buf[p2-p1]=0;
  551.   for(i=1;i<varcnt && strcmp(buf,param[i].name)!=0;i++);
  552.   if(i>=varcnt && i<MAX_PARAM) {
  553.     param[varcnt].name=p1;
  554.     param[varcnt].type=pt_real;
  555.     param[varcnt].save=0;
  556.     varcnt++;
  557.   }
  558.   snprintf(vbuf,sizeof(vbuf),"%s",p2); subst(vbuf); *p2=0;
  559.   if(deftag) repsubst(vbuf);
  560.   prepcnt=0; parmprep(vbuf, pt_real);
  561.   fprintf(outf,"!for val%d %s \n", i, vbuf);
  562. }
  563.  
  564. void p_next(char *p[MAX_PARM])
  565. {
  566.   fprintf(outf,"!next\n");
  567. }
  568.  
  569. void p_plot(char *p[MAX_PARM])
  570. {
  571.   int i, f, xr, yr;
  572.   char *pp, *p2;
  573.   char buf[MAX_LINELEN+1];
  574.   f=xr=yr=-1;
  575.   for(i=0;i<3;i++) {
  576.     if(*p[i]==0) continue;
  577.     if((pp=strchr(p[i],'='))==NULL) f=i;
  578.     else {
  579.       *pp=0; pp++;
  580.       p2=find_word_start(p[i]);
  581.       if(*p2=='x' || *p2=='X') xr=i;
  582.       else if (*p2=='y' || *p2=='Y') yr=i;
  583.       ovlstrcpy(p[i],pp);
  584.     }
  585.   }
  586. /*    if(xr>=0 && (pp=strstr(p[xr],".."))!=NULL) {
  587.  
  588.     }
  589. */    if(f<0) return;
  590.   ovlstrcpy(buf, p[f]);
  591.   prepcnt=0; parmprep(buf,pt_func);
  592.   fprintf(outf,"plot_fn=!rawmath %s\n",buf);
  593.  
  594. }
  595.  
  596. void p_condition(char *p[MAX_PARM])
  597. {
  598.   int i,j;
  599.   char buf1[MAX_LINELEN+1],buf2[MAX_LINELEN+1];
  600.   for(i=0;i<5;i++) {
  601.     if(p[i]==NULL || p[i][0]==0) continue;
  602.     p[i]=find_word_start(p[i]);
  603.     if(strncasecmp(p[i],"option",strlen("option"))==0) {
  604.       char *tt, *tv;
  605.       tt=p[i]+strlen("option");
  606.       if(*tt=='s' || *tt=='S') tt++;
  607.       tt=find_word_start(tt);
  608.       if(*tt=='=') {
  609.         for(j=i;j<6;j++) p[j]=p[j+1];
  610.         i--;
  611.         snprintf(buf1,sizeof(buf1),"%s",tt+1); subst(buf1);
  612.         for(tv=buf1; *tv; tv++) if(*tv==',' || *tv==';') *tv=' ';
  613.         strip_trailing_spaces(buf1);
  614.         fprintf(outf,"condoption%d=%s \n",conditioncnt,
  615.         find_word_start(buf1));
  616.       }
  617.       continue;
  618.     }
  619.     if(strncasecmp(p[i],"weight",strlen("weight"))==0) {
  620.       char *tt;
  621.       tt=p[i]+strlen("weight");
  622.       tt=find_word_start(tt);
  623.       if(*tt=='=') {
  624.         for(j=i;j<6;j++) p[j]=p[j+1];
  625.         i--;
  626.         snprintf(buf1,sizeof(buf1),"%s",tt+1); subst(buf1);
  627.         strip_trailing_spaces(buf1);
  628.         fprintf(outf,"condweight%d=%s \n",conditioncnt,
  629.               find_word_start(buf1));
  630.       }
  631.       continue;
  632.     }
  633.   }
  634.   if(p[1][0]==0) {p[1]=p[0]; p[0]="";}
  635.   snprintf(buf1,sizeof(buf1),"%s",p[0]); subst(buf1);
  636.   snprintf(buf2,sizeof(buf2),"%s",p[1]); subst(buf2);
  637.   prepcnt=0; parmprep(buf2, pt_real);
  638.   repsubst(buf2);
  639.   fprintf(outf,"\n!ifval %s\n condtest%d=1\n!else\n condtest%d=0\n!endif\n\
  640. condname%d=%s\n", buf2,conditioncnt,conditioncnt,conditioncnt,buf1);
  641.     conditioncnt++;
  642. }
  643.  
  644. void p_conditions(char *p[MAX_PARM])
  645. {
  646.   char buf[MAX_LINELEN+1];
  647.   snprintf(buf,sizeof(buf),"%s",p[0]); subst(buf);
  648.   prepcnt=0; parmprep(buf, pt_real);
  649.   repsubst(buf);
  650.   fprintf(outf,"\ncondlist=%s\n",buf);
  651. }
  652.  
  653. void p_feedback(char *p[MAX_PARM])
  654. {
  655.   char buf1[MAX_LINELEN+1],buf2[MAX_LINELEN+1];
  656.   char *cmpstr="ifval";
  657.  
  658.   snprintf(buf1,sizeof(buf1),"%s",p[0]); subst(buf1);
  659.   snprintf(buf2,sizeof(buf2),"%s",p[1]); subst(buf2);
  660.   repsubst(buf1); repsubst(buf2);
  661.   if(strstr(buf1,"$m_choice")!=NULL) cmpstr="if";
  662.   prepcnt=0; setpre="!set "; parmprep(buf1, pt_real); setpre="";
  663.   fprintf(outf,"!%s %s\n <div class='oef_feedbacks'>",cmpstr, buf1);
  664.   out_exec(buf2,NULL);
  665.   fprintf(outf,"</div>\n!endif\n");
  666. }
  667.  
  668. /* definition of steps */
  669. void p_steps(char *p[MAX_PARM])
  670. {
  671.   char vbuf[MAX_LINELEN+1];
  672.   char *pp, *p2;
  673.  
  674.   snprintf(vbuf,sizeof(vbuf),"%s",find_word_start(p[0])); subst(vbuf);
  675.   strip_trailing_spaces(vbuf);
  676.   if(vbuf[0]==0) return;
  677.   if((pp=strparchr(vbuf,'?'))!=NULL && pp[1]!='?') {
  678.     char buf[MAX_LINELEN+1];
  679.     if(check_compare(vbuf)==0) goto noif;
  680.     p2=strparchr(pp,':'); *pp++=0; if(p2!=NULL) *p2++=0;
  681.     snprintf(buf,sizeof(buf),"%s",vbuf);
  682.     prepcnt=0; parmprep(buf,pt_text);
  683.     fprintf(outf,"\n!ifval %s \n",buf);
  684.     snprintf(buf,sizeof(buf),"%s",pp);
  685.     parmprep(buf,pt_text);
  686.     fprintf(outf,"oefsteps=%s \n",buf);
  687.     if(p2!=NULL) {
  688.       fprintf(outf,"!else\n");
  689.       snprintf(buf,sizeof(buf),"%s",p2);
  690.       parmprep(buf,pt_text);
  691.       fprintf(outf,"oefsteps=%s \n",buf);
  692.     }
  693.     fprintf(outf,"!endif\n");
  694.   }
  695.   else {
  696. noif:
  697.     prepcnt=0; parmprep(vbuf, pt_text);
  698.     fprintf(outf,"oefsteps=%s \nnextstep=!nosubst %s \n",vbuf,vbuf);
  699.   }
  700.   fprintf(outf,"!readproc oef/steps.proc\n");
  701. }
  702.  
  703. /* dynamic steps */
  704. void p_nextstep(char *p[MAX_PARM])
  705. {
  706.   fprintf(outf,"dynsteps=yes\n");
  707.   p_steps(p);
  708. }
  709.