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