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}\n");
206: break;
207: case HTML_MODE: append_text("</PRE>\n");
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>