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