File:  [LON-CAPA] / capa / capa51 / pProj / capaGrammarDef.y
Revision 1.16: download - view: text, annotated - select for diffs
Wed Sep 20 17:21:01 2000 UTC (23 years, 7 months ago) by albertel
Branches: MAIN
CVS tags: version_2_9_X, version_2_9_99_0, version_2_9_1, version_2_9_0, version_2_8_X, version_2_8_99_1, version_2_8_99_0, version_2_8_2, version_2_8_1, version_2_8_0, version_2_7_X, version_2_7_99_1, version_2_7_99_0, version_2_7_1, version_2_7_0, version_2_6_X, version_2_6_99_1, version_2_6_99_0, version_2_6_3, version_2_6_2, version_2_6_1, version_2_6_0, version_2_5_X, version_2_5_99_1, version_2_5_99_0, version_2_5_2, version_2_5_1, version_2_5_0, version_2_4_X, version_2_4_99_0, version_2_4_2, version_2_4_1, version_2_4_0, version_2_3_X, version_2_3_99_0, version_2_3_2, version_2_3_1, version_2_3_0, version_2_2_X, version_2_2_99_1, version_2_2_99_0, version_2_2_2, version_2_2_1, version_2_2_0, version_2_1_X, version_2_1_99_3, version_2_1_99_2, version_2_1_99_1, version_2_1_99_0, version_2_1_3, version_2_1_2, version_2_1_1, version_2_1_0, version_2_12_X, version_2_11_X, version_2_11_4_uiuc, version_2_11_4_msu, version_2_11_4, version_2_11_3_uiuc, version_2_11_3_msu, version_2_11_3, version_2_11_2_uiuc, version_2_11_2_msu, version_2_11_2_educog, version_2_11_2, version_2_11_1, version_2_11_0_RC3, version_2_11_0_RC2, version_2_11_0_RC1, version_2_11_0, version_2_10_X, version_2_10_1, version_2_10_0_RC2, version_2_10_0_RC1, version_2_10_0, version_2_0_X, version_2_0_99_1, version_2_0_2, version_2_0_1, version_2_0_0, version_1_99_3, version_1_99_2, version_1_99_1_tmcc, version_1_99_1, version_1_99_0_tmcc, version_1_99_0, version_1_3_X, version_1_3_3, version_1_3_2, version_1_3_1, version_1_3_0, version_1_2_X, version_1_2_99_1, version_1_2_99_0, version_1_2_1, version_1_2_0, version_1_1_X, version_1_1_99_5, version_1_1_99_4, version_1_1_99_3, version_1_1_99_2, version_1_1_99_1, version_1_1_99_0, version_1_1_3, version_1_1_2, version_1_1_1, version_1_1_0, version_1_0_99_3, version_1_0_99_2, version_1_0_99_1, version_1_0_99, version_1_0_3, version_1_0_2, version_1_0_1, version_1_0_0, version_0_99_5, version_0_99_4, version_0_99_3, version_0_99_2, version_0_99_1, version_0_99_0, version_0_6_2, version_0_6, version_0_5_1, version_0_5, version_0_4, stable_2002_spring, stable_2002_july, stable_2002_april, stable_2001_fall, loncapaMITrelate_1, language_hyphenation_merge, language_hyphenation, conference_2003, bz6209-base, bz6209, STABLE, HEAD, GCI_3, GCI_2, GCI_1, CAPA_5-1-6, CAPA_5-1-5, CAPA_5-1-4_RC1, BZ4492-merge, BZ4492-feature_horizontal_radioresponse, BZ4492-feature_Support_horizontal_radioresponse, BZ4492-Support_horizontal_radioresponse
- fixed implementation of random_multivariate_normal()

    1: /* main CAPA parser
    2:    Copyright (C) 1992-2000 Michigan State University
    3: 
    4:    The CAPA system is free software; you can redistribute it and/or
    5:    modify it under the terms of the GNU General Public License as
    6:    published by the Free Software Foundation; either version 2 of the
    7:    License, or (at your option) any later version.
    8: 
    9:    The CAPA system is distributed in the hope that it will be useful,
   10:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   11:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   12:    General Public License for more details.
   13: 
   14:    You should have received a copy of the GNU General Public
   15:    License along with the CAPA system; see the file COPYING.  If not,
   16:    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   17:    Boston, MA 02111-1307, USA.
   18: 
   19:    As a special exception, you have permission to link this program
   20:    with the TtH/TtM library and distribute executables, as long as you
   21:    follow the requirements of the GNU GPL in regard to all of the
   22:    software in the executable aside from TtH/TtM.
   23: */
   24: 
   25: /* ========================================================================== */
   26: /*            capaGrammarDef.y    created by Isaac Tsai                       */
   27: /*                                1998, 1999 by Isaac Tsai        */
   28: /* no longer there is a length constrain on string concatenation July 13 1998 */
   29: /* /RMAP() function */
   30: /* TODO: new mechanism to collect answer informations */
   31: /*****************************************************************************/
   32: /*****************************************************************************/
   33: /*****************************************************************************/
   34: %{
   35: #include <stdio.h>
   36: #include <ctype.h>
   37: #include <string.h>
   38: #include <math.h>
   39: #include "capaParser.h"   /* _symbol structure def */
   40: #include "capaCommon.h"
   41: #include "capaFunction.h"
   42: #include "capaRQO.h"
   43: #ifdef __hpux
   44: #include <stdlib.h>
   45: #include <alloca.h>
   46: #endif
   47: 
   48: #ifdef   YACC_DBUG
   49: #define  YYDBUG_PR1(xx)        { printf(xx);    fflush(stdout); }
   50: #define  YYDBUG_PR2(xx,yy)     { printf(xx,yy); fflush(stdout); }
   51: #define  YYDBUG_PR3(xx,yy,zz)  { printf(xx,yy,zz); fflush(stdout); }
   52: #define  YYDBUG_PR4(xx,yy,zz,aa)  { printf(xx,yy,zz,aa); fflush(stdout); }
   53: #define  YYDBUG_SYM(xx)        { switch((xx)->s_type) { \
   54:                                      case IDENTIFIER: \
   55:                                               printf("ID(%s)\n",(xx)->s_name);  break; \
   56:                                      case I_VAR:  case I_CONSTANT: \
   57:                                               printf("INT(%d)\n",(xx)->s_int);  break; \
   58:                                      case R_VAR:  case R_CONSTANT: \
   59:                                               printf("REAL(%.16g)\n",(xx)->s_real); break; \
   60:                                      case S_VAR:  case S_CONSTANT: \
   61:                                               printf("STR(%s)\n",(xx)->s_str); break; \
   62:                                } }
   63: #else  /* YACC_DBUG */
   64: #define  YYDBUG_PR1(xx)        { }
   65: #define  YYDBUG_PR2(xx,yy)     { }
   66: #define  YYDBUG_PR3(xx,yy,zz)  { }
   67: #define  YYDBUG_PR4(xx,yy,zz,aa)  { }
   68: #define  YYDBUG_SYM(xx)        { }
   69: #endif /* YACC_DBUG */
   70: 
   71: int   yylex();
   72: void  yyerror(char*);
   73: void  free_calc_expr(Symbol*);
   74: void assign_pts (Symbol *, Symbol *, Symbol *);
   75: /******************************************************************************/
   76: /* GLOBAL VARIABLES                                                           */
   77: /******************************************************************************/
   78: int                Lexi_qnum;
   79: 
   80: extern int         Lexi_line;
   81: extern int         Lexi_pos[MAX_OPENED_FILE];
   82: extern char        Opened_filename[MAX_OPENED_FILE][QUARTER_K];
   83: extern int         Input_idx;
   84: int                Current_line[MAX_OPENED_FILE];
   85: extern int         Func_idx;
   86: extern Symbol      FuncStack[MAX_FUNC_NEST];
   87: extern int         IFstatus[MAX_FUNC_NEST];
   88: extern int         IFcount;
   89: extern int         gUnitError;
   90: 
   91: int                Parsemode_f;    /* Parser mode flag */
   92: 
   93: Problem_t         *FirstProblem_p; /* First problem                    */
   94: Problem_t         *LastProblem_p;  /* Last problem                     */
   95: Problem_t         *LexiProblem_p;  /* Current problem                  */
   96: char              *EndText_p;
   97: char              *StartText_p;
   98: char              *ErrorMsg_p;
   99: int                ErrorMsg_count;
  100: WarnMsg_t         *WarnMsg_p;
  101: int                WarnMsg_count;
  102: int                Answer_infospec;
  103: void              (*Status_Func)();
  104: AnswerInfo_t       CurrAnsInfo;
  105: 
  106: RandQO_t          *QuestionOrder;
  107: PointsList_t      *CurrPtsList;
  108: PointsList_t      *LastPtsList;
  109: 
  110: 
  111: 
  112: 
  113: #ifdef  YYSTYPE
  114: #undef  YYSTYPE
  115: #endif
  116: #define YYSTYPE  Symbol_p
  117: 
  118: 
  119: #define ADD_op          1
  120: #define SUB_op          2
  121: #define MUL_op          3
  122: #define DIV_op          4
  123: #define IDIV_op         5
  124: #define NOT_DEFINED_op  9
  125: 
  126: /*#define  yyerror  printf*/
  127: 
  128: %}
  129: %token       NEW_ID
  130: %token       I_CONSTANT  R_CONSTANT     S_CONSTANT
  131: %token       I_VAR       R_VAR          S_VAR
  132: 
  133: %token       IDENTIFIER  FUNCTION_ID    ARRAY_ID
  134: %token       HINT_LINE   EXPLAIN_LINE   TEXT_LINE    IMPORT_LINE
  135: %token       CAPA_LET  CAPA_DEF  CAPA_DIS   CAPA_END   CAPA_VAR
  136: %token       CAPA_ESC  CAPA_MAP  CAPA_FIG   CAPA_ANS   CAPA_RMAP
  137: %token       CAPA_IF   CAPA_ELSE CAPA_ENDIF CAPA_SUBJ  CAPA_WHILE
  138: %token       CAPA_RQO  CAPA_ENDWHILE        CAPA_START 
  139: %token       ANS_AND         ANS_BOX_SHOW    ANS_CALC        ANS_CI          ANS_COMPARE       ANS_CS
  140: %token       ANS_EVAL        ANS_EXPLAIN     ANS_EXTERNAL    ANS_FMT
  141: %token       ANS_FORMULA     ANS_HINT        ANS_MC          ANS_MINUS
  142: %token       ANS_OFF         ANS_ON          ANS_OR          ANS_ORDERED
  143: %token       ANS_PATH        ANS_PCREDIT     ANS_PLUS        ANS_RANGE       
  144: %token       ANS_SHOW_BR     ANS_SIG         ANS_TOLERANCE   ANS_TRY         ANS_TYPE
  145: %token       ANS_UNFMT       ANS_UNIT        ANS_VERBATIM    ANS_WEIGHT 
  146: %token       VAR_RANGE       VERBATIM
  147: %token       SLASH           FORMAT
  148: %token       EQ_op  NE_op  GT_op  GE_op  LT_op  LE_op  AND_op  OR_op   EoL    
  149: 
  150: %start       prob_set
  151: 
  152: %%
  153: 
  154: prob_set     :  startQ  questions  CAPA_END  { YYDBUG_PR1(" prob_set := startQ questions END\n\n"); }
  155:              ;
  156: 
  157: questions    :  a_line                  { YYDBUG_PR1(" questions <= a_line");
  158:                                           if (Status_Func != NULL) Status_Func();
  159:                                         }
  160:              |  questions  a_line       { YYDBUG_PR1(" questions <= questions a_line");
  161:                                           if (Status_Func != NULL) Status_Func();
  162:                                         }
  163:              ;
  164:              
  165: startL       :  CAPA_LET                { YYDBUG_PR1("\n begin_let::"); } 
  166:              ;
  167:              
  168: startV       :  CAPA_VAR                { YYDBUG_PR1(" begin_var"); } 
  169:              ;
  170:              
  171: startA       :  CAPA_ANS                { YYDBUG_PR1("\n START ANSWER(/ANS)::\n"); 
  172:                                           init_answerinfo(); 
  173:                                         }
  174:              ;
  175: 
  176: startSA      :  CAPA_SUBJ               { YYDBUG_PR1("\n START SUBJECT ANSWER(/SUBJECTIVE)::\n");
  177:                                           init_answerinfo();
  178:                                         }
  179:              ;
  180:              
  181: startM       :  CAPA_MAP                { YYDBUG_PR1("\n begin_map::"); } 
  182:              ;
  183: 
  184: startR       :  CAPA_RMAP               { YYDBUG_PR1("\n begin_rmap::"); } 
  185:              ;
  186: 
  187: startRQO     :  CAPA_RQO                { YYDBUG_PR1("\n begin_rqo::"); } 
  188:              ;
  189: 
  190: ans_and_op   :  ANS_AND                 { add_answer_cnt(ANS_AND); YYDBUG_PR1("(AND ,new an answer info)"); }
  191:              ;
  192:              
  193: ans_or_op    :  ANS_OR                  { add_answer_cnt(ANS_OR); YYDBUG_PR1("(OR ,new an answer info)");  }
  194:              ;
  195: 
  196: a_line       :  startL  statement EoL   { YYDBUG_PR1(" a_line <= startL statement CR\n");  }
  197:              | CAPA_END                 { YYDBUG_PR1(" a_line <=  END\n\n"); }
  198:              |  startRQO rqo_def EoL     { YYDBUG_PR1(" aline <= CAPA_RQO\n");
  199:                                           rqo_finish();
  200:                                         }
  201:              |  CAPA_START              { YYDBUG_PR1(" aline <= CAPA_START\n");
  202: 					  start_question_over();
  203: 	                                }
  204:              |  HINT_LINE               { append_hint($1->s_str); 
  205:                                           YYDBUG_PR2(" a_line <= Hint_line(%s)\n",$1->s_str);
  206:                                           capa_mfree($1->s_str); capa_mfree((char *)$1);
  207:                                         }
  208:              |  EXPLAIN_LINE            { append_explain($1->s_str); 
  209:                                           YYDBUG_PR2(" a_line <= Explain_line(%s)\n",$1->s_str);
  210:                                           capa_mfree($1->s_str); capa_mfree((char*)$1);
  211:                                         }
  212:              |  IMPORT_LINE  EoL        { YYDBUG_PR1(" a_line <= import_line CR\n");  }
  213:              |  q_text EoL              { YYDBUG_PR1(" a_line <= Qtext CR\n"); append_text("\n");  }
  214:              |  answer_expr             { YYDBUG_PR1(" a_line <= answer_expr (init a new prob) CR\n"); 
  215:                                           init_new_prob(); }
  216:              |  if_expr                 { YYDBUG_PR1(" a_line <= if_expr\n");  }
  217:              |  while_expr              { YYDBUG_PR1(" a_line <= while_expr\n");  }
  218:              |  map_expr   EoL          { YYDBUG_PR1(" a_line <= map_expr CR\n");  }
  219:              |  EoL                     { YYDBUG_PR1(" a_line <= (CR)\n");  }
  220:              |  VERBATIM                { YYDBUG_PR1(" a_line <= (VERBATIM)\n");
  221: 	                                  switch(Parsemode_f) {
  222: 					  case TeX_MODE: append_text("\\begin{verbatim}");
  223: 					    break;
  224: 					  case HTML_MODE: append_text("<PRE>");
  225: 					    break;
  226: 					  }
  227:                                           append_text($1->s_str);
  228:                                           capa_mfree($1->s_str); capa_mfree((char *)$1);
  229: 	                                  switch(Parsemode_f) {
  230: 					  case TeX_MODE: append_text("\\end{verbatim}\n");
  231: 					    break;
  232: 					  case HTML_MODE: append_text("</PRE>\n");
  233: 					    break;
  234: 					  }
  235:                                         }
  236:              |  error EoL               { char  warn_msg[WARN_MSG_LENGTH]; 
  237:                                           YYDBUG_PR1(" a_line := ERROR(CR)\n");
  238:                                           sprintf(warn_msg," Question %d: Syntax error.\n", Lexi_qnum+1);
  239:                                           capa_msg(MESSAGE_ERROR,warn_msg); 
  240:                                           begin_text();
  241:                                         }
  242:              
  243:              ;
  244:              
  245: statement    :  IDENTIFIER '=' calc_expr 
  246:                                         { char  warn_msg[WARN_MSG_LENGTH];
  247:                                           
  248: 					if ( $1 != $3 ) { /* /LET a = a */
  249:                                           switch($1->s_type) {
  250:                                              case IDENTIFIER:
  251:                                              case I_VAR: case I_CONSTANT:
  252:                                              case R_VAR: case R_CONSTANT: break;
  253:                                              case S_VAR: case S_CONSTANT: /* free up original used spaces */
  254:                                                     capa_mfree($1->s_str); $1->s_str = NULL; break;
  255:                                              default:    break;
  256:                                           }
  257:                                           switch($3->s_type) {
  258:                                             case IDENTIFIER:
  259:                                                  sprintf(warn_msg,"var \"%s\" not defined before use.\n",$3->s_name);
  260:                                                  capa_msg(MESSAGE_ERROR,warn_msg);
  261:                                                  break;
  262:                                             case I_VAR:  case I_CONSTANT: 
  263:                                                  $1->s_type = I_VAR;
  264:                                                  $1->s_int = $3->s_int; 
  265:                                                  break;
  266:                                             case R_VAR:  case R_CONSTANT:
  267:                                                  $1->s_type = R_VAR;
  268:                                                  $1->s_real = $3->s_real; 
  269:                                                  break;
  270:                                             case S_VAR:  case S_CONSTANT:
  271:                                                  $1->s_type = S_VAR;
  272:                                                  $1->s_str = strsave($3->s_str);
  273:                                                  break;
  274:                                           }
  275:                                           YYDBUG_PR1(" statement <=    ID = calc_expr:: "); YYDBUG_SYM($3);
  276: 					  free_calc_expr($3);
  277: 					}
  278:                                         }
  279:              |  ARRAY_ID '[' calc_expr ']' '=' calc_expr
  280:                                         {    Symbol  *s_p;
  281:                                              char     warn_msg[WARN_MSG_LENGTH];
  282: 
  283: 					     s_p = get_array_symbol($1,$3,1);
  284:                                              switch(s_p->s_type) {
  285:                                                case IDENTIFIER:
  286:                                                case I_VAR: case I_CONSTANT:
  287:                                                case R_VAR: case R_CONSTANT: break;
  288:                                                case S_VAR: case S_CONSTANT: 
  289:                                                     capa_mfree(s_p->s_str); s_p->s_str = NULL; break;
  290:                                                default:    break;
  291:                                              }
  292:                                              switch($6->s_type) {
  293:                                                case IDENTIFIER:
  294:                                                  sprintf(warn_msg,"var \"%s\" not defined before use.\n",$6->s_name);
  295:                                                  capa_msg(MESSAGE_ERROR,warn_msg);
  296:                                                  break;
  297:                                                case I_VAR:  case I_CONSTANT: 
  298:                                                  s_p->s_type = I_VAR;
  299:                                                  s_p->s_int = $6->s_int;
  300:                                                  break;
  301:                                                case R_VAR:  case R_CONSTANT:
  302:                                                  s_p->s_type = R_VAR;
  303:                                                  s_p->s_real = $6->s_real; 
  304:                                                  break;
  305:                                                case S_VAR:  case S_CONSTANT:
  306:                                                  s_p->s_type = S_VAR;
  307:                                                  s_p->s_str = strsave($6->s_str);
  308:                                                  break;
  309:                                              }
  310:                                              free_calc_expr($6);
  311:                                         }
  312:              ;
  313: 
  314: rqo_def      :  rqo_speca             { rqo_1spec(); }
  315:              |  rqo_speca ',' rqo_def { rqo_2spec(); }
  316:              ;
  317: 
  318: rqo_speca    : an_integer                 {start_rqo_type(SINGLE);append_rqo($1);}
  319:              | an_integer '!'             {start_rqo_type(IMMOBILE);append_rqo($1);}
  320:              | an_integer '-' an_integer  {start_rqo_type(RANGE);append_rqo($1);
  321:                                            append_rqo($3);
  322:                                           }
  323:              | an_integer '~' rqo_specb   {prefix_rqo($1);}
  324:              | an_integer '+' rqo_specc   {prefix_rqo($1);}
  325:              ;
  326: 
  327: rqo_specb    : an_integer                 {start_rqo_type(ALL_MIX);append_rqo($1);}
  328:              | an_integer '~' rqo_specb   {prefix_rqo($1);}
  329:              | an_integer '+' an_integer  {start_rqo_type(LAST_FIXED);append_rqo($1);
  330:                                            append_rqo($3);}
  331:              ;
  332: 
  333: rqo_specc    : an_integer                 {start_rqo_type(ALL_FIXED);append_rqo($1);}
  334:              | an_integer '+' rqo_specd   {prefix_rqo($1);}
  335:              | an_integer '~' rqo_spece   {prefix_rqo($1);}
  336:              ;
  337: 
  338: rqo_specd    : an_integer                 {start_rqo_type(ALL_FIXED);append_rqo($1);}
  339:              | an_integer '+' rqo_specd   {prefix_rqo($1);}
  340:              ;
  341: 
  342: rqo_spece    : an_integer                 {start_rqo_type(FIRST_FIXED);append_rqo($1);}
  343:              | an_integer '~' rqo_spece   {prefix_rqo($1);}
  344:              | an_integer '+' an_integer  {start_rqo_type(BOTH_FIXED);append_rqo($1);
  345:                                            append_rqo($3);}
  346:              ;
  347: 
  348: 
  349: q_text       :  TEXT_LINE               { append_text($1->s_str);
  350:                                           capa_mfree($1->s_str); capa_mfree((char *)$1);
  351:                                         }
  352:              |  var_expr                {   }
  353:              |  q_text var_expr         {   }
  354:              |  q_text TEXT_LINE        { append_text($2->s_str); 
  355:                                           capa_mfree($2->s_str); capa_mfree((char *)$2);
  356:                                         }
  357:              ;
  358:              
  359: if_expr      :  CAPA_IF '(' calc_expr  ')'
  360:                                         { int leng=0; /* begin_next_line(); no use, can be get rid of */
  361:                                           YYDBUG_PR2("(IF expr <IFcount=%d>)\n",IFcount);
  362:                                           switch($3->s_type) {
  363:                                             case IDENTIFIER: 
  364:                                                    IFstatus[IFcount] = IF_FALSE;
  365:                                                    begin_next_line();
  366:                                                    break;
  367:                                             case I_CONSTANT: case I_VAR: 
  368:                                                    if(!$3->s_int) {
  369:                                                       IFstatus[IFcount] = IF_FALSE;
  370:                                                       begin_if_skip();
  371:                                                    } else {
  372:                                                       IFstatus[IFcount] = IF_TRUE;
  373:                                                       begin_next_line();
  374:                                                    } 
  375:                                                    break;
  376:                                             case R_CONSTANT: case R_VAR:
  377:                                                    if($3->s_real == 0.0) {
  378:                                                       IFstatus[IFcount] = IF_FALSE;
  379:                                                       begin_if_skip();
  380:                                                    }else{
  381:                                                       IFstatus[IFcount] = IF_TRUE;
  382:                                                       begin_next_line();
  383:                                                    }
  384:                                                    break;
  385:                                             case S_CONSTANT: 
  386: 					           if ( $3->s_str) {
  387: 						      leng = strlen($3->s_str);
  388:                                                       capa_mfree($3->s_str);
  389:                                                    } 
  390:                                                    if(leng == 0) {
  391:                                                       IFstatus[IFcount] = IF_FALSE;
  392:                                                       begin_if_skip();
  393:                                                    }else{
  394:                                                       IFstatus[IFcount] = IF_TRUE;
  395:                                                       begin_next_line();
  396:                                                    }
  397:                                                    break;
  398:                                             case S_VAR:
  399: 					           if ( $3->s_str) {
  400: 						      leng = strlen($3->s_str);
  401:                                                       capa_mfree($3->s_str);
  402:                                                    }
  403: 						   if(leng == 0) {
  404:                                                       IFstatus[IFcount] = IF_FALSE;
  405:                                                       begin_if_skip();
  406:                                                    }else{
  407:                                                       IFstatus[IFcount] = IF_TRUE;
  408:                                                       begin_next_line();
  409:                                                    }
  410:                                                    break;
  411:                                           }
  412: 					  capa_mfree((char*)$3);
  413:                                         }
  414:              ;
  415: 
  416: while_expr   :  CAPA_WHILE '(' calc_expr  ')'
  417:                                         {
  418:                                           int leng; 
  419:                                           YYDBUG_PR1("(WHILE expr)\n");
  420:                                           switch($3->s_type) {
  421:                                             case IDENTIFIER: /* undefined identifier regarded as false */
  422:                                                    begin_while_skip();
  423:                                                    break;
  424:                                             case I_CONSTANT: case I_VAR: 
  425:                                                    if(!$3->s_int) {
  426:                                                       begin_while_skip();
  427:                                                    } else {
  428:                                                       begin_next_line(); /* skip to EoL and begin S_TEXT */
  429:                                                    } 
  430:                                                    break;
  431:                                             case R_CONSTANT: case R_VAR:
  432:                                                    if($3->s_real == 0.0) {
  433:                                                       begin_while_skip();
  434:                                                    }else{
  435:                                                       begin_next_line(); /* skip to EoL and begin S_TEXT */
  436:                                                    }
  437:                                                    break;
  438:                                             case S_CONSTANT: 
  439:                                                    leng = strlen($3->s_str);
  440:                                                    capa_mfree($3->s_str);
  441:                                                    if(leng == 0) {
  442:                                                       begin_while_skip();
  443:                                                    }else{
  444:                                                       begin_next_line(); /* skip to EoL and begin S_TEXT */
  445:                                                    }
  446:                                                    break;
  447:                                             case S_VAR:
  448:                                                    leng = strlen($3->s_str);
  449:                                                    if(leng == 0) {
  450:                                                       begin_while_skip();
  451:                                                    }else{
  452:                                                       begin_next_line(); /* skip to EoL and begin S_TEXT */
  453:                                                    }
  454:                                                    break;
  455:                                           }
  456: 					  capa_mfree((char*)$3);
  457:                                         }
  458:              ;
  459: 
  460: var_expr     :  startV '(' formated_ans  ')'
  461:                                         { display_var( $3 ) ; }
  462:              ;
  463:              
  464: answer_expr  : answer_spec              { finish_answer_info(); 
  465:                                         }
  466:              | answer_expr ans_and_op  answer_spec
  467:                                         { finish_answer_info(); 
  468:                                           YYDBUG_PR1(" answer_expr <-- AND answers (copy answerinfo)\n"); }
  469:              | answer_expr ans_or_op   answer_spec
  470:                                         { finish_answer_info(); 
  471:                                           YYDBUG_PR1(" answer_expr <-- OR answers (copy answerinfo)\n"); 
  472: }             | startSA  '(' answer_info ')'
  473:                                         { YYDBUG_PR1("\n subjective answer\n");
  474: 					  finish_answer_info();
  475:                                           LexiProblem_p->ans_type = ANSWER_IS_SUBJECTIVE;
  476:                                         }
  477:              | startSA  '(' ')'
  478:                                         { YYDBUG_PR1("\n subjective answer\n");
  479: 					  finish_answer_info();
  480:                                           LexiProblem_p->ans_type = ANSWER_IS_SUBJECTIVE;
  481:                                         }
  482:              
  483:              ;
  484:              
  485: answer_spec  : startA '(' formated_ans  ')'
  486:                                         { assign_answer( $3 );
  487:                                           YYDBUG_PR1("\nASSIGN Answer\n");
  488:                                         }
  489:              | startA '(' formated_ans ',' answer_info ')'
  490:                                         { assign_answer( $3 );
  491:                                           YYDBUG_PR1("\nASSIGN Answers + Answer Info\n");
  492:                                         }
  493:              ;
  494: 	     
  495: answer_info  : ans_infospec
  496: 	     | answer_info ',' ans_infospec
  497: 	     ;
  498: 
  499: 
  500: ans_infospec : ANS_TOLERANCE '=' a_number
  501:                                        { YYDBUG_PR1(" ans_infospec:= TOL=a_number");
  502:                                          assign_tolerance(TOL_ABSOLUTE,$3);
  503:                                        }
  504:              | ANS_TOLERANCE '=' IDENTIFIER
  505:                                        { assign_tolerance(TOL_ABSOLUTE,$3);
  506:                                        }
  507:              | ANS_TOLERANCE '=' IDENTIFIER '%'
  508:                                        { assign_tolerance(TOL_PERCENTAGE,$3);
  509:                                        }
  510:              | ANS_TOLERANCE '=' a_number '%'
  511:                                        { assign_tolerance(TOL_PERCENTAGE,$3);
  512:                                        }
  513: 	     | ANS_COMPARE '=' answer_comp {       }
  514: 	     | ANS_SIG '='  answer_sig     {       }
  515: 	     | ANS_WEIGHT '=' an_integer
  516: 	                               {  assign_weight( $3 );
  517: 	                               }
  518: 	     | ANS_WEIGHT '=' IDENTIFIER
  519: 	                               {  assign_weight( $3 );
  520: 	                               }
  521: 	     | ANS_HINT '=' an_integer {  assign_hint( $3 );
  522: 	                               }
  523: 	     | ANS_HINT '=' IDENTIFIER {  assign_hint( $3 );
  524: 	                               }
  525: 	     | ANS_PCREDIT '=' ANS_ON  {  LexiProblem_p->partial_cdt = 1;
  526: 	                               }
  527: 	     | ANS_PCREDIT '=' ANS_OFF {  LexiProblem_p->partial_cdt = 0;
  528: 	                               }
  529: 	     | ANS_SHOW_BR '=' ANS_ON  {  LexiProblem_p->show_br = DO_SHOW;
  530: 	                               }
  531: 	     | ANS_SHOW_BR '=' ANS_OFF {  LexiProblem_p->show_br = DONOT_SHOW;
  532: 	                               }
  533: 	     | ANS_VERBATIM '=' ANS_ON  {  LexiProblem_p->verbatim = DO_VERBATIM;
  534: 	                                }
  535: 	     | ANS_VERBATIM '=' ANS_OFF {  LexiProblem_p->verbatim = DONOT_VERBATIM;
  536: 	                                }
  537: 	     | ANS_BOX_SHOW '=' ANS_ON {  LexiProblem_p->show_ans_box  = DO_SHOW;
  538: 	                               }
  539: 	     | ANS_BOX_SHOW '=' ANS_OFF {  LexiProblem_p->show_ans_box = DONOT_SHOW;
  540: 	                               }                          
  541: 	     | ANS_CALC '=' ANS_FMT    {  CurrAnsInfo.ans_calc = CALC_FORMATED;
  542: 	                               }
  543: 	     | ANS_CALC '=' ANS_UNFMT  {  CurrAnsInfo.ans_calc = CALC_UNFORMATED;
  544: 	                               } 
  545: 	     | ANS_TRY '=' an_integer  {  assign_try_limits( $3 );
  546: 	                               }
  547: 	     | ANS_TRY '=' IDENTIFIER  {  assign_try_limits( $3 );
  548: 	                               }
  549: 	     | ANS_UNIT '=' S_CONSTANT {  assign_units( $3 ); capa_mfree($3->s_str); capa_mfree((char *)$3);
  550: 	                               }
  551: 	     | ANS_UNIT '=' IDENTIFIER {  assign_units( $3 );
  552: 	                               }
  553: 	     | ANS_EVAL '=' var_range {  CurrAnsInfo.ans_pts_list = CurrPtsList; 
  554: 	                                 CurrPtsList=NULL; LastPtsList = NULL;  
  555: 	                               }
  556: 	     ;
  557: 
  558: 
  559: var_range    :  '<' S_CONSTANT '@'  pt_list  '>'     { assign_id_list( $2 ); 
  560:                                                        capa_mfree($2->s_str); 
  561:                                                        capa_mfree((char *)$2);
  562:                                                      }
  563:              |  '<' IDENTIFIER '@'  pt_list  '>'     { assign_id_list( $2 );  }
  564:              ;
  565: 
  566: pt_list      :   pt_list  ','  point_coord          { int idx;
  567:                                                       idx = LastPtsList->pts_idx; idx++;
  568:                                                       LastPtsList->pts_next = new_ptslist( $3 );
  569:                                                       LastPtsList = LastPtsList->pts_next;
  570:                                                       LastPtsList->pts_idx = idx;
  571:                                                       CurrPtsList->pts_idx = idx;
  572:                                                       if( $3->s_type == S_CONSTANT ) {
  573:                                                         capa_mfree($3->s_str); capa_mfree((char *)$3);
  574:                                                       }
  575:                                                     }
  576:              |   pt_list  ','  pt_range             { }
  577:              |   point_coord                        { CurrPtsList = new_ptslist( $1 );  
  578:                                                       LastPtsList = CurrPtsList;
  579:                                                       if( $1->s_type == S_CONSTANT ) {
  580:                                                         capa_mfree($1->s_str); capa_mfree((char *)$1);
  581:                                                       }
  582:                                                     }
  583:              |   pt_range                           { }
  584:              ;
  585: 
  586: pt_range     :   point_coord   ':'  point_coord  '#'  IDENTIFIER   
  587:                               { 
  588: 				assign_pts($1,$3,$5);
  589: 				/*PointsList_t *pt;
  590: 			        if( LastPtsList != NULL ) {
  591: 				  LastPtsList->pts_next = gen_ptslist( $1, $3, $5 );
  592: 				  pt = LastPtsList->pts_next;
  593: 				  while( pt->pts_next != NULL ) {
  594: 				    pt = pt->pts_next;
  595: 				  }
  596: 				  LastPtsList = pt;
  597: 				} else {
  598: 				  CurrPtsList = gen_ptslist( $1, $3, $5 );
  599: 				  LastPtsList = CurrPtsList;
  600: 				}
  601: 				if( $1->s_type == S_CONSTANT ) {
  602: 				  capa_mfree($1->s_str); capa_mfree((char *)$1);
  603: 				}
  604: 				if( $3->s_type == S_CONSTANT ) {
  605: 				  capa_mfree($3->s_str); capa_mfree((char *)$3);
  606: 				}
  607: 				*/
  608: 			      }
  609:              |   point_coord   ':'  point_coord  '#'  ARRAY_ID '[' calc_expr ']'
  610:                               { assign_pts($1,$3,get_array_symbol($5,$7,1)); }
  611:              |   point_coord   ':'  point_coord  '#'  a_number     
  612:                               { 
  613: 				assign_pts($1,$3,$5);
  614: 				/*PointsList_t *pt;
  615: 			      
  616: 				 if( LastPtsList != NULL ) {
  617: 				   LastPtsList->pts_next = gen_ptslist( $1, $3, $5 );
  618: 				   pt = LastPtsList->pts_next;
  619: 				   while( pt->pts_next != NULL ) {
  620: 				     pt = pt->pts_next;
  621: 				   }
  622: 				   LastPtsList = pt;
  623: 				 } else {
  624: 				   CurrPtsList = gen_ptslist( $1, $3, $5 );
  625: 				   LastPtsList = CurrPtsList;
  626: 				 }
  627: 				 if( $1->s_type == S_CONSTANT ) {
  628: 				   capa_mfree($1->s_str); capa_mfree((char *)$1);
  629: 				 }
  630: 				 if( $3->s_type == S_CONSTANT ) {
  631: 				   capa_mfree($3->s_str); capa_mfree((char *)$3);
  632: 				 }
  633: 				 if( $5->s_type == I_CONSTANT || $5->s_type == R_CONSTANT) {
  634: 				   capa_mfree((char *)$5);
  635: 				 }
  636: 				*/
  637: 			      }
  638:              ;
  639: 
  640: 
  641: point_coord  :   IDENTIFIER                 { $$ = $1;  }
  642:              |   ARRAY_ID '[' calc_expr ']' { $$ = get_array_symbol($1,$3,1); }
  643:              |   S_CONSTANT                 { $$ = $1;  }
  644:              ;
  645: 
  646: 
  647: 	     
  648: formated_ans : calc_expr               { $1->s_distype = DEFAULT_FORMAT;
  649:                                          $$ = $1;
  650:                                          $1->s_format = NULL;
  651:                                          YYDBUG_PR2(" formated_ans := calc_expr (type %d)",$1->s_type);
  652:                                        }
  653:              | calc_expr FORMAT        { $1->s_distype = $2->s_distype;
  654:                                          $1->s_format  = strsave($2->s_str); /* **** */
  655:                                          capa_mfree($2->s_str); capa_mfree((char *)$2);
  656:                                          $$ = $1;
  657:                                          YYDBUG_PR1(" formated_ans <= calc_expr FORMAT");
  658:                                        }
  659:              ;
  660:              
  661:              
  662: 
  663: answer_sig   : an_integer              { assign_sigs( $1->s_int,$1->s_int);
  664:                                          capa_mfree((char *)$1);
  665: 	                               }
  666:              | an_integer ANS_PLUS  an_integer
  667:                                        { assign_sigs($1->s_int,$1->s_int + $3->s_int);
  668:                                          capa_mfree((char *)$1);  capa_mfree((char *)$3);
  669: 	                               }
  670:              | an_integer ANS_MINUS an_integer
  671:                                        { assign_sigs($1->s_int - $3->s_int,$1->s_int);
  672:                                          capa_mfree((char *)$1);  capa_mfree((char *)$3);
  673: 	                               }
  674:              | an_integer ANS_PLUS  an_integer ANS_MINUS an_integer
  675:                                        { assign_sigs($1->s_int - $5->s_int,$1->s_int + $3->s_int);
  676:                                          capa_mfree((char *)$1);  capa_mfree((char *)$3); capa_mfree((char *)$5);
  677: 	                               }
  678: 	     | an_integer ANS_MINUS  an_integer ANS_PLUS an_integer
  679:                                        { assign_sigs($1->s_int - $3->s_int,$1->s_int + $5->s_int);
  680:                                          capa_mfree((char *)$1);  capa_mfree((char *)$3); capa_mfree((char *)$5);
  681: 	                               }
  682:              ;
  683:              
  684: answer_comp  : ANS_CS                  {  CurrAnsInfo.ans_type = ANSWER_IS_STRING_CS; }
  685:              | ANS_CI                  {  CurrAnsInfo.ans_type = ANSWER_IS_STRING_CI; }
  686:              | ANS_MC                  {  CurrAnsInfo.ans_type = ANSWER_IS_CHOICE;    }
  687:              | ANS_FORMULA             {  CurrAnsInfo.ans_type = ANSWER_IS_FORMULA;   }
  688:              | ANS_EXTERNAL            {  CurrAnsInfo.ans_type = ANSWER_IS_EXTERNAL;  }
  689:              ;
  690: 
  691: 
  692: map_expr     : startM '(' basic_constr ';' var_list ';' arg_list ')'
  693:                                       { char   key[SMALL_LINE_BUFFER];
  694:                                         char   warn_msg[WARN_MSG_LENGTH];
  695:                                         int    result=0;
  696: 
  697:                                         YYDBUG_PR1(" map_expr body executed\n");
  698:                                         sprintf(key,"%ld",$3->s_int);
  699:                                         if( $5->s_argc ==  $7->s_argc ) {
  700:                                           result=do_map(key, $5->s_argp, $7->s_argp, $5->s_argc, FORWARD_MAP);
  701: 					} else {
  702: 					  if ($5->s_argc==1) {
  703: 					    Symbol *a_sp;
  704: 					    a_sp=build_array_list($5,$7->s_argc);
  705: 					    result=do_map(key, a_sp->s_argp, $7->s_argp, a_sp->s_argc, FORWARD_MAP);
  706: 					    free_arglist(a_sp->s_argp);
  707: 					    a_sp->s_argp=NULL;
  708: 					  } else {
  709: 					    sprintf(warn_msg,"/MAP arg. counts are not matched.\n");
  710: 					    capa_msg(MESSAGE_ERROR,warn_msg);
  711: 					  }
  712:                                         }
  713: 					if (result!=0) {
  714: 					    sprintf(warn_msg,
  715: 						    "/MAP had invalid arguments.\n");
  716: 					    capa_msg(MESSAGE_ERROR,warn_msg);
  717: 					}
  718:                                         free_arglist($5->s_argp);
  719: 					$5->s_argp=NULL;
  720: 					free_arglist($7->s_argp);
  721: 					$7->s_argp=NULL;
  722:                                       }
  723:              | startR '(' basic_constr ';' var_list ';' arg_list ')'
  724:                                       { char   key[SMALL_LINE_BUFFER];
  725:                                         char   warn_msg[WARN_MSG_LENGTH];
  726: 					int    result=0;
  727: 
  728:                                         YYDBUG_PR1(" rmap_expr body executed\n");
  729:                                         sprintf(key,"%ld",$3->s_int);
  730:                                         if( $5->s_argc ==  $7->s_argc ) {
  731:                                           result=do_map(key, $5->s_argp, $7->s_argp, $5->s_argc, REVERSE_MAP);
  732:                                           
  733:                                         } else {
  734: 					  if ($5->s_argc==1) {
  735: 					    Symbol *a_sp;
  736: 					    a_sp=build_array_list($5,$7->s_argc);
  737: 					    result=do_map(key, a_sp->s_argp, $7->s_argp, a_sp->s_argc, FORWARD_MAP);
  738: 					    free_arglist(a_sp->s_argp);
  739: 					    a_sp->s_argp=NULL;
  740: 					  } else {
  741: 					    sprintf(warn_msg,"/RMAP arg. counts are not matched.\n");
  742: 					    capa_msg(MESSAGE_ERROR,warn_msg);
  743: 					  }
  744:                                         }
  745: 					if (result!=0) {
  746: 					    sprintf(warn_msg,
  747: 						    "/MAP had invalid arguments.\n");
  748: 					    capa_msg(MESSAGE_ERROR,warn_msg);
  749: 					}
  750:                                         free_arglist($5->s_argp);
  751: 					$5->s_argp=NULL;
  752:                                         free_arglist($7->s_argp);
  753: 					$7->s_argp=NULL;
  754:                                       }
  755:              ;
  756: 
  757: 
  758: 
  759: calc_expr    : calc_expr EQ_op  block  { $$ = symbols_op($1, $3, EQ_op);  }
  760:              | calc_expr NE_op  block  { $$ = symbols_op($1, $3, NE_op);  }
  761:              | calc_expr GE_op  block  { $$ = symbols_op($1, $3, GE_op);  }
  762:              | calc_expr GT_op  block  { $$ = symbols_op($1, $3, GT_op);  }
  763:              | calc_expr LE_op  block  { $$ = symbols_op($1, $3, LE_op);  }
  764:              | calc_expr LT_op  block  { $$ = symbols_op($1, $3, LT_op);  }
  765:              | calc_expr AND_op block  { $$ = symbols_op($1, $3, AND_op); }
  766:              | calc_expr OR_op  block  { $$ = symbols_op($1, $3, OR_op);  }
  767:              | block                   { $$ = $1; 
  768:                                          YYDBUG_PR1(" calc_expr <= block "); YYDBUG_SYM($1);   }
  769:              ;
  770: 
  771: block        : block '+' term          { $$ = symbols_op($1, $3, ADD_op); YYDBUG_PR1("block <= block '+' term "); YYDBUG_SYM($$); }
  772:              | block '-' term          { $$ = symbols_op($1, $3, SUB_op); }
  773:              | term                    { $$ = $1; YYDBUG_PR2(" block <= term YYSTATE(%d) ",yystate); YYDBUG_SYM($1);   }
  774:              ;
  775: 
  776: term         : term '*' basic_constr   { $$ = symbols_op($1, $3, MUL_op); }
  777:              | term '/' basic_constr   { $$ = symbols_op($1, $3, DIV_op); }
  778:              | term '%' basic_constr   { $$ = symbols_op($1, $3, IDIV_op); }
  779:              | basic_constr            { $$ = $1; 
  780:                                          YYDBUG_PR1(" term <= basic_constr "); YYDBUG_SYM($1);   }
  781:              ;
  782: 
  783: basic_constr : FUNCTION_ID '('  ')'   {  int tmp;
  784:                                          
  785:                                          Func_idx--;
  786:                                          if(Func_idx >= 0 ) {
  787:                                            tmp = match_function(FuncStack[Func_idx].s_name,0);
  788:                                            $$ = do_function(tmp, 0, NULL );
  789:                                            capa_mfree(FuncStack[Func_idx].s_name);
  790:                                          }
  791:                                          
  792:                                       }
  793:              | FUNCTION_ID '(' arg_list ')'
  794:                                       {  int  tmp;
  795:                                       
  796:                                          Func_idx--;
  797:                                          YYDBUG_PR4(" basic_constr <= FUNCTION<%s><argc=%d> YYSTATE(%d) ",
  798:                                              FuncStack[Func_idx].s_name,$3->s_argc,yystate);
  799:                                          
  800:                                          if(Func_idx >= 0 ) {
  801:                                            tmp = match_function(FuncStack[Func_idx].s_name,$3->s_argc);
  802: 					   $$ = do_function(tmp, $3->s_argc, $3->s_argp);
  803: 					   capa_mfree(FuncStack[Func_idx].s_name);
  804: 					   free_arglist($3->s_argp);
  805: 					   $3->s_argp=NULL;
  806:                                          }
  807:                                          YYDBUG_PR1(" basic_constr <= RETURN FUNCT "); YYDBUG_SYM($$);
  808:                                          
  809:                                       }
  810:              | an_array               {   $$ = $1;   }                         
  811:              | IDENTIFIER             { /* do not free identifier */ 
  812:                                           $$ = $1;
  813:                                       }
  814:              | '-' basic_constr       { $$ = $2;
  815:                                           switch($2->s_type) {
  816:                                             case I_VAR:      $$ = (Symbol *)capa_malloc(sizeof(Symbol),1);
  817:                                                              $$->s_type = I_CONSTANT;
  818:                                             case I_CONSTANT: $$->s_int =    - $2->s_int; break;
  819:                                             case R_VAR: $$ = (Symbol *)capa_malloc(sizeof(Symbol),1);
  820:                                                         $$->s_type = R_CONSTANT;
  821:                                             case R_CONSTANT: $$->s_real =   (-1.0)*($2->s_real); 
  822:                                                              break;
  823:                                             case S_VAR:
  824:                                             case S_CONSTANT: break;
  825:                                             default:         break;
  826:                                           }
  827:                                         }
  828:              | '+' basic_constr         { $$ = $2; }
  829:              | S_CONSTANT               { $$ = $1; }
  830:              | a_number                 { $$ = $1; }
  831:              | '(' calc_expr ')'        { $$ = $2; }
  832:              ;
  833: 
  834: arg_list     : arg_list ',' calc_expr   { $$ = $1;
  835:                                           $$->s_argc++;
  836:                                           $$->s_argp = addto_arglist($1->s_argp, $3); 
  837:                                         }
  838:              | calc_expr                { $$ = $1;
  839:                                           $$->s_argc = 1;
  840:                                           $$->s_argp = new_arglist($1);
  841:                                         }
  842:              ;
  843: 
  844: 
  845: var_list     : IDENTIFIER               { /* do not free identifier */
  846:                                           YYDBUG_PR1(" var_list <= ID");
  847:                                           $$ = $1;
  848:                                           $$->s_argc = 1;
  849:                                           $$->s_argp = new_arglist($1);
  850:                                         }
  851:              | ARRAY_ID '[' calc_expr ']'{
  852:                                           YYDBUG_PR1(" var_list <= ARRAYID,calc");
  853:                                           $$ = get_array_symbol($1,$3,1);
  854:                                           $$->s_argc = 1;
  855:                                           $$->s_argp = new_arglist($$);
  856: 	                                 }
  857:              | var_list ',' ARRAY_ID '[' calc_expr ']' {
  858:                                           YYDBUG_PR1(" var_list <= var_list,ARRAYID,calc");
  859: 	                                  $$ = $1;
  860: 					  $$->s_argc++;
  861: 					  $$->s_argp = addto_arglist($1->s_argp, 
  862: 							    get_array_symbol($3,$5,1));
  863:                                         }
  864:              | var_list ',' IDENTIFIER  { /* do not free identifier */
  865:                                           YYDBUG_PR1(" var_list <= var_list,ID");
  866:                                           $$ = $1;
  867:                                           $$->s_argc++;
  868:                                           $$->s_argp = addto_arglist($1->s_argp, $3); 
  869:                                         }
  870:              ;
  871: 
  872: 
  873: a_number     : an_integer               { $$ = $1; }
  874:              | a_real                   { $$ = $1; }
  875:              ;
  876:              
  877: an_integer   : I_CONSTANT               { $$ = $1; }
  878:              ;
  879:              
  880: a_real       : R_CONSTANT               { $$ = $1; } 
  881:              ;
  882: 
  883: an_array     : ARRAY_ID '[' calc_expr ']'     {   
  884:                                          YYDBUG_PR1(" an_array <= ARRAY_ID '['calc_expr ']' ");
  885:                                          $$=get_array_symbol($1,$3,1);   
  886:                                                } 
  887:              ;
  888: 
  889: startQ       :                  { /* first matching will occur before first line of input text */
  890:                                   YYDBUG_PR1(" startQ := begin_question\n");
  891:                                   begin_question(); Answer_infospec = 0; 
  892:                                 }
  893:              ;
  894: 
  895: 
  896: 
  897: %%
  898: /* ============================================================================  */
  899: ExpNode_p
  900: mk_node(op, left, right) int op; ExpNode_p left; ExpNode_p right;
  901: { 
  902:   ExpNode     *np;
  903:   
  904:   np = (ExpNode* )malloc(sizeof(ExpNode));
  905:   np->e_type       = op;
  906:   np->e_lsibp      = left;
  907:   np->e_rsibp      = right;
  908:   left->e_parentp  = np;
  909:   right->e_parentp = np;
  910:   return (np);
  911: }
  912: 
  913: ExpNode_p
  914: mk_leaf(type, valp) int type; Symbol_p valp;
  915: {
  916:   ExpNode     *np;
  917:   
  918:   np = (ExpNode*)malloc(sizeof(ExpNode));
  919:   np->e_type = IDENTIFIER;
  920:   np->e_sp = valp;
  921:   return (np);
  922:   
  923: }
  924: 
  925: /* ------------------------------------------------------------- */
  926: void free_calc_expr(Symbol *expr)
  927: {
  928:   switch(expr->s_type) {
  929:   case I_CONSTANT:
  930:   case R_CONSTANT: capa_mfree((char *)expr); break;
  931:   case S_CONSTANT: capa_mfree(expr->s_str); capa_mfree((char *)expr); break;
  932:   default: break;
  933:   }
  934: }
  935: 
  936: /* this is the entry point to array symbol retrieval */
  937: /* array main name and index are  used to locate the symbol */
  938: /* name of the array is used to retrieve the array symbol */
  939: 
  940: Symbol* get_array_symbol ( name,index,free_symbols ) 
  941: Symbol *name,*index;int free_symbols;
  942: {
  943:   Symbol  *s_p, *a_p;
  944:   char    *key, *tmp;
  945:   int      leng, idx_len;
  946:   leng = strlen(name->s_name)+8; /* [ ] */
  947:   
  948:   switch(index->s_type) {
  949:     case I_VAR:
  950:     case I_CONSTANT: tmp = (char *)capa_malloc(64,1);
  951:       sprintf(tmp,"%ld",index->s_int);
  952:       break;
  953:     case R_VAR: 
  954:     case R_CONSTANT: tmp = (char *)capa_malloc(64,1);
  955:       sprintf(tmp,"%g",index->s_real);
  956:       break;
  957:     case S_VAR:
  958:     case S_CONSTANT: idx_len = strlen(index->s_str); tmp = (char *)capa_malloc(idx_len+4,1);
  959:       sprintf(tmp,"\"%s\"",index->s_str); /* string array index is a bit different from integer one */
  960:       break;
  961:     default:         break;
  962:   }
  963:   idx_len = strlen(tmp);
  964:   
  965:   key = (char *)capa_malloc(idx_len+leng,1);
  966:   sprintf(key,"%s[%s]",name->s_name,tmp);
  967:   a_p = (Symbol *)NULL;
  968:   a_p = find_arrayid(name->s_name); /* use the array name to search array tree */
  969:   if( a_p == NULL ) {
  970:     return NULL;
  971:   }
  972:                                       /* did not check for error! */
  973:   s_p = find_array_by_index(a_p,key); /* use the index portion to search along array linked list */
  974:   capa_mfree((char *)tmp); capa_mfree((char *)key);
  975:   
  976:   if (free_symbols) { /* free both the name symbol and index symbol */
  977:     if( (index->s_type == I_CONSTANT) || (index->s_type == R_CONSTANT) ) 
  978:       capa_mfree((char *)index);
  979:     if(index->s_type == S_CONSTANT) {
  980:       capa_mfree(index->s_str); capa_mfree((char *)index); 
  981:     }
  982:     capa_mfree(name->s_name);  capa_mfree((char *)name);
  983:   }
  984:   return (s_p);
  985: }
  986: 
  987: Symbol * build_array_list(ar_name,num_elem)
  988: Symbol *ar_name;int num_elem;
  989: {
  990:   int     i;
  991:   Symbol *arg_list,*a_p;
  992:   char    idx_str[MAX_BUFFER_SIZE];
  993:   
  994:   a_p = find_arrayid(ar_name->s_name);
  995:   i = 1;
  996:   sprintf(idx_str,"%s[%d]",ar_name->s_name,i); /* create array elements with integer index */
  997:   arg_list = find_array_by_index(a_p,idx_str); /* will create a new element if not found */
  998:   arg_list->s_argc=1;
  999:   arg_list->s_argp=new_arglist(arg_list);
 1000:   
 1001:   for (i=2;i<=num_elem;i++) {
 1002:       sprintf(idx_str,"%s[%d]",ar_name->s_name,i);
 1003:       arg_list->s_argc++;
 1004:       arg_list->s_argp=addto_arglist(arg_list->s_argp,find_array_by_index(a_p,idx_str));
 1005:   }
 1006:   return arg_list;
 1007: }
 1008: 
 1009: 
 1010: 
 1011: 
 1012: 
 1013: 
 1014: 
 1015: /* ------------------------------------------------------------- */
 1016: void        
 1017: append_text(str) char *str;  
 1018: {            
 1019:   char *q;  
 1020:   int   i;  
 1021:  
 1022:   if (!LexiProblem_p->question) {
 1023:       if (!(q = capa_malloc(strlen(str)+1,1)))  printf("No room to append.");
 1024:       strncpy(q,str,strlen(str)+1);
 1025:   } else {
 1026:       i =  strlen(LexiProblem_p->question);
 1027:       i += (strlen(str)+1);
 1028:       q =  capa_malloc(i,1);  /* *** */
 1029:       if (!q)  printf("No room to append().");
 1030:       strcat(strncpy(q,LexiProblem_p->question, strlen(LexiProblem_p->question)+1), str);
 1031:       capa_mfree(LexiProblem_p->question);
 1032:   }
 1033:   LexiProblem_p->question=q;
 1034: }
 1035:  
 1036: /******************************************************************************/
 1037: /* ADD A STRING TO THE CURRENT HINT TEXT BLOCK                                */
 1038: /******************************************************************************/
 1039: void             /* RETURNS: nothing */
 1040: append_hint(str) /* ARGUMENTS:       */
 1041: char *str;       /*    String to add */
 1042: {                /* LOCAL VARIABLES: */
 1043:    char *q;      /*    New string    */
 1044:  
 1045:    if (!LexiProblem_p->hint) {
 1046:       if (!(q = capa_malloc(strlen(str)+1,1)))
 1047:          printf("no room");
 1048:       strncpy(q,str,strlen(str)+1);
 1049:    } else {
 1050:       if (!(q = capa_malloc(strlen(LexiProblem_p->hint)+strlen(str)+1,1)))
 1051:          printf("no room");
 1052:       strcat(strncpy(q,LexiProblem_p->hint,strlen(LexiProblem_p->hint)), str);
 1053:       capa_mfree(LexiProblem_p->hint);
 1054:    }
 1055:    LexiProblem_p->hint=q;
 1056:    /* printf("APPEND HINT: %s\n", str); */
 1057: }
 1058: /******************************************************************************/
 1059: /* ADD A STRING TO THE CURRENT EXPLAIN TEXT BLOCK                                */
 1060: /******************************************************************************/
 1061: void             /* RETURNS: nothing */
 1062: append_explain(str) /* ARGUMENTS:       */
 1063: char *str;       /*    String to add */
 1064: {                /* LOCAL VARIABLES: */
 1065:    char *q;      /*    New string    */
 1066:  
 1067:    if (!LexiProblem_p->explain) {
 1068:       if (!(q = capa_malloc(strlen(str)+1,1)))
 1069:          printf("no room");
 1070:       strncpy(q,str, strlen(str)+1);
 1071:    } else {
 1072:       if (!(q = capa_malloc(strlen(LexiProblem_p->explain)+strlen(str)+1,1)))
 1073:          printf("no room");
 1074:       strcat(strncpy(q,LexiProblem_p->explain,strlen(LexiProblem_p->explain)+1), str);
 1075:       capa_mfree(LexiProblem_p->explain);
 1076:    }
 1077:    LexiProblem_p->explain=q;
 1078:    /* printf("APPEND EXPLAIN: %s\n", str); */
 1079: }
 1080: 
 1081: void        
 1082: append_error(str) char *str;  
 1083: {            
 1084:   char *q;  
 1085:   int   i;  
 1086: 
 1087:   ErrorMsg_count++;
 1088:   if (!ErrorMsg_p) {
 1089:       if (!(q = capa_malloc(strlen(str)+1,1)))  printf("No room in append.");
 1090:       strncpy(q,str,strlen(str)+1);
 1091:   } else {
 1092:       i =  strlen(ErrorMsg_p);
 1093:       i += (strlen(str)+1);
 1094:       q =  capa_malloc(i,1);  /* *** */
 1095:       if (!q)  printf("No room in append()");
 1096:       strcat(strncpy(q,ErrorMsg_p, strlen(ErrorMsg_p)+1), str);
 1097:       capa_mfree(ErrorMsg_p);
 1098:   }
 1099:   ErrorMsg_p=q;
 1100:   /* printf("APPEND ERROR: %s\n", str); */
 1101: }
 1102: void        
 1103: append_warn(type,str) int type;char *str;  
 1104: {            
 1105:   WarnMsg_t  *p, *t;
 1106:   char       *q;  
 1107: 
 1108:   WarnMsg_count++;
 1109:   if (!WarnMsg_p) {
 1110:       if (!(p = (WarnMsg_t *)capa_malloc(sizeof(WarnMsg_t),1)))  printf("No room in create WarnMsg_t.");
 1111:       if (!(q = capa_malloc(strlen(str)+1,1)))      printf("No room in allocating space for warn msg.");
 1112:       strncpy(q,str,strlen(str)+1);
 1113:       p->warn_next = NULL;
 1114:       p->warn_type = type;
 1115:       p->warn_str = q;
 1116:       WarnMsg_p=p;
 1117:   } else {
 1118:       for(t=WarnMsg_p;t->warn_next;t=t->warn_next) {   } /* do nothing within for loop */
 1119:       if (!(p = (WarnMsg_t *)capa_malloc(sizeof(WarnMsg_t),1)))  printf("No room in create WarnMsg_t.");
 1120:       if (!(q = capa_malloc(strlen(str)+1,1)))      printf("No room in allocating space for warn msg.");
 1121:       strncpy(q,str,strlen(str)+1);
 1122:       p->warn_next = NULL;
 1123:       p->warn_type = type;
 1124:       p->warn_str = q;
 1125:       t->warn_next = p;
 1126:   }
 1127: }
 1128: 
 1129: /*****************************************************************************/
 1130: /*********** if *b is a constant symbol, destroy (free) b ********************/
 1131: /*********** if *a is a var symbol, create a new symbol **********************/
 1132: /*                 do not free(*a)     */
 1133: /*  If either a or b is invalid it propagates the error up the parse tree    */
 1134: Symbol *
 1135: symbols_op(a, b, op) Symbol *a; Symbol *b; int op;
 1136: {
 1137:   int     type,  new, leng;
 1138:   long    tmp_i, tmp_j;
 1139:   double  tmp_p, tmp_q;
 1140:   char    a_str[QUARTER_K], *b_str=NULL, *r_strp;
 1141:   char    warn_msg[ONE_K];
 1142:   Symbol *a_symp;
 1143:   
 1144: if( a->s_type == IDENTIFIER || b->s_type == IDENTIFIER ) {
 1145:    if(a->s_type == IDENTIFIER) { /* a is IDENTIFIER */
 1146:      sprintf(warn_msg,"var \"%s\" not defined before use.\n", a->s_name);
 1147:      capa_msg(MESSAGE_ERROR,warn_msg);
 1148:      return (a);
 1149:    } else { /* b is IDENTIFIER */
 1150:      sprintf(warn_msg,"var \"%s\" not defined before use.\n",b->s_name);
 1151:      capa_msg(MESSAGE_ERROR,warn_msg);
 1152:      return (b);
 1153:    }
 1154:  } else {  /* a and b are neither identifiers */
 1155:   if( (a->s_type == I_VAR) ||
 1156:       (a->s_type == R_VAR) ||
 1157:       (a->s_type == S_VAR) )  {
 1158:         a_symp = (Symbol *)capa_malloc(sizeof(Symbol),1);  /* *** */
 1159:         new = 1;
 1160:   } else {
 1161:         new = 0;
 1162:         a_symp = a; /* re-use symbol *a */
 1163:   }
 1164:   if( ((a->s_type == I_CONSTANT)||(a->s_type == I_VAR)) && 
 1165:       ((b->s_type == I_CONSTANT)||(b->s_type == I_VAR)) ) { /* both a and b are integer */
 1166:     type = I_CONSTANT;
 1167:     switch( op ) {
 1168:       case ADD_op: a_symp->s_int = a->s_int +  b->s_int ; break;
 1169:       case SUB_op: a_symp->s_int = a->s_int -  b->s_int ; break;
 1170:       case MUL_op: a_symp->s_int = a->s_int *  b->s_int ; break;
 1171:       case DIV_op: if(b->s_int != 0) {
 1172:                      a_symp->s_int = a->s_int /  b->s_int ; 
 1173:                    } else {
 1174:                      sprintf(warn_msg,"division (/) by zero!\n");
 1175:                      capa_msg(MESSAGE_ERROR,warn_msg);
 1176:                    } break;
 1177:       case IDIV_op: if(b->s_int != 0) {
 1178:                       a_symp->s_int = (a->s_int %  b->s_int );
 1179:                     } else {
 1180:                       sprintf(warn_msg,"integer division (%%) by zero!\n");
 1181:                       capa_msg(MESSAGE_ERROR,warn_msg);
 1182:                     } break;
 1183:       case EQ_op:   a_symp->s_int = ((a->s_int ==  b->s_int)? 1: 0); break;
 1184:       case NE_op:   a_symp->s_int = ((a->s_int ==  b->s_int)? 0: 1); break;
 1185:       case GT_op:   a_symp->s_int = ((a->s_int >   b->s_int)? 1: 0); break;
 1186:       case GE_op:   a_symp->s_int = ((a->s_int >=  b->s_int)? 1: 0); break;
 1187:       case LT_op:   a_symp->s_int = ((a->s_int <   b->s_int)? 1: 0); break;
 1188:       case LE_op:   a_symp->s_int = ((a->s_int <=  b->s_int)? 1: 0); break;
 1189:       case AND_op:  a_symp->s_int = ((a->s_int &&  b->s_int)? 1: 0); break;
 1190:       case OR_op:   a_symp->s_int = ((a->s_int ||  b->s_int)? 1: 0); break;
 1191:     }
 1192:   } else {  /* a, b neither are integers */
 1193:     if( (a->s_type == S_VAR) || (a->s_type == S_CONSTANT) || 
 1194:         (b->s_type == S_VAR) || (b->s_type == S_CONSTANT) ) { /* either a or b is a string */
 1195:       type = S_CONSTANT;  /* the return type is a string */
 1196:       if( (a->s_type == S_VAR) || (a->s_type == S_CONSTANT) ) { /* a is a string */
 1197: 	if (a->s_str == NULL || 
 1198: 	    (((b->s_type == S_VAR) || (b->s_type == S_CONSTANT)) && b->s_str == NULL)) {
 1199: 	  if (a->s_str == NULL) {
 1200: 	    sprintf(warn_msg,"variable %s has not yet been assigned a value.\n",a->s_name);
 1201: 	    capa_msg(MESSAGE_ERROR,warn_msg);
 1202: 	  }
 1203: 	  if (((b->s_type == S_VAR) || (b->s_type == S_CONSTANT)) && b->s_str == NULL) {
 1204: 	    sprintf(warn_msg,"variable %s has not yet been assigned a value.\n",a->s_name);
 1205: 	    capa_msg(MESSAGE_ERROR,warn_msg);
 1206: 	  }
 1207: 	} else { /* a is a valid string */
 1208: 	  switch( b->s_type ) {
 1209: 	  case I_VAR:
 1210: 	  case I_CONSTANT:
 1211: 	    leng = SMALL_LINE_BUFFER; /* assuming a long integer does not exceed 128 digits*/
 1212: 	    b_str= capa_malloc(sizeof(char), leng);
 1213: 	    sprintf(b_str,"%ld", b->s_int);
 1214: 	    break;
 1215: 	  case R_VAR:
 1216: 	  case R_CONSTANT:
 1217: 	    leng = SMALL_LINE_BUFFER;/*assuming a double does not exceed128chars*/
 1218: 	    b_str= capa_malloc(sizeof(char), leng);
 1219: 	    sprintf(b_str,"%.15g", b->s_real);
 1220: 	    break;
 1221: 	  case S_VAR:
 1222: 	  case S_CONSTANT: /* DONE: get rid of limitations on b_str[] */
 1223: 	    leng =  strlen( b->s_str ) +  1;
 1224: 	    b_str= capa_malloc(sizeof(char), leng);
 1225: 	    sprintf(b_str,"%s",b->s_str);
 1226: 	    /*if(b->s_type == S_CONSTANT)  capa_mfree(b->s_str);*/
 1227: 	    break;
 1228: 	  }
 1229: 	  switch( op ) {
 1230: 	  case ADD_op:
 1231: 	    leng =  strlen( a->s_str ) + strlen(b_str) + 1;
 1232: 	    r_strp = capa_malloc(sizeof(char), leng);    /* **** */
 1233: 	    strcat(r_strp, a->s_str);
 1234: 	    strcat(r_strp, b_str);  /* concatenate two strings together */
 1235: 	    if( !new )   capa_mfree(a->s_str);  
 1236: 	    a_symp->s_str = r_strp;
 1237: 	    break;
 1238: 	  case SUB_op:
 1239: 	  case MUL_op:
 1240: 	  case DIV_op:
 1241: 	  case IDIV_op:
 1242: 	    if( !new )   capa_mfree(a->s_str);
 1243: 	    a_symp->s_str = strsave("<<Op NOT DEFINED>>");
 1244: 	    sprintf(warn_msg,"integer division (%%) cannot accept string operand!\n");
 1245: 	    capa_msg(MESSAGE_ERROR,warn_msg);
 1246: 	    break;
 1247: 	  case EQ_op: a_symp->s_int = (strcmp(a->s_str, b_str) == 0? 1: 0);
 1248: 	    type = I_CONSTANT;  break;
 1249: 	  case NE_op: a_symp->s_int = (strcmp(a->s_str, b_str) == 0? 0: 1);
 1250: 	    type = I_CONSTANT;  break;
 1251: 	  case GT_op: a_symp->s_int = (strcmp(a->s_str, b_str) > 0? 1: 0);
 1252: 	    type = I_CONSTANT;  break;
 1253: 	  case GE_op: a_symp->s_int = (strcmp(a->s_str, b_str) >= 0? 1: 0);
 1254: 	    type = I_CONSTANT;  break;
 1255: 	  case LT_op: a_symp->s_int = (strcmp(a->s_str, b_str) < 0? 1: 0);
 1256: 	    type = I_CONSTANT;  break;
 1257: 	  case LE_op: a_symp->s_int = (strcmp(a->s_str, b_str) <= 0? 1: 0);
 1258: 	    type = I_CONSTANT;  break;
 1259: 	  case AND_op: 
 1260: 	    if( (a->s_str[0] != 0) && (b_str[0] != 0)) {
 1261: 	      a_symp->s_int = 1;
 1262: 	    } else {
 1263: 	      a_symp->s_int = 0;
 1264: 	    } 
 1265: 	    type = I_CONSTANT;  break;
 1266: 	  case OR_op: 
 1267: 	    if( (a->s_str[0] != 0) || (b_str[0] != 0)) {
 1268: 	      a_symp->s_int = 1;
 1269: 	    } else {
 1270: 	      a_symp->s_int = 0;
 1271: 	    } 
 1272: 	    type = I_CONSTANT;  break;
 1273: 	  }
 1274: 	}
 1275: 	if (b_str!=NULL) capa_mfree(b_str);
 1276:       } else {  /* b is string and a is either integer or real */
 1277:         switch( a->s_type ) {
 1278:          case I_VAR:
 1279:          case I_CONSTANT:
 1280:                    sprintf(a_str,"%ld", a->s_int);     break;
 1281:          case R_VAR:
 1282:          case R_CONSTANT:
 1283:                    sprintf(a_str,"%.15g", a->s_real);  break;
 1284:         }
 1285:         switch( op ) {
 1286:          case ADD_op:
 1287:                    leng =  strlen( b->s_str ) + strlen(a_str) + 1;
 1288:                    r_strp = capa_malloc(sizeof(char), leng);   /* *** */
 1289:                    strcat(r_strp, a_str);
 1290:                    strcat(r_strp, b->s_str);
 1291:                    /*if( b->s_type == S_CONSTANT )  capa_mfree(b->s_str);*/
 1292:                    a_symp->s_str = r_strp;              break;
 1293:          case SUB_op:
 1294:          case MUL_op:
 1295:          case DIV_op:
 1296:          case IDIV_op:
 1297:                    a_symp->s_str = strsave("<<Op NOT DEFINED>>");
 1298:                    sprintf(warn_msg,"integer division (%%) cannot accept string operand!\n");
 1299:                    capa_msg(MESSAGE_ERROR,warn_msg);
 1300:                    break;
 1301:          case EQ_op: a_symp->s_int = (strcmp(a_str, b->s_str) == 0? 1: 0);
 1302:                      type = I_CONSTANT;  break;
 1303:          case NE_op: a_symp->s_int = (strcmp(a_str, b->s_str) == 0? 0: 1);
 1304:                      type = I_CONSTANT;  break;
 1305:          case GT_op: a_symp->s_int = (strcmp(a_str, b->s_str) > 0? 1: 0);
 1306:                      type = I_CONSTANT;  break;
 1307:          case GE_op: a_symp->s_int = (strcmp(a_str, b->s_str) >= 0? 1: 0);
 1308:                      type = I_CONSTANT;  break;
 1309:          case LT_op: a_symp->s_int = (strcmp(a_str, b->s_str) < 0? 1: 0);
 1310:                      type = I_CONSTANT;  break;
 1311:          case LE_op: a_symp->s_int = (strcmp(a_str,b->s_str) <= 0? 1: 0);
 1312:                      type = I_CONSTANT;  break;
 1313:          case AND_op: if( (a_str[0] != 0) && (b->s_str[0] != 0)) {
 1314:                        a_symp->s_int = 1;
 1315:                       } else {
 1316:                        a_symp->s_int = 0;
 1317:                       } 
 1318:                      type = I_CONSTANT;  break;
 1319:          case OR_op: if( (a_str[0] != 0) || (b_str[0] != 0)) {
 1320:                        a_symp->s_int = 1;
 1321:                       } else {
 1322:                        a_symp->s_int = 0;
 1323:                       } 
 1324:                      type = I_CONSTANT;  break;
 1325:         }
 1326:       }
 1327:       
 1328:     } else { /* both a and b are real */
 1329:       type = R_CONSTANT;
 1330:       if( (a->s_type == R_CONSTANT)||(a->s_type == R_VAR) ) {
 1331:         tmp_p = a->s_real;
 1332:       } else {
 1333:         tmp_p = (double)a->s_int;
 1334:       }
 1335:       if( (b->s_type == R_CONSTANT)||(b->s_type == R_VAR) ) {
 1336:         tmp_q = b->s_real;
 1337:       } else {
 1338:         tmp_q = (double)b->s_int;
 1339:       }
 1340:       switch( op ) {
 1341:         case ADD_op: a_symp->s_real =  tmp_p + tmp_q ; break;
 1342:         case SUB_op: a_symp->s_real =  tmp_p - tmp_q ; break;
 1343:         case MUL_op: a_symp->s_real =  tmp_p * tmp_q ; break;
 1344:         case DIV_op: if(tmp_q != 0.0) {
 1345:                        a_symp->s_real =  tmp_p / tmp_q ; 
 1346:                      } else {
 1347:                        /* printf("FDIVISION by ZERO\n"); */
 1348:                        sprintf(warn_msg,"division (/) by zero!\n");
 1349:                        capa_msg(MESSAGE_ERROR,warn_msg);
 1350:                      }
 1351:                      break;
 1352:         case IDIV_op: if(tmp_q != 0.0 ) {
 1353:                         tmp_i =  (long)tmp_p;
 1354:                         tmp_j =  (long)tmp_q;
 1355:                         a_symp->s_int = tmp_i % tmp_j;
 1356:                         type = I_CONSTANT;
 1357:                      } else {
 1358:                        /* printf("DIVISION by ZERO\n"); */
 1359:                        sprintf(warn_msg,"division (/) by zero!\n");
 1360:                        capa_msg(MESSAGE_ERROR,warn_msg);
 1361:                      }
 1362:                       break;
 1363:         case EQ_op:   type = I_CONSTANT;
 1364:                       a_symp->s_int = ((tmp_p ==  tmp_q)? 1: 0); break;
 1365:         case NE_op:   type = I_CONSTANT;
 1366:                       a_symp->s_int = ((tmp_p ==  tmp_q)? 0: 1); break;
 1367:         case GT_op:   type = I_CONSTANT;
 1368:                       a_symp->s_int = ((tmp_p >   tmp_q)? 1: 0); break;
 1369:         case GE_op:   type = I_CONSTANT;
 1370:                       a_symp->s_int = ((tmp_p >=  tmp_q)? 1: 0); break;
 1371:         case LT_op:   type = I_CONSTANT;
 1372:                       a_symp->s_int = ((tmp_p <   tmp_q)? 1: 0); break;
 1373:         case LE_op:   type = I_CONSTANT;
 1374:                       a_symp->s_int = ((tmp_p <=  tmp_q)? 1: 0); break;
 1375:         case AND_op:  type = I_CONSTANT;
 1376:                       a_symp->s_int = ((tmp_p &&  tmp_q)? 1: 0); break;
 1377:         case OR_op:   type = I_CONSTANT;
 1378:                       a_symp->s_int = ((tmp_p ||  tmp_q)? 1: 0); break;
 1379:       }
 1380:     }
 1381:   }
 1382:   if( (b->s_type == I_CONSTANT) ||
 1383:       (b->s_type == R_CONSTANT) )    capa_mfree((char *)b);     /* free symbol *b only */
 1384:   if( (b->s_type == S_CONSTANT) ) {  
 1385:     capa_mfree((char *)b->s_str);  
 1386:     capa_mfree((char *)b); 
 1387:   }
 1388:   a_symp->s_type =  type;
 1389:   return (a_symp);
 1390:  } 
 1391: }
 1392: 
 1393: /* ------------------------------------------------------ */
 1394: char *
 1395: format_toTeX( real ) char *real;
 1396: {
 1397:   int     idx, length, fraclength, i_exp;
 1398:   char   *expo_p, fracS[SMALL_LINE_BUFFER], result[ONE_K], *areal;
 1399:   char    warn_msg[WARN_MSG_LENGTH];
 1400:   
 1401:   length = strlen(real);
 1402:   if( index( real, 'e' ) == NULL ) {
 1403:     if( index( real, 'E' ) == NULL ) {
 1404:       sprintf(result,"%s", real);
 1405:     } else {
 1406:       expo_p = index(real, 'E'); /*** hpux complained */
 1407:       fraclength = length - strlen(expo_p);
 1408:       expo_p++; if(expo_p[0] == '+') expo_p++;
 1409:       sscanf(expo_p,"%d",&i_exp);
 1410:       for(idx=0;idx<fraclength;idx++) fracS[idx] = real[idx];
 1411:       fracS[fraclength] = 0;
 1412:       if(i_exp == 0 ) {
 1413:         sprintf(result,"$%s$", fracS);
 1414:       } else {
 1415:         sprintf(result,"$%s \\times 10^{%d}$", fracS, i_exp);
 1416:       }
 1417:     }
 1418:   } else {
 1419:     if( index( real, 'E' ) == NULL ) {
 1420:       expo_p = index(real, 'e'); /*** hpux complained */
 1421:       fraclength = length - strlen(expo_p);
 1422:       expo_p++; if(expo_p[0] == '+') expo_p++;
 1423:       sscanf(expo_p,"%d",&i_exp);
 1424:       for(idx=0;idx<fraclength;idx++) fracS[idx] = real[idx];
 1425:       fracS[fraclength] = 0;
 1426:       if(i_exp == 0 ) {
 1427:         sprintf(result,"$%s$", fracS);
 1428:       } else {
 1429:         sprintf(result,"$%s \\times 10^{%d}$", fracS, i_exp);
 1430:       }
 1431:     } else {
 1432:       sprintf(result,"<<Ill-formed REAL>>");
 1433:       sprintf(warn_msg,"number %s is not a valid real number!\n",real);
 1434:       capa_msg(MESSAGE_ERROR,warn_msg);
 1435:     }
 1436:   }
 1437:   areal = (char *) capa_malloc(strlen(result)+1, 1);
 1438:   strcpy(areal,result);
 1439:   return (areal);
 1440: }
 1441: /* ------------------------------------------------------ */
 1442: char *
 1443: format_toHTML( real ) char *real;
 1444: {
 1445:   int     idx, length, fraclength, i_exp;
 1446:   char   *expo_p, fracS[SMALL_LINE_BUFFER], result[ONE_K], *areal;
 1447:   char    warn_msg[WARN_MSG_LENGTH];
 1448:   
 1449:   length = strlen(real);
 1450:   if( index( real, 'e' ) == NULL ) {
 1451:     if( index( real, 'E' ) == NULL ) {
 1452:       sprintf(result,"%s", real);
 1453:     } else {
 1454:       expo_p = index(real, 'E'); /*** hpux complained */
 1455:       fraclength = length - strlen(expo_p);
 1456:       expo_p++; if(expo_p[0] == '+') expo_p++;
 1457:       sscanf(expo_p,"%d",&i_exp);
 1458:       for(idx=0;idx<fraclength;idx++) fracS[idx] = real[idx];
 1459:       fracS[fraclength] = 0;
 1460:       if(i_exp == 0 ) {
 1461:         sprintf(result,"%s", fracS);
 1462:       } else {
 1463:         sprintf(result,"%s&#215;10<sup>%d</sup>", fracS, i_exp); /* &#215 is code for x */
 1464:       }
 1465:     }
 1466:   } else { /* the string contains 'e' char */
 1467:     if( index( real, 'E' ) == NULL ) {
 1468:       expo_p = index(real, 'e'); /*** hpux complained */
 1469:       fraclength = length - strlen(expo_p);
 1470:       expo_p++; if(expo_p[0] == '+') expo_p++;
 1471:       sscanf(expo_p,"%d",&i_exp);
 1472:       for(idx=0;idx<fraclength;idx++) fracS[idx] = real[idx];
 1473:       fracS[fraclength] = 0;
 1474:       if(i_exp == 0 ) {
 1475:         sprintf(result,"%s", fracS);
 1476:       } else {
 1477:         sprintf(result,"%s&#215;10<sup>%d</sup>", fracS, i_exp); /* &#215 is code for x */
 1478:       }
 1479:     } else {
 1480:       sprintf(result,"<<Ill-formed REAL>>");
 1481:       sprintf(warn_msg,"number %s is not a valid real number!\n",real);
 1482:       capa_msg(MESSAGE_ERROR,warn_msg);
 1483:     }
 1484:   }
 1485:   areal = (char *) capa_malloc(strlen(result)+1, 1);
 1486:   strcpy(areal,result);
 1487:   return (areal);
 1488: }
 1489: /* -- This routine is called when a /ANS is encountered -- */
 1490: void
 1491: init_answerinfo()
 1492: {
 1493: 
 1494:   CurrAnsInfo.ans_str      = NULL;
 1495:   CurrAnsInfo.ans_type     = 0;
 1496:   CurrAnsInfo.ans_calc     = CALC_DEFAULT;
 1497:   CurrAnsInfo.ans_tol_type = TOL_ABSOLUTE;
 1498:   CurrAnsInfo.ans_tol      = TOL_DEFAULT;
 1499:   CurrAnsInfo.ans_sig_ub   = SIG_UB_DEFAULT;
 1500:   CurrAnsInfo.ans_sig_lb   = SIG_LB_DEFAULT;
 1501:   CurrAnsInfo.ans_id_list  = NULL;
 1502:   CurrAnsInfo.ans_pts_list = NULL;
 1503:   CurrAnsInfo.ans_fmt[0]      = '\0';
 1504:   CurrAnsInfo.ans_unit_str[0] = '\0';
 1505:   CurrAnsInfo.ans_unit     = NULL;
 1506:   CurrAnsInfo.ans_next     = NULL;
 1507: }
 1508: /* when encountered a /DIS(variable)  */
 1509: void
 1510: display_var( s )Symbol *s;
 1511: {
 1512:   char    *aline;
 1513:   char    *tmp_p;
 1514:   char    warn_msg[WARN_MSG_LENGTH];
 1515: 
 1516:                           
 1517:   switch(s->s_type) {
 1518:     case IDENTIFIER:
 1519:            aline = (char *)capa_malloc(sizeof(char)*ONE_K,1);
 1520:            sprintf(aline,"VAR \"%s\" NOT DEFINED!", s->s_name);
 1521:            sprintf(warn_msg,"display var \"%s\" not defined before use.\n",s->s_name);
 1522:            capa_msg(MESSAGE_ERROR,warn_msg);
 1523:           break;
 1524:     case I_VAR:  case I_CONSTANT:
 1525:            aline = (char *)capa_malloc(sizeof(char)*ONE_K,1);
 1526:            sprintf(aline, "%ld", s->s_int);
 1527:           break;
 1528:     case R_VAR:  case R_CONSTANT:
 1529:            aline = (char *)capa_malloc(sizeof(char)*ONE_K,1);
 1530:            if(Parsemode_f == TeX_MODE) {
 1531:              if(s->s_distype == DEFAULT_FORMAT ) {
 1532:                 sprintf(aline,"%.15g",s->s_real);
 1533:              } else {
 1534:                 sprintf(aline,s->s_format,s->s_real);
 1535:              }
 1536:              tmp_p = format_toTeX(aline);
 1537:              sprintf(aline,"%s",tmp_p);
 1538:              capa_mfree( (char *)tmp_p);
 1539:                                                       
 1540:            } else {
 1541:              if(Parsemode_f == HTML_MODE ) {
 1542:                 if(s->s_distype == DEFAULT_FORMAT ) {
 1543:                    sprintf(aline,"%.15g",s->s_real);
 1544:                 } else {
 1545:                    sprintf(aline,s->s_format,s->s_real);
 1546:                 }
 1547:                 tmp_p = format_toHTML(aline);
 1548:                 sprintf(aline,"%s",tmp_p);
 1549:                 capa_mfree( (char *)tmp_p);
 1550:               } else {
 1551:                 if(s->s_distype == DEFAULT_FORMAT ) {
 1552:                   sprintf(aline,"%.15g",s->s_real);
 1553:                 } else {
 1554:                   sprintf(aline,s->s_format,s->s_real);   
 1555:                 }
 1556:               }
 1557:             }
 1558:            break;
 1559:      case S_VAR:  case S_CONSTANT:  
 1560:             if (s->s_str == NULL) {
 1561: 	      sprintf(warn_msg,"variable %s has not yet been assigned a value.\n",
 1562: 		      s->s_name);
 1563: 	      capa_msg(MESSAGE_ERROR,warn_msg);
 1564: 	      aline=(char *)capa_malloc(9,1);
 1565: 	      sprintf(aline,"NO VALUE");
 1566:             } else {
 1567: 	      aline = (char *)capa_malloc(strlen(s->s_str)+1,1);
 1568: 	      sprintf(aline,"%s",s->s_str);
 1569: 	    }
 1570:            break;
 1571:    }
 1572:    append_text(aline);
 1573:    capa_mfree((char *)aline);
 1574:    if(s->s_format) { capa_mfree((char *)s->s_format); }
 1575:    s->s_format = NULL;
 1576:    switch(s->s_type) { /* free up spaces taken by constants */
 1577:      case I_CONSTANT:
 1578:      case R_CONSTANT: capa_mfree((char *)s); break;
 1579:      case S_CONSTANT: capa_mfree(s->s_str); capa_mfree((char *)s); break;
 1580:      default:  break;
 1581:    }
 1582: 
 1583: }
 1584: 
 1585: /* Assign the correct answer to CurrAnsInfo first */
 1586: void
 1587: assign_answer( s ) Symbol *s;
 1588: {
 1589:   char    aline[QUARTER_K];
 1590:   char    warn_msg[WARN_MSG_LENGTH];
 1591:                                           
 1592:   /*problem_default(LexiProblem_p);*/
 1593:   switch(s->s_type) {
 1594:     case IDENTIFIER:
 1595:             sprintf(warn_msg,"File %s, Line %3d: in /ANS, var %s not defined before use.\n",
 1596:               Opened_filename[Input_idx],Current_line[Input_idx],s->s_name);
 1597:             capa_msg(MESSAGE_ERROR,warn_msg);
 1598:             CurrAnsInfo.ans_str = strsave("ANSWER NOT DEFINED!");
 1599:             CurrAnsInfo.ans_type = ANSWER_IS_STRING_CI;
 1600:             sprintf(CurrAnsInfo.ans_fmt,"%%s");
 1601: 	    if (CurrAnsInfo.ans_tol == 0.0) {
 1602: 		sprintf(warn_msg, "File %s, Line %3d: answer has a numerical value of %ld and an implicit zero tolerance.\n",
 1603: 		  Opened_filename[Input_idx],Current_line[Input_idx],s->s_int);
 1604: 		capa_msg(MESSAGE_WARN,warn_msg);
 1605: 	    }
 1606: 	break;
 1607:      case I_VAR:  case I_CONSTANT:
 1608:             sprintf(aline, "%ld", s->s_int);
 1609:             CurrAnsInfo.ans_str = strsave(aline);
 1610:             CurrAnsInfo.ans_type = ANSWER_IS_INTEGER;
 1611:             sprintf(CurrAnsInfo.ans_fmt,"%%ld");
 1612:         break;
 1613:      case R_VAR:  case R_CONSTANT:
 1614:             if(s->s_distype == DEFAULT_FORMAT ) {
 1615:                sprintf(aline,"%.15g",s->s_real);
 1616:                sprintf(CurrAnsInfo.ans_fmt,"%%.15g");
 1617:             } else {
 1618:                sprintf(aline,"%.15g",s->s_real);
 1619:                strcpy(CurrAnsInfo.ans_fmt,s->s_format);  
 1620:             }
 1621:             CurrAnsInfo.ans_str = strsave(aline);
 1622:             CurrAnsInfo.ans_type = ANSWER_IS_FLOAT;
 1623:             if( CurrAnsInfo.ans_tol == 0.0 ) {
 1624:                 sprintf(warn_msg,"File %s, Line %3d: answer has a numerical value of %s and a zero tolerance.\n",
 1625:                         Opened_filename[Input_idx],Current_line[Input_idx],aline);
 1626:                 capa_msg(MESSAGE_WARN,warn_msg);
 1627:             }
 1628:          break;
 1629:      case S_VAR:  case S_CONSTANT:
 1630:             CurrAnsInfo.ans_str = strsave(s->s_str);
 1631:             if (s->s_str!=NULL && (strlen(s->s_str)>ANSWER_STRING_LENG-1)) {
 1632: 	      sprintf(warn_msg,"File %s, Line %3d: answer is too long, max allowed length is %d, current answer is %d\n",
 1633: 		      Opened_filename[Input_idx],Current_line[Input_idx],
 1634: 		      ANSWER_STRING_LENG-1, strlen(s->s_str));
 1635: 	      capa_msg(MESSAGE_ERROR,warn_msg);
 1636: 	      CurrAnsInfo.ans_str[ANSWER_STRING_LENG-1]='\0';
 1637: 	    }
 1638:             if ( !CurrAnsInfo.ans_type ) { /* not yet specified by str=  answer info */ 
 1639:               CurrAnsInfo.ans_type = ANSWER_IS_STRING_CI;
 1640:             }
 1641:             sprintf(CurrAnsInfo.ans_fmt,"%%s");
 1642:          break;
 1643:    }
 1644:    if(s->s_format) { 
 1645:        capa_mfree((char *)s->s_format);
 1646:    }
 1647:    s->s_format = NULL;
 1648:    switch(s->s_type) {
 1649:       case I_CONSTANT:
 1650:       case R_CONSTANT: capa_mfree((char *)s); break;
 1651:       case S_CONSTANT: capa_mfree(s->s_str); capa_mfree((char *)s); break;
 1652:      default:  break;
 1653:    }
 1654: 
 1655: }
 1656: 
 1657: /* Assign tolerance to CurrAnsInfo first */
 1658: void
 1659: assign_tolerance(tol_type, s) int tol_type; Symbol *s;
 1660: {
 1661:   char  warn_msg[WARN_MSG_LENGTH];
 1662:   
 1663:   CurrAnsInfo.ans_tol_type  = tol_type;
 1664:   switch( s->s_type ) {
 1665:       case IDENTIFIER:
 1666:             sprintf(warn_msg,"TOL = var, \"%s\" not defined before use.\n",s->s_name);
 1667:             capa_msg(MESSAGE_ERROR,warn_msg);
 1668:             CurrAnsInfo.ans_tol = 0.0;
 1669:           break;
 1670:        case I_VAR: case I_CONSTANT: 
 1671:            CurrAnsInfo.ans_tol =(double)s->s_int;
 1672:           break;
 1673:        case R_VAR: case R_CONSTANT:
 1674:            CurrAnsInfo.ans_tol = s->s_real;
 1675:           break;
 1676:        case S_VAR: case S_CONSTANT: CurrAnsInfo.ans_tol = 0.0;
 1677:           break;
 1678:    }
 1679:   free_calc_expr(s);
 1680: }
 1681: 
 1682: /* Problem weight is per problem based */
 1683: void
 1684: assign_weight( s ) Symbol *s;
 1685: { char warn_msg[WARN_MSG_LENGTH];
 1686:   YYDBUG_PR1(" weight = identifier\n");
 1687:   switch( s->s_type ) {
 1688:     case IDENTIFIER:
 1689:             sprintf(warn_msg,"WGT = var, \"%s\" not defined before use.\n", s->s_name);
 1690:             capa_msg(MESSAGE_ERROR,warn_msg);
 1691:             LexiProblem_p->weight = WEIGHT_DEFAULT;
 1692:            break;
 1693:     case I_VAR: case I_CONSTANT:
 1694:             if( s->s_int < 0 ) {
 1695:               sprintf(warn_msg,"WGT = %ld, weight cannot be less than zero.\n", s->s_int);
 1696: 	      capa_msg(MESSAGE_ERROR,warn_msg);
 1697: 	      LexiProblem_p->weight = WEIGHT_DEFAULT;
 1698:             } else {
 1699:               LexiProblem_p->weight = s->s_int; 
 1700:             }
 1701:             break;
 1702:      case R_VAR: case R_CONSTANT:
 1703:             if( s->s_real < 0.0 ) {
 1704:                sprintf(warn_msg,"WGT = %g, weight cannot be less than zero.\n", s->s_real);
 1705: 	       capa_msg(MESSAGE_ERROR,warn_msg);
 1706: 	       LexiProblem_p->weight = WEIGHT_DEFAULT;
 1707:             } else {
 1708:                LexiProblem_p->weight = (int)(s->s_real); 
 1709:             }
 1710:             break;
 1711:       case S_VAR: case S_CONSTANT: LexiProblem_p->weight = WEIGHT_DEFAULT; break;
 1712:     }
 1713:   free_calc_expr(s);
 1714: }
 1715: /* Answer try limit is per problem based */
 1716: void
 1717: assign_try_limits( s ) Symbol *s;
 1718: { char warn_msg[WARN_MSG_LENGTH];
 1719:   switch( s->s_type ) {
 1720:     case IDENTIFIER:
 1721: 	    sprintf(warn_msg,"TRY = var, \"%s\" not defined before use.\n",s->s_name);
 1722:             capa_msg(MESSAGE_ERROR,warn_msg);
 1723:             LexiProblem_p->tries = MAX_TRIES;
 1724:            break;
 1725:     case I_VAR: case I_CONSTANT:
 1726:             if(s->s_int <= 0) {
 1727: 	       sprintf(warn_msg,"TRIES = %ld, tries cannot be less than or equal to zero.\n",s->s_int);
 1728: 	       capa_msg(MESSAGE_ERROR,warn_msg);
 1729: 	       LexiProblem_p->tries = MAX_TRIES;
 1730: 	    } else {
 1731: 	       LexiProblem_p->tries = s->s_int;
 1732: 	    }
 1733: 	   break;
 1734:      case R_VAR:  case R_CONSTANT:
 1735:             if(s->s_real <= 0.0) {
 1736: 	       sprintf(warn_msg,"TRIES = %g, tries cannot be less than or equal to zero.\n",s->s_real);
 1737: 	       capa_msg(MESSAGE_ERROR,warn_msg);
 1738: 	       LexiProblem_p->tries = MAX_TRIES;
 1739: 	     } else {
 1740: 	       LexiProblem_p->tries = (int)(s->s_real);
 1741: 	     }
 1742:             break;
 1743:       case S_VAR: case S_CONSTANT: LexiProblem_p->tries = MAX_TRIES; break;
 1744:    }	    
 1745:   free_calc_expr(s);
 1746: }
 1747: /* Answer hint is per problem based */
 1748: void
 1749: assign_hint( s ) Symbol *s;
 1750: {  char warn_msg[WARN_MSG_LENGTH];
 1751: 	                                 
 1752:     switch( s->s_type ) {
 1753:       case IDENTIFIER:
 1754:                sprintf(warn_msg,"HINT = var, \"%s\" not defined before use.\n", s->s_name);
 1755:                capa_msg(MESSAGE_ERROR,warn_msg);
 1756:                LexiProblem_p->show_hint = SHOW_HINT_DEFAULT;
 1757:              break;
 1758:       case I_VAR: case I_CONSTANT:
 1759:                if( s->s_int < 0 ) {
 1760:                   sprintf(warn_msg,"HINT = %ld, show hint cannot be less than zero.\n", s->s_int);
 1761: 	          capa_msg(MESSAGE_ERROR,warn_msg);
 1762: 	          LexiProblem_p->show_hint = SHOW_HINT_DEFAULT;
 1763:                } else {
 1764:                   LexiProblem_p->show_hint = s->s_int; 
 1765:                }
 1766:              break;
 1767:        case R_VAR: case R_CONSTANT:
 1768:                if( s->s_real < 0.0 ) {
 1769:                   sprintf(warn_msg,"HINT = %g, show hint cannot be less than zero.\n", s->s_real);
 1770: 	          capa_msg(MESSAGE_ERROR,warn_msg);
 1771: 	          LexiProblem_p->show_hint = SHOW_HINT_DEFAULT;
 1772:                } else {
 1773:                   LexiProblem_p->weight = (int)(s->s_real); 
 1774:                }
 1775:              break;
 1776:        case S_VAR: case S_CONSTANT: LexiProblem_p->show_hint = SHOW_HINT_DEFAULT; break;
 1777:     }
 1778:   free_calc_expr(s);
 1779: }
 1780: 
 1781: /* Assign answer units string to CurrAnsInfo first */
 1782: void
 1783: assign_units( s ) Symbol *s;
 1784: {
 1785:   char    symb_str[ONE_TWO_EIGHT];
 1786:   char    warn_msg[WARN_MSG_LENGTH];
 1787:   
 1788:   switch( s->s_type ) {
 1789:     case IDENTIFIER:
 1790:            sprintf(warn_msg,"UNIT = var, \"%s\" not defined before use.\n", s->s_name);
 1791:            capa_msg(MESSAGE_ERROR,warn_msg);
 1792:            break;
 1793:     case I_VAR: case I_CONSTANT:
 1794:            sprintf(warn_msg,"UNIT = %ld, unit cannot be a number.\n", s->s_int);
 1795:            capa_msg(MESSAGE_ERROR,warn_msg);
 1796:            break;
 1797:     case R_VAR: case R_CONSTANT:
 1798:            sprintf(warn_msg,"UNIT = %g, unit cannot be a number.\n", s->s_real);
 1799: 	   capa_msg(MESSAGE_ERROR,warn_msg);
 1800:            break;
 1801:     case S_VAR: case S_CONSTANT:
 1802:            strcpy(symb_str,s->s_str);
 1803: 	   strcpy(CurrAnsInfo.ans_unit_str,symb_str);
 1804: 	   CurrAnsInfo.ans_unit = u_parse_unit(symb_str);
 1805: 	   if (gUnitError) {
 1806: 	      sprintf(warn_msg,"Error in unit specified: %s\n",symb_str);
 1807: 	      capa_msg(MESSAGE_ERROR,warn_msg);
 1808: 	   }
 1809: 	break;
 1810:   }
 1811: }
 1812: void
 1813: assign_sigs( lb, ub ) int lb; int ub;
 1814: {
 1815:   CurrAnsInfo.ans_sig_lb = lb;
 1816:   CurrAnsInfo.ans_sig_ub = ub;
 1817: }
 1818: 
 1819: void
 1820: assign_id_list( s ) Symbol *s;
 1821: {
 1822:   char    warn_msg[WARN_MSG_LENGTH];
 1823:   
 1824:   switch( s->s_type ) {
 1825:     case IDENTIFIER:
 1826:            sprintf(warn_msg,"Eval = < ID @ Pts >, \"%s\" not defined before use.\n", s->s_name);
 1827:            capa_msg(MESSAGE_ERROR,warn_msg);
 1828:            break;
 1829:     case I_VAR: case I_CONSTANT:
 1830:            sprintf(warn_msg,"Eval = < %ld @ Pts >, ID cannot be a number.\n", s->s_int);
 1831:            capa_msg(MESSAGE_ERROR,warn_msg);
 1832:            break;
 1833:     case R_VAR: case R_CONSTANT:
 1834:            sprintf(warn_msg,"Eval = < %.16g @ Pts >, ID cannot be a number.\n", s->s_real);
 1835: 	   capa_msg(MESSAGE_ERROR,warn_msg);
 1836:            break;
 1837:     case S_VAR: case S_CONSTANT:
 1838: 	   CurrAnsInfo.ans_id_list = strsave(s->s_str);
 1839: 	   break;
 1840:   }
 1841: }
 1842: 
 1843: /* void assign_pts ( Symbol* coord1, Symbol* coord2, Symbol* num) { */
 1844: void assign_pts (coord1, coord2, num)Symbol *coord1;Symbol *coord2;Symbol *num;
 1845: {
 1846:   PointsList_t *pt;
 1847:   if( LastPtsList != NULL ) {
 1848:     LastPtsList->pts_next = gen_ptslist( coord1, coord2, num );
 1849:     pt = LastPtsList->pts_next;
 1850:     while( pt->pts_next != NULL ) {
 1851:       pt = pt->pts_next;
 1852:     }
 1853:     LastPtsList = pt;
 1854:   } else {
 1855:     CurrPtsList = gen_ptslist( coord1, coord2, num );
 1856:     LastPtsList = CurrPtsList;
 1857:   }
 1858:   if(coord1->s_type == S_CONSTANT) {
 1859:     capa_mfree(coord1->s_str); capa_mfree((char *)coord1);
 1860:   }
 1861:   if(coord2->s_type == S_CONSTANT) {
 1862:     capa_mfree(coord2->s_str); capa_mfree((char *)coord2);
 1863:   }
 1864:   if(num->s_type == I_CONSTANT || num->s_type == R_CONSTANT) {
 1865:     capa_mfree((char *)num);
 1866:   }
 1867: }
 1868: 
 1869: /* =========================================================================== */
 1870: 
 1871: 
 1872: 
 1873: 
 1874: 
 1875: 
 1876: /* =========================================================================== */
 1877: 
 1878: void start_question_over()
 1879: {
 1880:   free_problems(LexiProblem_p);
 1881:   LexiProblem_p = (Problem_t *) capa_malloc(sizeof(Problem_t),1); 
 1882:   problem_default(LexiProblem_p);
 1883:   begin_question();
 1884: }
 1885: 
 1886: void
 1887: init_new_prob()
 1888: {
 1889:   if (LastProblem_p) {
 1890:      LastProblem_p->next = LexiProblem_p;
 1891:   } else {
 1892:      FirstProblem_p      = LexiProblem_p;
 1893:   }
 1894:   LastProblem_p = LexiProblem_p;
 1895:   Lexi_qnum++;  
 1896:   LexiProblem_p = (Problem_t *) capa_malloc(sizeof(Problem_t),1); /* *** */
 1897:   problem_default(LexiProblem_p);
 1898: }
 1899: void
 1900: add_answer_cnt(op)int op;
 1901: {
 1902:   LexiProblem_p->ans_cnt++;
 1903:   if(LexiProblem_p->ans_op == 0) { /* the very first /AND or /OR */
 1904:     LexiProblem_p->ans_op = op;
 1905:   } else {
 1906:     if( LexiProblem_p->ans_op != op ) { char    warn_msg[WARN_MSG_LENGTH];
 1907:       sprintf(warn_msg,"When specifying multiple answers, either /AND or /OR can be used, but not both.\n");
 1908:       capa_msg(MESSAGE_ERROR,warn_msg);
 1909:     }
 1910:   }
 1911: }
 1912: 
 1913: /* -- called when forming answer_expr */
 1914: void
 1915: finish_answer_info()
 1916: {
 1917:   AnswerInfo_t  *ai;
 1918:   
 1919:   if( LexiProblem_p->ans_cnt == 1 ) {  /* Only one answer is defined */
 1920:       LexiProblem_p->answer    = CurrAnsInfo.ans_str;
 1921:       LexiProblem_p->ans_type  = CurrAnsInfo.ans_type;
 1922:       LexiProblem_p->calc      = CurrAnsInfo.ans_calc;
 1923:       LexiProblem_p->tol_type  = CurrAnsInfo.ans_tol_type;
 1924:       LexiProblem_p->tolerance = CurrAnsInfo.ans_tol;
 1925:       LexiProblem_p->sig_ubound= CurrAnsInfo.ans_sig_ub;
 1926:       LexiProblem_p->sig_lbound= CurrAnsInfo.ans_sig_lb;
 1927:       LexiProblem_p->id_list   = CurrAnsInfo.ans_id_list;
 1928:       LexiProblem_p->pts_list  = CurrAnsInfo.ans_pts_list;
 1929:       strcpy(LexiProblem_p->ans_fmt,CurrAnsInfo.ans_fmt);
 1930:       strcpy(LexiProblem_p->unit_str,CurrAnsInfo.ans_unit_str);
 1931:       LexiProblem_p->ans_unit  = CurrAnsInfo.ans_unit;
 1932:   } else {
 1933:       ai = (AnswerInfo_t  *)capa_malloc(sizeof(AnswerInfo_t),1);
 1934:       ai->ans_str       = CurrAnsInfo.ans_str;
 1935:       ai->ans_type      = CurrAnsInfo.ans_type;
 1936:       ai->ans_calc      = CurrAnsInfo.ans_calc;
 1937:       ai->ans_tol_type  = CurrAnsInfo.ans_tol_type;
 1938:       ai->ans_tol       = CurrAnsInfo.ans_tol;
 1939:       ai->ans_sig_ub    = CurrAnsInfo.ans_sig_ub;
 1940:       ai->ans_sig_lb    = CurrAnsInfo.ans_sig_lb;
 1941:       ai->ans_id_list   = CurrAnsInfo.ans_id_list;
 1942:       ai->ans_pts_list  = CurrAnsInfo.ans_pts_list;
 1943:       strcpy(ai->ans_fmt,CurrAnsInfo.ans_fmt);
 1944:       strcpy(ai->ans_unit_str,CurrAnsInfo.ans_unit_str);
 1945:       ai->ans_unit      = CurrAnsInfo.ans_unit;
 1946:       ai->ans_next      = NULL;
 1947:       if(LexiProblem_p->ans_cnt == 2) {
 1948:         LexiProblem_p->ans_list = ai;
 1949:       } else {
 1950:         (LexiProblem_p->ans_list_last)->ans_next = ai;
 1951:       }
 1952:       LexiProblem_p->ans_list_last = ai;
 1953:   }
 1954: 
 1955: }
 1956: 
 1957: /* === End of capaGrammarDef.y ============================================= */
 1958: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>