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