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