Subversion Repositories wimsdev

Rev

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