Annotation of capa/capa51/pProj/capaGrammarDef.y, revision 1.8

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

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