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