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