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