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