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