Annotation of loncom/homework/CAPA-converter/capaGrammarDef.y, revision 1.1

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

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