Annotation of capa/capa51/pProj/capaGrammarDef.y, revision 1.14
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);
1.14 ! albertel 707: a_sp->s_argp=NULL;
1.1 albertel 708: } else {
709: sprintf(warn_msg,"/MAP arg. counts are not matched.\n");
710: capa_msg(MESSAGE_ERROR,warn_msg);
711: }
712: }
713: if (result!=0) {
714: sprintf(warn_msg,
715: "/MAP had invalid arguments.\n");
716: capa_msg(MESSAGE_ERROR,warn_msg);
717: }
718: free_arglist($5->s_argp);
1.14 ! albertel 719: $5->s_argp=NULL;
! 720: free_arglist($7->s_argp);
! 721: $7->s_argp=NULL;
1.1 albertel 722: }
723: | startR '(' basic_constr ';' var_list ';' arg_list ')'
1.3 albertel 724: { char key[SMALL_LINE_BUFFER];
1.1 albertel 725: char warn_msg[WARN_MSG_LENGTH];
726: int result=0;
727:
728: YYDBUG_PR1(" rmap_expr body executed\n");
729: sprintf(key,"%ld",$3->s_int);
730: if( $5->s_argc == $7->s_argc ) {
731: result=do_map(key, $5->s_argp, $7->s_argp, $5->s_argc, REVERSE_MAP);
732:
733: } else {
734: if ($5->s_argc==1) {
735: Symbol *a_sp;
736: a_sp=build_array_list($5,$7->s_argc);
737: result=do_map(key, a_sp->s_argp, $7->s_argp, a_sp->s_argc, FORWARD_MAP);
738: free_arglist(a_sp->s_argp);
1.14 ! albertel 739: a_sp->s_argp=NULL;
1.1 albertel 740: } else {
741: sprintf(warn_msg,"/RMAP arg. counts are not matched.\n");
742: capa_msg(MESSAGE_ERROR,warn_msg);
743: }
744: }
745: if (result!=0) {
746: sprintf(warn_msg,
747: "/MAP had invalid arguments.\n");
748: capa_msg(MESSAGE_ERROR,warn_msg);
749: }
750: free_arglist($5->s_argp);
1.14 ! albertel 751: $5->s_argp=NULL;
1.1 albertel 752: free_arglist($7->s_argp);
1.14 ! albertel 753: $7->s_argp=NULL;
1.1 albertel 754: }
755: ;
756:
757:
758:
759: calc_expr : calc_expr EQ_op block { $$ = symbols_op($1, $3, EQ_op); }
760: | calc_expr NE_op block { $$ = symbols_op($1, $3, NE_op); }
761: | calc_expr GE_op block { $$ = symbols_op($1, $3, GE_op); }
762: | calc_expr GT_op block { $$ = symbols_op($1, $3, GT_op); }
763: | calc_expr LE_op block { $$ = symbols_op($1, $3, LE_op); }
764: | calc_expr LT_op block { $$ = symbols_op($1, $3, LT_op); }
765: | calc_expr AND_op block { $$ = symbols_op($1, $3, AND_op); }
766: | calc_expr OR_op block { $$ = symbols_op($1, $3, OR_op); }
767: | block { $$ = $1;
768: YYDBUG_PR1(" calc_expr <= block "); YYDBUG_SYM($1); }
769: ;
770:
771: block : block '+' term { $$ = symbols_op($1, $3, ADD_op); YYDBUG_PR1("block <= block '+' term "); YYDBUG_SYM($$); }
772: | block '-' term { $$ = symbols_op($1, $3, SUB_op); }
773: | term { $$ = $1; YYDBUG_PR2(" block <= term YYSTATE(%d) ",yystate); YYDBUG_SYM($1); }
774: ;
775:
776: term : term '*' basic_constr { $$ = symbols_op($1, $3, MUL_op); }
777: | term '/' basic_constr { $$ = symbols_op($1, $3, DIV_op); }
778: | term '%' basic_constr { $$ = symbols_op($1, $3, IDIV_op); }
779: | basic_constr { $$ = $1;
780: YYDBUG_PR1(" term <= basic_constr "); YYDBUG_SYM($1); }
781: ;
782:
783: basic_constr : FUNCTION_ID '(' ')' { int tmp;
784:
785: Func_idx--;
786: if(Func_idx >= 0 ) {
787: tmp = match_function(FuncStack[Func_idx].s_name,0);
788: $$ = do_function(tmp, 0, NULL );
789: capa_mfree(FuncStack[Func_idx].s_name);
790: }
791:
792: }
793: | FUNCTION_ID '(' arg_list ')'
794: { int tmp;
795:
796: Func_idx--;
797: YYDBUG_PR4(" basic_constr <= FUNCTION<%s><argc=%d> YYSTATE(%d) ",
798: FuncStack[Func_idx].s_name,$3->s_argc,yystate);
799:
800: if(Func_idx >= 0 ) {
801: tmp = match_function(FuncStack[Func_idx].s_name,$3->s_argc);
802: $$ = do_function(tmp, $3->s_argc, $3->s_argp);
803: capa_mfree(FuncStack[Func_idx].s_name);
804: free_arglist($3->s_argp);
1.14 ! albertel 805: $3->s_argp=NULL;
1.1 albertel 806: }
807: YYDBUG_PR1(" basic_constr <= RETURN FUNCT "); YYDBUG_SYM($$);
808:
809: }
810: | an_array { $$ = $1; }
811: | IDENTIFIER { /* do not free identifier */
812: $$ = $1;
813: }
814: | '-' basic_constr { $$ = $2;
815: switch($2->s_type) {
816: case I_VAR: $$ = (Symbol *)capa_malloc(sizeof(Symbol),1);
817: $$->s_type = I_CONSTANT;
818: case I_CONSTANT: $$->s_int = - $2->s_int; break;
819: case R_VAR: $$ = (Symbol *)capa_malloc(sizeof(Symbol),1);
820: $$->s_type = R_CONSTANT;
821: case R_CONSTANT: $$->s_real = (-1.0)*($2->s_real);
822: break;
823: case S_VAR:
824: case S_CONSTANT: break;
825: default: break;
826: }
827: }
828: | '+' basic_constr { $$ = $2; }
829: | S_CONSTANT { $$ = $1; }
830: | a_number { $$ = $1; }
831: | '(' calc_expr ')' { $$ = $2; }
832: ;
833:
834: arg_list : arg_list ',' calc_expr { $$ = $1;
835: $$->s_argc++;
836: $$->s_argp = addto_arglist($1->s_argp, $3);
837: }
838: | calc_expr { $$ = $1;
839: $$->s_argc = 1;
840: $$->s_argp = new_arglist($1);
841: }
842: ;
843:
844:
845: var_list : IDENTIFIER { /* do not free identifier */
846: YYDBUG_PR1(" var_list <= ID");
847: $$ = $1;
848: $$->s_argc = 1;
849: $$->s_argp = new_arglist($1);
850: }
851: | ARRAY_ID '[' calc_expr ']'{
852: YYDBUG_PR1(" var_list <= ARRAYID,calc");
853: $$ = get_array_symbol($1,$3,1);
854: $$->s_argc = 1;
855: $$->s_argp = new_arglist($$);
856: }
857: | var_list ',' ARRAY_ID '[' calc_expr ']' {
858: YYDBUG_PR1(" var_list <= var_list,ARRAYID,calc");
859: $$ = $1;
860: $$->s_argc++;
861: $$->s_argp = addto_arglist($1->s_argp,
862: get_array_symbol($3,$5,1));
863: }
864: | var_list ',' IDENTIFIER { /* do not free identifier */
865: YYDBUG_PR1(" var_list <= var_list,ID");
866: $$ = $1;
867: $$->s_argc++;
868: $$->s_argp = addto_arglist($1->s_argp, $3);
869: }
870: ;
871:
872:
873: a_number : an_integer { $$ = $1; }
874: | a_real { $$ = $1; }
875: ;
876:
877: an_integer : I_CONSTANT { $$ = $1; }
878: ;
879:
880: a_real : R_CONSTANT { $$ = $1; }
881: ;
882:
1.9 albertel 883: an_array : ARRAY_ID '[' calc_expr ']' {
884: YYDBUG_PR1(" an_array <= ARRAY_ID '['calc_expr ']' ");
885: $$=get_array_symbol($1,$3,1);
886: }
1.1 albertel 887: ;
888:
889: startQ : { /* first matching will occur before first line of input text */
890: YYDBUG_PR1(" startQ := begin_question\n");
891: begin_question(); Answer_infospec = 0;
892: }
893: ;
894:
895:
896:
897: %%
898: /* ============================================================================ */
899: ExpNode_p
900: mk_node(op, left, right) int op; ExpNode_p left; ExpNode_p right;
901: {
902: ExpNode *np;
903:
904: np = (ExpNode* )malloc(sizeof(ExpNode));
905: np->e_type = op;
906: np->e_lsibp = left;
907: np->e_rsibp = right;
908: left->e_parentp = np;
909: right->e_parentp = np;
910: return (np);
911: }
912:
913: ExpNode_p
914: mk_leaf(type, valp) int type; Symbol_p valp;
915: {
916: ExpNode *np;
917:
918: np = (ExpNode*)malloc(sizeof(ExpNode));
919: np->e_type = IDENTIFIER;
920: np->e_sp = valp;
921: return (np);
922:
923: }
924:
925: /* ------------------------------------------------------------- */
926: void free_calc_expr(Symbol *expr)
927: {
928: switch(expr->s_type) {
929: case I_CONSTANT:
930: case R_CONSTANT: capa_mfree((char *)expr); break;
931: case S_CONSTANT: capa_mfree(expr->s_str); capa_mfree((char *)expr); break;
932: default: break;
933: }
934: }
935:
936: /* this is the entry point to array symbol retrieval */
937: /* array main name and index are used to locate the symbol */
938: /* name of the array is used to retrieve the array symbol */
939:
940: Symbol* get_array_symbol ( name,index,free_symbols )
941: Symbol *name,*index;int free_symbols;
942: {
943: Symbol *s_p, *a_p;
944: char *key, *tmp;
945: int leng, idx_len;
946: leng = strlen(name->s_name)+8; /* [ ] */
947:
948: switch(index->s_type) {
949: case I_VAR:
950: case I_CONSTANT: tmp = (char *)capa_malloc(64,1);
951: sprintf(tmp,"%ld",index->s_int);
952: break;
953: case R_VAR:
954: case R_CONSTANT: tmp = (char *)capa_malloc(64,1);
955: sprintf(tmp,"%g",index->s_real);
956: break;
957: case S_VAR:
958: case S_CONSTANT: idx_len = strlen(index->s_str); tmp = (char *)capa_malloc(idx_len+4,1);
959: sprintf(tmp,"\"%s\"",index->s_str); /* string array index is a bit different from integer one */
960: break;
961: default: break;
962: }
963: idx_len = strlen(tmp);
964:
965: key = (char *)capa_malloc(idx_len+leng,1);
966: sprintf(key,"%s[%s]",name->s_name,tmp);
967:
968: a_p = find_arrayid(name->s_name); /* use the array name to search array tree */
1.8 albertel 969: /* did not check for error! */
1.1 albertel 970: s_p = find_array_by_index(a_p,key); /* use the index portion to search along array linked list */
971: capa_mfree((char *)tmp); capa_mfree((char *)key);
972:
973: if (free_symbols) { /* free both the name symbol and index symbol */
974: if( (index->s_type == I_CONSTANT) || (index->s_type == R_CONSTANT) )
975: capa_mfree((char *)index);
976: if(index->s_type == S_CONSTANT) {
977: capa_mfree(index->s_str); capa_mfree((char *)index);
978: }
979: capa_mfree(name->s_name); capa_mfree((char *)name);
980: }
981: return (s_p);
982: }
983:
984: Symbol * build_array_list(ar_name,num_elem)
985: Symbol *ar_name;int num_elem;
986: {
987: int i;
988: Symbol *arg_list,*a_p;
1.3 albertel 989: char idx_str[MAX_BUFFER_SIZE];
1.1 albertel 990:
1.3 albertel 991: a_p = find_arrayid(ar_name->s_name);
1.1 albertel 992: i = 1;
1.3 albertel 993: sprintf(idx_str,"%s[%d]",ar_name->s_name,i); /* create array elements with integer index */
1.1 albertel 994: arg_list = find_array_by_index(a_p,idx_str); /* will create a new element if not found */
995: arg_list->s_argc=1;
996: arg_list->s_argp=new_arglist(arg_list);
997:
998: for (i=2;i<=num_elem;i++) {
1.3 albertel 999: sprintf(idx_str,"%s[%d]",ar_name->s_name,i);
1.1 albertel 1000: arg_list->s_argc++;
1001: arg_list->s_argp=addto_arglist(arg_list->s_argp,find_array_by_index(a_p,idx_str));
1002: }
1003: return arg_list;
1004: }
1005:
1006:
1007:
1008:
1009:
1010:
1011:
1012: /* ------------------------------------------------------------- */
1013: void
1014: append_text(str) char *str;
1015: {
1016: char *q;
1017: int i;
1018:
1019: if (!LexiProblem_p->question) {
1020: if (!(q = capa_malloc(strlen(str)+1,1))) printf("No room to append.");
1021: strncpy(q,str,strlen(str)+1);
1022: } else {
1023: i = strlen(LexiProblem_p->question);
1024: i += (strlen(str)+1);
1025: q = capa_malloc(i,1); /* *** */
1026: if (!q) printf("No room to append().");
1027: strcat(strncpy(q,LexiProblem_p->question, strlen(LexiProblem_p->question)+1), str);
1028: capa_mfree(LexiProblem_p->question);
1029: }
1030: LexiProblem_p->question=q;
1031: }
1032:
1033: /******************************************************************************/
1034: /* ADD A STRING TO THE CURRENT HINT TEXT BLOCK */
1035: /******************************************************************************/
1036: void /* RETURNS: nothing */
1037: append_hint(str) /* ARGUMENTS: */
1038: char *str; /* String to add */
1039: { /* LOCAL VARIABLES: */
1040: char *q; /* New string */
1041:
1042: if (!LexiProblem_p->hint) {
1043: if (!(q = capa_malloc(strlen(str)+1,1)))
1044: printf("no room");
1045: strncpy(q,str,strlen(str)+1);
1046: } else {
1047: if (!(q = capa_malloc(strlen(LexiProblem_p->hint)+strlen(str)+1,1)))
1048: printf("no room");
1049: strcat(strncpy(q,LexiProblem_p->hint,strlen(LexiProblem_p->hint)), str);
1050: capa_mfree(LexiProblem_p->hint);
1051: }
1052: LexiProblem_p->hint=q;
1053: /* printf("APPEND HINT: %s\n", str); */
1054: }
1055: /******************************************************************************/
1056: /* ADD A STRING TO THE CURRENT EXPLAIN TEXT BLOCK */
1057: /******************************************************************************/
1058: void /* RETURNS: nothing */
1059: append_explain(str) /* ARGUMENTS: */
1060: char *str; /* String to add */
1061: { /* LOCAL VARIABLES: */
1062: char *q; /* New string */
1063:
1064: if (!LexiProblem_p->explain) {
1065: if (!(q = capa_malloc(strlen(str)+1,1)))
1066: printf("no room");
1067: strncpy(q,str, strlen(str)+1);
1068: } else {
1069: if (!(q = capa_malloc(strlen(LexiProblem_p->explain)+strlen(str)+1,1)))
1070: printf("no room");
1071: strcat(strncpy(q,LexiProblem_p->explain,strlen(LexiProblem_p->explain)+1), str);
1072: capa_mfree(LexiProblem_p->explain);
1073: }
1074: LexiProblem_p->explain=q;
1075: /* printf("APPEND EXPLAIN: %s\n", str); */
1076: }
1077:
1078: void
1079: append_error(str) char *str;
1080: {
1081: char *q;
1082: int i;
1083:
1084: ErrorMsg_count++;
1085: if (!ErrorMsg_p) {
1086: if (!(q = capa_malloc(strlen(str)+1,1))) printf("No room in append.");
1087: strncpy(q,str,strlen(str)+1);
1088: } else {
1089: i = strlen(ErrorMsg_p);
1090: i += (strlen(str)+1);
1091: q = capa_malloc(i,1); /* *** */
1092: if (!q) printf("No room in append()");
1093: strcat(strncpy(q,ErrorMsg_p, strlen(ErrorMsg_p)+1), str);
1094: capa_mfree(ErrorMsg_p);
1095: }
1096: ErrorMsg_p=q;
1097: /* printf("APPEND ERROR: %s\n", str); */
1098: }
1099: void
1100: append_warn(type,str) int type;char *str;
1101: {
1102: WarnMsg_t *p, *t;
1103: char *q;
1104:
1105: WarnMsg_count++;
1106: if (!WarnMsg_p) {
1107: if (!(p = (WarnMsg_t *)capa_malloc(sizeof(WarnMsg_t),1))) printf("No room in create WarnMsg_t.");
1108: if (!(q = capa_malloc(strlen(str)+1,1))) printf("No room in allocating space for warn msg.");
1109: strncpy(q,str,strlen(str)+1);
1110: p->warn_next = NULL;
1111: p->warn_type = type;
1112: p->warn_str = q;
1113: WarnMsg_p=p;
1114: } else {
1115: for(t=WarnMsg_p;t->warn_next;t=t->warn_next) { } /* do nothing within for loop */
1116: if (!(p = (WarnMsg_t *)capa_malloc(sizeof(WarnMsg_t),1))) printf("No room in create WarnMsg_t.");
1117: if (!(q = capa_malloc(strlen(str)+1,1))) printf("No room in allocating space for warn msg.");
1118: strncpy(q,str,strlen(str)+1);
1119: p->warn_next = NULL;
1120: p->warn_type = type;
1121: p->warn_str = q;
1122: t->warn_next = p;
1123: }
1124: }
1125:
1126: /*****************************************************************************/
1127: /*********** if *b is a constant symbol, destroy (free) b ********************/
1128: /*********** if *a is a var symbol, create a new symbol **********************/
1129: /* do not free(*a) */
1.7 albertel 1130: /* If either a or b is invalid it propagates the error up the parse tree */
1.1 albertel 1131: Symbol *
1132: symbols_op(a, b, op) Symbol *a; Symbol *b; int op;
1133: {
1134: int type, new, leng;
1135: long tmp_i, tmp_j;
1136: double tmp_p, tmp_q;
1137: char a_str[QUARTER_K], *b_str=NULL, *r_strp;
1138: char warn_msg[ONE_K];
1139: Symbol *a_symp;
1140:
1141: if( a->s_type == IDENTIFIER || b->s_type == IDENTIFIER ) {
1142: if(a->s_type == IDENTIFIER) { /* a is IDENTIFIER */
1143: sprintf(warn_msg,"var \"%s\" not defined before use.\n", a->s_name);
1144: capa_msg(MESSAGE_ERROR,warn_msg);
1.7 albertel 1145: return (a);
1.1 albertel 1146: } else { /* b is IDENTIFIER */
1.7 albertel 1147: sprintf(warn_msg,"var \"%s\" not defined before use.\n",b->s_name);
1.1 albertel 1148: capa_msg(MESSAGE_ERROR,warn_msg);
1.7 albertel 1149: return (b);
1.1 albertel 1150: }
1151: } else { /* a and b are neither identifiers */
1152: if( (a->s_type == I_VAR) ||
1153: (a->s_type == R_VAR) ||
1154: (a->s_type == S_VAR) ) {
1155: a_symp = (Symbol *)capa_malloc(sizeof(Symbol),1); /* *** */
1156: new = 1;
1157: } else {
1158: new = 0;
1159: a_symp = a; /* re-use symbol *a */
1160: }
1161: if( ((a->s_type == I_CONSTANT)||(a->s_type == I_VAR)) &&
1162: ((b->s_type == I_CONSTANT)||(b->s_type == I_VAR)) ) { /* both a and b are integer */
1163: type = I_CONSTANT;
1164: switch( op ) {
1165: case ADD_op: a_symp->s_int = a->s_int + b->s_int ; break;
1166: case SUB_op: a_symp->s_int = a->s_int - b->s_int ; break;
1167: case MUL_op: a_symp->s_int = a->s_int * b->s_int ; break;
1168: case DIV_op: if(b->s_int != 0) {
1169: a_symp->s_int = a->s_int / b->s_int ;
1170: } else {
1171: sprintf(warn_msg,"division (/) by zero!\n");
1172: capa_msg(MESSAGE_ERROR,warn_msg);
1173: } break;
1174: case IDIV_op: if(b->s_int != 0) {
1175: a_symp->s_int = (a->s_int % b->s_int );
1176: } else {
1177: sprintf(warn_msg,"integer division (%%) by zero!\n");
1178: capa_msg(MESSAGE_ERROR,warn_msg);
1179: } break;
1180: case EQ_op: a_symp->s_int = ((a->s_int == b->s_int)? 1: 0); break;
1181: case NE_op: a_symp->s_int = ((a->s_int == b->s_int)? 0: 1); break;
1182: case GT_op: a_symp->s_int = ((a->s_int > b->s_int)? 1: 0); break;
1183: case GE_op: a_symp->s_int = ((a->s_int >= b->s_int)? 1: 0); break;
1184: case LT_op: a_symp->s_int = ((a->s_int < b->s_int)? 1: 0); break;
1185: case LE_op: a_symp->s_int = ((a->s_int <= b->s_int)? 1: 0); break;
1186: case AND_op: a_symp->s_int = ((a->s_int && b->s_int)? 1: 0); break;
1187: case OR_op: a_symp->s_int = ((a->s_int || b->s_int)? 1: 0); break;
1188: }
1189: } else { /* a, b neither are integers */
1190: if( (a->s_type == S_VAR) || (a->s_type == S_CONSTANT) ||
1191: (b->s_type == S_VAR) || (b->s_type == S_CONSTANT) ) { /* either a or b is a string */
1192: type = S_CONSTANT; /* the return type is a string */
1193: if( (a->s_type == S_VAR) || (a->s_type == S_CONSTANT) ) { /* a is a string */
1.4 albertel 1194: if (a->s_str == NULL ||
1195: (((b->s_type == S_VAR) || (b->s_type == S_CONSTANT)) && b->s_str == NULL)) {
1196: if (a->s_str == NULL) {
1197: sprintf(warn_msg,"variable %s has not yet been assigned a value.\n",a->s_name);
1198: capa_msg(MESSAGE_ERROR,warn_msg);
1199: }
1200: if (((b->s_type == S_VAR) || (b->s_type == S_CONSTANT)) && b->s_str == NULL) {
1201: sprintf(warn_msg,"variable %s has not yet been assigned a value.\n",a->s_name);
1202: capa_msg(MESSAGE_ERROR,warn_msg);
1203: }
1204: } else { /* a is a valid string */
1205: switch( b->s_type ) {
1206: case I_VAR:
1207: case I_CONSTANT:
1208: leng = SMALL_LINE_BUFFER; /* assuming a long integer does not exceed 128 digits*/
1209: b_str= capa_malloc(sizeof(char), leng);
1210: sprintf(b_str,"%ld", b->s_int);
1211: break;
1212: case R_VAR:
1213: case R_CONSTANT:
1214: leng = SMALL_LINE_BUFFER;/*assuming a double does not exceed128chars*/
1215: b_str= capa_malloc(sizeof(char), leng);
1216: sprintf(b_str,"%.15g", b->s_real);
1217: break;
1218: case S_VAR:
1219: case S_CONSTANT: /* DONE: get rid of limitations on b_str[] */
1220: leng = strlen( b->s_str ) + 1;
1221: b_str= capa_malloc(sizeof(char), leng);
1222: sprintf(b_str,"%s",b->s_str);
1223: /*if(b->s_type == S_CONSTANT) capa_mfree(b->s_str);*/
1224: break;
1225: }
1226: switch( op ) {
1227: case ADD_op:
1228: leng = strlen( a->s_str ) + strlen(b_str) + 1;
1229: r_strp = capa_malloc(sizeof(char), leng); /* **** */
1230: strcat(r_strp, a->s_str);
1231: strcat(r_strp, b_str); /* concatenate two strings together */
1232: if( !new ) capa_mfree(a->s_str);
1233: a_symp->s_str = r_strp;
1234: break;
1235: case SUB_op:
1236: case MUL_op:
1237: case DIV_op:
1238: case IDIV_op:
1239: if( !new ) capa_mfree(a->s_str);
1240: a_symp->s_str = strsave("<<Op NOT DEFINED>>");
1241: sprintf(warn_msg,"integer division (%%) cannot accept string operand!\n");
1242: capa_msg(MESSAGE_ERROR,warn_msg);
1243: break;
1244: case EQ_op: a_symp->s_int = (strcmp(a->s_str, b_str) == 0? 1: 0);
1245: type = I_CONSTANT; break;
1246: case NE_op: a_symp->s_int = (strcmp(a->s_str, b_str) == 0? 0: 1);
1247: type = I_CONSTANT; break;
1248: case GT_op: a_symp->s_int = (strcmp(a->s_str, b_str) > 0? 1: 0);
1249: type = I_CONSTANT; break;
1250: case GE_op: a_symp->s_int = (strcmp(a->s_str, b_str) >= 0? 1: 0);
1251: type = I_CONSTANT; break;
1252: case LT_op: a_symp->s_int = (strcmp(a->s_str, b_str) < 0? 1: 0);
1253: type = I_CONSTANT; break;
1254: case LE_op: a_symp->s_int = (strcmp(a->s_str, b_str) <= 0? 1: 0);
1255: type = I_CONSTANT; break;
1256: case AND_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: case OR_op:
1264: if( (a->s_str[0] != 0) || (b_str[0] != 0)) {
1265: a_symp->s_int = 1;
1266: } else {
1267: a_symp->s_int = 0;
1268: }
1269: type = I_CONSTANT; break;
1270: }
1271: }
1.1 albertel 1272: if (b_str!=NULL) capa_mfree(b_str);
1273: } else { /* b is string and a is either integer or real */
1274: switch( a->s_type ) {
1275: case I_VAR:
1276: case I_CONSTANT:
1277: sprintf(a_str,"%ld", a->s_int); break;
1278: case R_VAR:
1279: case R_CONSTANT:
1280: sprintf(a_str,"%.15g", a->s_real); break;
1281: }
1282: switch( op ) {
1283: case ADD_op:
1284: leng = strlen( b->s_str ) + strlen(a_str) + 1;
1285: r_strp = capa_malloc(sizeof(char), leng); /* *** */
1286: strcat(r_strp, a_str);
1287: strcat(r_strp, b->s_str);
1288: /*if( b->s_type == S_CONSTANT ) capa_mfree(b->s_str);*/
1289: a_symp->s_str = r_strp; break;
1290: case SUB_op:
1291: case MUL_op:
1292: case DIV_op:
1293: case IDIV_op:
1294: a_symp->s_str = strsave("<<Op NOT DEFINED>>");
1295: sprintf(warn_msg,"integer division (%%) cannot accept string operand!\n");
1296: capa_msg(MESSAGE_ERROR,warn_msg);
1297: break;
1298: case EQ_op: a_symp->s_int = (strcmp(a_str, b->s_str) == 0? 1: 0);
1299: type = I_CONSTANT; break;
1300: case NE_op: a_symp->s_int = (strcmp(a_str, b->s_str) == 0? 0: 1);
1301: type = I_CONSTANT; break;
1302: case GT_op: a_symp->s_int = (strcmp(a_str, b->s_str) > 0? 1: 0);
1303: type = I_CONSTANT; break;
1304: case GE_op: a_symp->s_int = (strcmp(a_str, b->s_str) >= 0? 1: 0);
1305: type = I_CONSTANT; break;
1306: case LT_op: a_symp->s_int = (strcmp(a_str, b->s_str) < 0? 1: 0);
1307: type = I_CONSTANT; break;
1308: case LE_op: a_symp->s_int = (strcmp(a_str,b->s_str) <= 0? 1: 0);
1309: type = I_CONSTANT; break;
1310: case AND_op: if( (a_str[0] != 0) && (b->s_str[0] != 0)) {
1311: a_symp->s_int = 1;
1312: } else {
1313: a_symp->s_int = 0;
1314: }
1315: type = I_CONSTANT; break;
1316: case OR_op: if( (a_str[0] != 0) || (b_str[0] != 0)) {
1317: a_symp->s_int = 1;
1318: } else {
1319: a_symp->s_int = 0;
1320: }
1321: type = I_CONSTANT; break;
1322: }
1323: }
1324:
1325: } else { /* both a and b are real */
1326: type = R_CONSTANT;
1327: if( (a->s_type == R_CONSTANT)||(a->s_type == R_VAR) ) {
1328: tmp_p = a->s_real;
1329: } else {
1330: tmp_p = (double)a->s_int;
1331: }
1332: if( (b->s_type == R_CONSTANT)||(b->s_type == R_VAR) ) {
1333: tmp_q = b->s_real;
1334: } else {
1335: tmp_q = (double)b->s_int;
1336: }
1337: switch( op ) {
1338: case ADD_op: a_symp->s_real = tmp_p + tmp_q ; break;
1339: case SUB_op: a_symp->s_real = tmp_p - tmp_q ; break;
1340: case MUL_op: a_symp->s_real = tmp_p * tmp_q ; break;
1341: case DIV_op: if(tmp_q != 0.0) {
1342: a_symp->s_real = tmp_p / tmp_q ;
1343: } else {
1344: /* printf("FDIVISION by ZERO\n"); */
1345: sprintf(warn_msg,"division (/) by zero!\n");
1346: capa_msg(MESSAGE_ERROR,warn_msg);
1347: }
1348: break;
1349: case IDIV_op: if(tmp_q != 0.0 ) {
1350: tmp_i = (long)tmp_p;
1351: tmp_j = (long)tmp_q;
1352: a_symp->s_int = tmp_i % tmp_j;
1353: type = I_CONSTANT;
1354: } else {
1355: /* printf("DIVISION by ZERO\n"); */
1356: sprintf(warn_msg,"division (/) by zero!\n");
1357: capa_msg(MESSAGE_ERROR,warn_msg);
1358: }
1359: break;
1360: case EQ_op: type = I_CONSTANT;
1361: a_symp->s_int = ((tmp_p == tmp_q)? 1: 0); break;
1362: case NE_op: type = I_CONSTANT;
1363: a_symp->s_int = ((tmp_p == tmp_q)? 0: 1); break;
1364: case GT_op: type = I_CONSTANT;
1365: a_symp->s_int = ((tmp_p > tmp_q)? 1: 0); break;
1366: case GE_op: type = I_CONSTANT;
1367: a_symp->s_int = ((tmp_p >= tmp_q)? 1: 0); break;
1368: case LT_op: type = I_CONSTANT;
1369: a_symp->s_int = ((tmp_p < tmp_q)? 1: 0); break;
1370: case LE_op: type = I_CONSTANT;
1371: a_symp->s_int = ((tmp_p <= tmp_q)? 1: 0); break;
1372: case AND_op: type = I_CONSTANT;
1373: a_symp->s_int = ((tmp_p && tmp_q)? 1: 0); break;
1374: case OR_op: type = I_CONSTANT;
1375: a_symp->s_int = ((tmp_p || tmp_q)? 1: 0); break;
1376: }
1377: }
1378: }
1379: if( (b->s_type == I_CONSTANT) ||
1380: (b->s_type == R_CONSTANT) ) capa_mfree((char *)b); /* free symbol *b only */
1381: if( (b->s_type == S_CONSTANT) ) {
1382: capa_mfree((char *)b->s_str);
1383: capa_mfree((char *)b);
1384: }
1385: a_symp->s_type = type;
1386: return (a_symp);
1387: }
1388: }
1389:
1390: /* ------------------------------------------------------ */
1391: char *
1392: format_toTeX( real ) char *real;
1393: {
1394: int idx, length, fraclength, i_exp;
1.3 albertel 1395: char *expo_p, fracS[SMALL_LINE_BUFFER], result[ONE_K], *areal;
1.1 albertel 1396: char warn_msg[WARN_MSG_LENGTH];
1397:
1398: length = strlen(real);
1399: if( index( real, 'e' ) == NULL ) {
1400: if( index( real, 'E' ) == NULL ) {
1401: sprintf(result,"%s", real);
1402: } else {
1403: expo_p = index(real, 'E'); /*** hpux complained */
1404: fraclength = length - strlen(expo_p);
1405: expo_p++; if(expo_p[0] == '+') expo_p++;
1406: sscanf(expo_p,"%d",&i_exp);
1407: for(idx=0;idx<fraclength;idx++) fracS[idx] = real[idx];
1408: fracS[fraclength] = 0;
1409: if(i_exp == 0 ) {
1410: sprintf(result,"$%s$", fracS);
1411: } else {
1412: sprintf(result,"$%s \\times 10^{%d}$", fracS, i_exp);
1413: }
1414: }
1415: } else {
1416: if( index( real, 'E' ) == NULL ) {
1417: expo_p = index(real, 'e'); /*** hpux complained */
1418: fraclength = length - strlen(expo_p);
1419: expo_p++; if(expo_p[0] == '+') expo_p++;
1420: sscanf(expo_p,"%d",&i_exp);
1421: for(idx=0;idx<fraclength;idx++) fracS[idx] = real[idx];
1422: fracS[fraclength] = 0;
1423: if(i_exp == 0 ) {
1424: sprintf(result,"$%s$", fracS);
1425: } else {
1426: sprintf(result,"$%s \\times 10^{%d}$", fracS, i_exp);
1427: }
1428: } else {
1429: sprintf(result,"<<Ill-formed REAL>>");
1430: sprintf(warn_msg,"number %s is not a valid real number!\n",real);
1431: capa_msg(MESSAGE_ERROR,warn_msg);
1432: }
1433: }
1434: areal = (char *) capa_malloc(strlen(result)+1, 1);
1435: strcpy(areal,result);
1436: return (areal);
1437: }
1438: /* ------------------------------------------------------ */
1439: char *
1440: format_toHTML( real ) char *real;
1441: {
1442: int idx, length, fraclength, i_exp;
1.3 albertel 1443: char *expo_p, fracS[SMALL_LINE_BUFFER], result[ONE_K], *areal;
1.1 albertel 1444: char warn_msg[WARN_MSG_LENGTH];
1445:
1446: length = strlen(real);
1447: if( index( real, 'e' ) == NULL ) {
1448: if( index( real, 'E' ) == NULL ) {
1449: sprintf(result,"%s", real);
1450: } else {
1451: expo_p = index(real, 'E'); /*** hpux complained */
1452: fraclength = length - strlen(expo_p);
1453: expo_p++; if(expo_p[0] == '+') expo_p++;
1454: sscanf(expo_p,"%d",&i_exp);
1455: for(idx=0;idx<fraclength;idx++) fracS[idx] = real[idx];
1456: fracS[fraclength] = 0;
1457: if(i_exp == 0 ) {
1458: sprintf(result,"%s", fracS);
1459: } else {
1460: sprintf(result,"%s×10<sup>%d</sup>", fracS, i_exp); /* × is code for x */
1461: }
1462: }
1463: } else { /* the string contains 'e' char */
1464: if( index( real, 'E' ) == NULL ) {
1465: expo_p = index(real, 'e'); /*** hpux complained */
1466: fraclength = length - strlen(expo_p);
1467: expo_p++; if(expo_p[0] == '+') expo_p++;
1468: sscanf(expo_p,"%d",&i_exp);
1469: for(idx=0;idx<fraclength;idx++) fracS[idx] = real[idx];
1470: fracS[fraclength] = 0;
1471: if(i_exp == 0 ) {
1472: sprintf(result,"%s", fracS);
1473: } else {
1474: sprintf(result,"%s×10<sup>%d</sup>", fracS, i_exp); /* × is code for x */
1475: }
1476: } else {
1477: sprintf(result,"<<Ill-formed REAL>>");
1478: sprintf(warn_msg,"number %s is not a valid real number!\n",real);
1479: capa_msg(MESSAGE_ERROR,warn_msg);
1480: }
1481: }
1482: areal = (char *) capa_malloc(strlen(result)+1, 1);
1483: strcpy(areal,result);
1484: return (areal);
1485: }
1486: /* -- This routine is called when a /ANS is encountered -- */
1487: void
1488: init_answerinfo()
1489: {
1490:
1491: CurrAnsInfo.ans_str = NULL;
1492: CurrAnsInfo.ans_type = 0;
1493: CurrAnsInfo.ans_calc = CALC_DEFAULT;
1494: CurrAnsInfo.ans_tol_type = TOL_ABSOLUTE;
1495: CurrAnsInfo.ans_tol = TOL_DEFAULT;
1496: CurrAnsInfo.ans_sig_ub = SIG_UB_DEFAULT;
1497: CurrAnsInfo.ans_sig_lb = SIG_LB_DEFAULT;
1498: CurrAnsInfo.ans_id_list = NULL;
1499: CurrAnsInfo.ans_pts_list = NULL;
1500: CurrAnsInfo.ans_fmt[0] = '\0';
1501: CurrAnsInfo.ans_unit_str[0] = '\0';
1502: CurrAnsInfo.ans_unit = NULL;
1503: CurrAnsInfo.ans_next = NULL;
1504: }
1505: /* when encountered a /DIS(variable) */
1506: void
1507: display_var( s )Symbol *s;
1508: {
1509: char *aline;
1510: char *tmp_p;
1511: char warn_msg[WARN_MSG_LENGTH];
1512:
1513:
1514: switch(s->s_type) {
1515: case IDENTIFIER:
1516: aline = (char *)capa_malloc(sizeof(char)*ONE_K,1);
1517: sprintf(aline,"VAR \"%s\" NOT DEFINED!", s->s_name);
1518: sprintf(warn_msg,"display var \"%s\" not defined before use.\n",s->s_name);
1519: capa_msg(MESSAGE_ERROR,warn_msg);
1520: break;
1521: case I_VAR: case I_CONSTANT:
1522: aline = (char *)capa_malloc(sizeof(char)*ONE_K,1);
1523: sprintf(aline, "%ld", s->s_int);
1524: break;
1525: case R_VAR: case R_CONSTANT:
1526: aline = (char *)capa_malloc(sizeof(char)*ONE_K,1);
1527: if(Parsemode_f == TeX_MODE) {
1528: if(s->s_distype == DEFAULT_FORMAT ) {
1529: sprintf(aline,"%.15g",s->s_real);
1530: } else {
1531: sprintf(aline,s->s_format,s->s_real);
1532: }
1533: tmp_p = format_toTeX(aline);
1534: sprintf(aline,"%s",tmp_p);
1535: capa_mfree( (char *)tmp_p);
1536:
1537: } else {
1538: if(Parsemode_f == HTML_MODE ) {
1539: if(s->s_distype == DEFAULT_FORMAT ) {
1540: sprintf(aline,"%.15g",s->s_real);
1541: } else {
1542: sprintf(aline,s->s_format,s->s_real);
1543: }
1544: tmp_p = format_toHTML(aline);
1545: sprintf(aline,"%s",tmp_p);
1546: capa_mfree( (char *)tmp_p);
1547: } else {
1548: if(s->s_distype == DEFAULT_FORMAT ) {
1549: sprintf(aline,"%.15g",s->s_real);
1550: } else {
1551: sprintf(aline,s->s_format,s->s_real);
1552: }
1553: }
1554: }
1555: break;
1.4 albertel 1556: case S_VAR: case S_CONSTANT:
1557: if (s->s_str == NULL) {
1558: sprintf(warn_msg,"variable %s has not yet been assigned a value.\n",
1559: s->s_name);
1560: capa_msg(MESSAGE_ERROR,warn_msg);
1561: aline=(char *)capa_malloc(9,1);
1562: sprintf(aline,"NO VALUE");
1563: } else {
1564: aline = (char *)capa_malloc(strlen(s->s_str)+1,1);
1565: sprintf(aline,"%s",s->s_str);
1566: }
1.1 albertel 1567: break;
1568: }
1569: append_text(aline);
1570: capa_mfree((char *)aline);
1.4 albertel 1571: if(s->s_format) { capa_mfree((char *)s->s_format); }
1.1 albertel 1572: s->s_format = NULL;
1573: switch(s->s_type) { /* free up spaces taken by constants */
1574: case I_CONSTANT:
1575: case R_CONSTANT: capa_mfree((char *)s); break;
1576: case S_CONSTANT: capa_mfree(s->s_str); capa_mfree((char *)s); break;
1577: default: break;
1578: }
1579:
1580: }
1581:
1582: /* Assign the correct answer to CurrAnsInfo first */
1583: void
1584: assign_answer( s ) Symbol *s;
1585: {
1586: char aline[QUARTER_K];
1587: char warn_msg[WARN_MSG_LENGTH];
1588:
1589: /*problem_default(LexiProblem_p);*/
1590: switch(s->s_type) {
1591: case IDENTIFIER:
1592: sprintf(warn_msg,"File %s, Line %3d: in /ANS, var %s not defined before use.\n",
1593: Opened_filename[Input_idx],Current_line[Input_idx],s->s_name);
1594: capa_msg(MESSAGE_ERROR,warn_msg);
1595: CurrAnsInfo.ans_str = strsave("ANSWER NOT DEFINED!");
1596: CurrAnsInfo.ans_type = ANSWER_IS_STRING_CI;
1597: sprintf(CurrAnsInfo.ans_fmt,"%%s");
1598: if (CurrAnsInfo.ans_tol == 0.0) {
1599: sprintf(warn_msg, "File %s, Line %3d: answer has a numerical value of %ld and an implicit zero tolerance.\n",
1600: Opened_filename[Input_idx],Current_line[Input_idx],s->s_int);
1601: capa_msg(MESSAGE_WARN,warn_msg);
1602: }
1603: break;
1604: case I_VAR: case I_CONSTANT:
1605: sprintf(aline, "%ld", s->s_int);
1606: CurrAnsInfo.ans_str = strsave(aline);
1607: CurrAnsInfo.ans_type = ANSWER_IS_INTEGER;
1608: sprintf(CurrAnsInfo.ans_fmt,"%%ld");
1609: break;
1610: case R_VAR: case R_CONSTANT:
1611: if(s->s_distype == DEFAULT_FORMAT ) {
1612: sprintf(aline,"%.15g",s->s_real);
1613: sprintf(CurrAnsInfo.ans_fmt,"%%.15g");
1614: } else {
1615: sprintf(aline,"%.15g",s->s_real);
1616: strcpy(CurrAnsInfo.ans_fmt,s->s_format);
1617: }
1618: CurrAnsInfo.ans_str = strsave(aline);
1619: CurrAnsInfo.ans_type = ANSWER_IS_FLOAT;
1620: if( CurrAnsInfo.ans_tol == 0.0 ) {
1621: sprintf(warn_msg,"File %s, Line %3d: answer has a numerical value of %s and a zero tolerance.\n",
1622: Opened_filename[Input_idx],Current_line[Input_idx],aline);
1623: capa_msg(MESSAGE_WARN,warn_msg);
1624: }
1625: break;
1626: case S_VAR: case S_CONSTANT:
1627: CurrAnsInfo.ans_str = strsave(s->s_str);
1628: if (s->s_str!=NULL && (strlen(s->s_str)>ANSWER_STRING_LENG-1)) {
1629: sprintf(warn_msg,"File %s, Line %3d: answer is too long, max allowed length is %d, current answer is %d\n",
1630: Opened_filename[Input_idx],Current_line[Input_idx],
1631: ANSWER_STRING_LENG-1, strlen(s->s_str));
1632: capa_msg(MESSAGE_ERROR,warn_msg);
1633: CurrAnsInfo.ans_str[ANSWER_STRING_LENG-1]='\0';
1634: }
1635: if ( !CurrAnsInfo.ans_type ) { /* not yet specified by str= answer info */
1636: CurrAnsInfo.ans_type = ANSWER_IS_STRING_CI;
1637: }
1638: sprintf(CurrAnsInfo.ans_fmt,"%%s");
1639: break;
1640: }
1641: if(s->s_format) {
1642: capa_mfree((char *)s->s_format);
1643: }
1644: s->s_format = NULL;
1645: switch(s->s_type) {
1646: case I_CONSTANT:
1647: case R_CONSTANT: capa_mfree((char *)s); break;
1648: case S_CONSTANT: capa_mfree(s->s_str); capa_mfree((char *)s); break;
1649: default: break;
1650: }
1651:
1652: }
1653:
1654: /* Assign tolerance to CurrAnsInfo first */
1655: void
1656: assign_tolerance(tol_type, s) int tol_type; Symbol *s;
1657: {
1658: char warn_msg[WARN_MSG_LENGTH];
1659:
1660: CurrAnsInfo.ans_tol_type = tol_type;
1661: switch( s->s_type ) {
1662: case IDENTIFIER:
1663: sprintf(warn_msg,"TOL = var, \"%s\" not defined before use.\n",s->s_name);
1664: capa_msg(MESSAGE_ERROR,warn_msg);
1665: CurrAnsInfo.ans_tol = 0.0;
1666: break;
1667: case I_VAR: case I_CONSTANT:
1668: CurrAnsInfo.ans_tol =(double)s->s_int;
1669: break;
1670: case R_VAR: case R_CONSTANT:
1671: CurrAnsInfo.ans_tol = s->s_real;
1672: break;
1673: case S_VAR: case S_CONSTANT: CurrAnsInfo.ans_tol = 0.0;
1674: break;
1675: }
1676: free_calc_expr(s);
1677: }
1678:
1679: /* Problem weight is per problem based */
1680: void
1681: assign_weight( s ) Symbol *s;
1682: { char warn_msg[WARN_MSG_LENGTH];
1683: YYDBUG_PR1(" weight = identifier\n");
1684: switch( s->s_type ) {
1685: case IDENTIFIER:
1686: sprintf(warn_msg,"WGT = var, \"%s\" not defined before use.\n", s->s_name);
1687: capa_msg(MESSAGE_ERROR,warn_msg);
1688: LexiProblem_p->weight = WEIGHT_DEFAULT;
1689: break;
1690: case I_VAR: case I_CONSTANT:
1691: if( s->s_int < 0 ) {
1692: sprintf(warn_msg,"WGT = %ld, weight cannot be less than zero.\n", s->s_int);
1693: capa_msg(MESSAGE_ERROR,warn_msg);
1694: LexiProblem_p->weight = WEIGHT_DEFAULT;
1695: } else {
1696: LexiProblem_p->weight = s->s_int;
1697: }
1698: break;
1699: case R_VAR: case R_CONSTANT:
1700: if( s->s_real < 0.0 ) {
1701: sprintf(warn_msg,"WGT = %g, weight cannot be less than zero.\n", s->s_real);
1702: capa_msg(MESSAGE_ERROR,warn_msg);
1703: LexiProblem_p->weight = WEIGHT_DEFAULT;
1704: } else {
1705: LexiProblem_p->weight = (int)(s->s_real);
1706: }
1707: break;
1708: case S_VAR: case S_CONSTANT: LexiProblem_p->weight = WEIGHT_DEFAULT; break;
1709: }
1710: free_calc_expr(s);
1711: }
1712: /* Answer try limit is per problem based */
1713: void
1714: assign_try_limits( s ) Symbol *s;
1715: { char warn_msg[WARN_MSG_LENGTH];
1716: switch( s->s_type ) {
1717: case IDENTIFIER:
1718: sprintf(warn_msg,"TRY = var, \"%s\" not defined before use.\n",s->s_name);
1719: capa_msg(MESSAGE_ERROR,warn_msg);
1720: LexiProblem_p->tries = MAX_TRIES;
1721: break;
1722: case I_VAR: case I_CONSTANT:
1723: if(s->s_int <= 0) {
1724: sprintf(warn_msg,"TRIES = %ld, tries cannot be less than or equal to zero.\n",s->s_int);
1725: capa_msg(MESSAGE_ERROR,warn_msg);
1726: LexiProblem_p->tries = MAX_TRIES;
1727: } else {
1728: LexiProblem_p->tries = s->s_int;
1729: }
1730: break;
1731: case R_VAR: case R_CONSTANT:
1732: if(s->s_real <= 0.0) {
1733: sprintf(warn_msg,"TRIES = %g, tries cannot be less than or equal to zero.\n",s->s_real);
1734: capa_msg(MESSAGE_ERROR,warn_msg);
1735: LexiProblem_p->tries = MAX_TRIES;
1736: } else {
1737: LexiProblem_p->tries = (int)(s->s_real);
1738: }
1739: break;
1740: case S_VAR: case S_CONSTANT: LexiProblem_p->tries = MAX_TRIES; break;
1741: }
1742: free_calc_expr(s);
1743: }
1744: /* Answer hint is per problem based */
1745: void
1746: assign_hint( s ) Symbol *s;
1747: { char warn_msg[WARN_MSG_LENGTH];
1748:
1749: switch( s->s_type ) {
1750: case IDENTIFIER:
1751: sprintf(warn_msg,"HINT = var, \"%s\" not defined before use.\n", s->s_name);
1752: capa_msg(MESSAGE_ERROR,warn_msg);
1753: LexiProblem_p->show_hint = SHOW_HINT_DEFAULT;
1754: break;
1755: case I_VAR: case I_CONSTANT:
1756: if( s->s_int < 0 ) {
1757: sprintf(warn_msg,"HINT = %ld, show hint cannot be less than zero.\n", s->s_int);
1758: capa_msg(MESSAGE_ERROR,warn_msg);
1759: LexiProblem_p->show_hint = SHOW_HINT_DEFAULT;
1760: } else {
1761: LexiProblem_p->show_hint = s->s_int;
1762: }
1763: break;
1764: case R_VAR: case R_CONSTANT:
1765: if( s->s_real < 0.0 ) {
1766: sprintf(warn_msg,"HINT = %g, show hint cannot be less than zero.\n", s->s_real);
1767: capa_msg(MESSAGE_ERROR,warn_msg);
1768: LexiProblem_p->show_hint = SHOW_HINT_DEFAULT;
1769: } else {
1770: LexiProblem_p->weight = (int)(s->s_real);
1771: }
1772: break;
1773: case S_VAR: case S_CONSTANT: LexiProblem_p->show_hint = SHOW_HINT_DEFAULT; break;
1774: }
1775: free_calc_expr(s);
1776: }
1777:
1778: /* Assign answer units string to CurrAnsInfo first */
1779: void
1780: assign_units( s ) Symbol *s;
1781: {
1782: char symb_str[ONE_TWO_EIGHT];
1783: char warn_msg[WARN_MSG_LENGTH];
1784:
1785: switch( s->s_type ) {
1786: case IDENTIFIER:
1787: sprintf(warn_msg,"UNIT = var, \"%s\" not defined before use.\n", s->s_name);
1788: capa_msg(MESSAGE_ERROR,warn_msg);
1789: break;
1790: case I_VAR: case I_CONSTANT:
1791: sprintf(warn_msg,"UNIT = %ld, unit cannot be a number.\n", s->s_int);
1792: capa_msg(MESSAGE_ERROR,warn_msg);
1793: break;
1794: case R_VAR: case R_CONSTANT:
1795: sprintf(warn_msg,"UNIT = %g, unit cannot be a number.\n", s->s_real);
1796: capa_msg(MESSAGE_ERROR,warn_msg);
1797: break;
1798: case S_VAR: case S_CONSTANT:
1799: strcpy(symb_str,s->s_str);
1800: strcpy(CurrAnsInfo.ans_unit_str,symb_str);
1801: CurrAnsInfo.ans_unit = u_parse_unit(symb_str);
1802: if (gUnitError) {
1803: sprintf(warn_msg,"Error in unit specified: %s\n",symb_str);
1804: capa_msg(MESSAGE_ERROR,warn_msg);
1805: }
1806: break;
1807: }
1808: }
1809: void
1810: assign_sigs( lb, ub ) int lb; int ub;
1811: {
1812: CurrAnsInfo.ans_sig_lb = lb;
1813: CurrAnsInfo.ans_sig_ub = ub;
1814: }
1815:
1816: void
1817: assign_id_list( s ) Symbol *s;
1818: {
1819: char warn_msg[WARN_MSG_LENGTH];
1820:
1821: switch( s->s_type ) {
1822: case IDENTIFIER:
1823: sprintf(warn_msg,"Eval = < ID @ Pts >, \"%s\" not defined before use.\n", s->s_name);
1824: capa_msg(MESSAGE_ERROR,warn_msg);
1825: break;
1826: case I_VAR: case I_CONSTANT:
1827: sprintf(warn_msg,"Eval = < %ld @ Pts >, ID cannot be a number.\n", s->s_int);
1828: capa_msg(MESSAGE_ERROR,warn_msg);
1829: break;
1830: case R_VAR: case R_CONSTANT:
1831: sprintf(warn_msg,"Eval = < %.16g @ Pts >, ID cannot be a number.\n", s->s_real);
1832: capa_msg(MESSAGE_ERROR,warn_msg);
1833: break;
1834: case S_VAR: case S_CONSTANT:
1835: CurrAnsInfo.ans_id_list = strsave(s->s_str);
1836: break;
1.6 albertel 1837: }
1838: }
1839:
1.8 albertel 1840: /* void assign_pts ( Symbol* coord1, Symbol* coord2, Symbol* num) { */
1841: void assign_pts (coord1, coord2, num)Symbol *coord1;Symbol *coord2;Symbol *num;
1842: {
1.6 albertel 1843: PointsList_t *pt;
1844: if( LastPtsList != NULL ) {
1845: LastPtsList->pts_next = gen_ptslist( coord1, coord2, num );
1846: pt = LastPtsList->pts_next;
1847: while( pt->pts_next != NULL ) {
1848: pt = pt->pts_next;
1849: }
1850: LastPtsList = pt;
1851: } else {
1852: CurrPtsList = gen_ptslist( coord1, coord2, num );
1853: LastPtsList = CurrPtsList;
1854: }
1855: if(coord1->s_type == S_CONSTANT) {
1856: capa_mfree(coord1->s_str); capa_mfree((char *)coord1);
1857: }
1858: if(coord2->s_type == S_CONSTANT) {
1859: capa_mfree(coord2->s_str); capa_mfree((char *)coord2);
1860: }
1861: if(num->s_type == I_CONSTANT || num->s_type == R_CONSTANT) {
1862: capa_mfree((char *)num);
1.1 albertel 1863: }
1864: }
1865:
1866: /* =========================================================================== */
1867:
1868:
1869:
1870:
1871:
1872:
1873: /* =========================================================================== */
1874:
1875: void start_question_over()
1876: {
1877: free_problems(LexiProblem_p);
1878: LexiProblem_p = (Problem_t *) capa_malloc(sizeof(Problem_t),1);
1879: problem_default(LexiProblem_p);
1880: begin_question();
1881: }
1882:
1883: void
1884: init_new_prob()
1885: {
1886: if (LastProblem_p) {
1887: LastProblem_p->next = LexiProblem_p;
1888: } else {
1889: FirstProblem_p = LexiProblem_p;
1890: }
1891: LastProblem_p = LexiProblem_p;
1892: Lexi_qnum++;
1893: LexiProblem_p = (Problem_t *) capa_malloc(sizeof(Problem_t),1); /* *** */
1894: problem_default(LexiProblem_p);
1895: }
1896: void
1897: add_answer_cnt(op)int op;
1898: {
1899: LexiProblem_p->ans_cnt++;
1900: if(LexiProblem_p->ans_op == 0) { /* the very first /AND or /OR */
1901: LexiProblem_p->ans_op = op;
1902: } else {
1903: if( LexiProblem_p->ans_op != op ) { char warn_msg[WARN_MSG_LENGTH];
1904: sprintf(warn_msg,"When specifying multiple answers, either /AND or /OR can be used, but not both.\n");
1905: capa_msg(MESSAGE_ERROR,warn_msg);
1906: }
1907: }
1908: }
1909:
1910: /* -- called when forming answer_expr */
1911: void
1912: finish_answer_info()
1913: {
1914: AnswerInfo_t *ai;
1915:
1916: if( LexiProblem_p->ans_cnt == 1 ) { /* Only one answer is defined */
1917: LexiProblem_p->answer = CurrAnsInfo.ans_str;
1918: LexiProblem_p->ans_type = CurrAnsInfo.ans_type;
1919: LexiProblem_p->calc = CurrAnsInfo.ans_calc;
1920: LexiProblem_p->tol_type = CurrAnsInfo.ans_tol_type;
1921: LexiProblem_p->tolerance = CurrAnsInfo.ans_tol;
1922: LexiProblem_p->sig_ubound= CurrAnsInfo.ans_sig_ub;
1923: LexiProblem_p->sig_lbound= CurrAnsInfo.ans_sig_lb;
1924: LexiProblem_p->id_list = CurrAnsInfo.ans_id_list;
1925: LexiProblem_p->pts_list = CurrAnsInfo.ans_pts_list;
1926: strcpy(LexiProblem_p->ans_fmt,CurrAnsInfo.ans_fmt);
1927: strcpy(LexiProblem_p->unit_str,CurrAnsInfo.ans_unit_str);
1928: LexiProblem_p->ans_unit = CurrAnsInfo.ans_unit;
1929: } else {
1930: ai = (AnswerInfo_t *)capa_malloc(sizeof(AnswerInfo_t),1);
1931: ai->ans_str = CurrAnsInfo.ans_str;
1932: ai->ans_type = CurrAnsInfo.ans_type;
1933: ai->ans_calc = CurrAnsInfo.ans_calc;
1934: ai->ans_tol_type = CurrAnsInfo.ans_tol_type;
1935: ai->ans_tol = CurrAnsInfo.ans_tol;
1936: ai->ans_sig_ub = CurrAnsInfo.ans_sig_ub;
1937: ai->ans_sig_lb = CurrAnsInfo.ans_sig_lb;
1938: ai->ans_id_list = CurrAnsInfo.ans_id_list;
1939: ai->ans_pts_list = CurrAnsInfo.ans_pts_list;
1940: strcpy(ai->ans_fmt,CurrAnsInfo.ans_fmt);
1941: strcpy(ai->ans_unit_str,CurrAnsInfo.ans_unit_str);
1942: ai->ans_unit = CurrAnsInfo.ans_unit;
1943: ai->ans_next = NULL;
1944: if(LexiProblem_p->ans_cnt == 2) {
1945: LexiProblem_p->ans_list = ai;
1946: } else {
1947: (LexiProblem_p->ans_list_last)->ans_next = ai;
1948: }
1949: LexiProblem_p->ans_list_last = ai;
1950: }
1951:
1952: }
1953:
1954: /* === End of capaGrammarDef.y ============================================= */
1955:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>