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