/* =||>>================================================================<<||= */
/* 45678901234567890123456789012345678901234567890123456789012345678901234567 */
/* copyrighted by Isaac Tsai, 1996, 1997, 1998, 1999, 2000 */
/* =||>>================================================================<<||= */
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "capaParser.h" /* Symbol_p */
#include "capaFunction.h" /* RANDOM_F etc. */
#include "capaToken.h"
#include "capaCommon.h"
#include "ranlib.h"
char Parse_class[QUARTER_K];
int Parse_set;
int Parse_section;
char Parse_student_number[MAX_STUDENT_NUMBER+1];
char Parse_name[MAX_NAME_CHAR+1];
long capaid_plus_gen;
extern int Parsemode_f;
extern int Lexi_qnum;
extern char Opened_filename[MAX_OPENED_FILE][QUARTER_K];
extern int Input_idx;
extern int Current_line[MAX_OPENED_FILE];
extern int Func_idx;
extern Symbol FuncStack[MAX_FUNC_NEST];
/* --------------------------------------------------------------------------- */
int
match_function(func, argc) char *func; int argc;
{
if( !strcmp(func,"random") ) return (((argc==2 || argc==3)? RANDOM_F : MIS_ARG_COUNT));
if( !strcmp(func,"choose") ) return (CHOOSE_F);
if( !strcmp(func,"tex") ) return (((argc==2)? TEX_F: MIS_ARG_COUNT));
if( !strcmp(func,"var_in_tex") ) return (VAR_IN_TEX_F);
if( !strcmp(func,"html") ) return (((argc==1)? HTML_F: MIS_ARG_COUNT));
if( !strcmp(func,"web") ) return (((argc==3)? WEB_F: MIS_ARG_COUNT));
if( !strcmp(func,"pin") ) return (((argc<2)? PIN_F: MIS_ARG_COUNT));
if( !strcmp(func,"capa_id") ) return (((argc<2)? PIN_F: MIS_ARG_COUNT));
if( !strcmp(func,"class") ) return (((argc==0)? CLASS_F: MIS_ARG_COUNT));
if( !strcmp(func,"section") ) return (((argc==0)? SECTION_F: MIS_ARG_COUNT));
if( !strcmp(func,"set") ) return (((argc==0)? SET_F: MIS_ARG_COUNT));
if( !strcmp(func,"problem") ) return (((argc==0)? PROBLEM_F: MIS_ARG_COUNT));
if( !strcmp(func,"name") ) return (((argc==0)? NAME_F: MIS_ARG_COUNT));
if( !strcmp(func,"student_number") ) return (((argc==0)? SNUMBER_F: MIS_ARG_COUNT));
if( !strcmp(func,"due_date") ) return (((argc<2)? DUE_DATE_F: MIS_ARG_COUNT));
if( !strcmp(func,"due_day") ) return (((argc<2)? DUE_DAY_F: MIS_ARG_COUNT));
if( !strcmp(func,"open_date") ) return (((argc<2)? OPEN_DATE_F: MIS_ARG_COUNT));
if( !strcmp(func,"answer_date") ) return (((argc<2)? ANSWER_DATE_F: MIS_ARG_COUNT));
if( !strcmp(func,"to_string") ) return (((argc==1 || argc==2)? TO_STRING_F: MIS_ARG_COUNT));
if( !strcmp(func,"sub_string") ) return (((argc==2 || argc==3)? SUB_STRING_F: MIS_ARG_COUNT));
if( !strcmp(func,"strlen") ) return (((argc==1)? STRLEN_F: MIS_ARG_COUNT));
if( !strcmp(func,"get_seed") ) return (((argc==0)? GET_SEED_F: MIS_ARG_COUNT));
if( !strcmp(func,"set_seed") ) return (((argc==1)? SET_SEED_F: MIS_ARG_COUNT));
if( !strcmp(func,"array_index") ) return (((argc==1)? ARRAY_INDEX_F: MIS_ARG_COUNT));
if( !strcmp(func,"array_sorted_index") ) return (((argc==2)? ARRAY_SORTED_INDEX_F: MIS_ARG_COUNT));
if( !strcmp(func,"array_max") ) return (((argc==1)? ARRAY_MAX_F: MIS_ARG_COUNT));
if( !strcmp(func,"array_min") ) return (((argc==1)? ARRAY_MIN_F: MIS_ARG_COUNT));
if( !strcmp(func,"array_moments") ) return (((argc==2)? ARRAY_MOMENTS_F: MIS_ARG_COUNT));
if( !strcmp(func,"array_var") ) return (((argc==1)? ARRAY_VARIANCE_F: MIS_ARG_COUNT));
if( !strcmp(func,"array_std_dev") ) return (((argc==1)? ARRAY_STD_DEV_F: MIS_ARG_COUNT));
if( !strcmp(func,"array_skewness") ) return (((argc==1)? ARRAY_SKEWNESS_F: MIS_ARG_COUNT));
if( !strcmp(func,"to_int") ) return (((argc==1)? TO_INT_F: MIS_ARG_COUNT));
if( !strcmp(func,"format") ) return (FORMAT_F);
if( !strcmp(func,"pick") ) return (((argc> 1)? PICK_F: MIS_ARG_COUNT));
if( !strcmp(func,"sin") ) return (((argc==1)? SIN_F: MIS_ARG_COUNT));
if( !strcmp(func,"cos") ) return (((argc==1)? COS_F: MIS_ARG_COUNT));
if( !strcmp(func,"tan") ) return (((argc==1)? TAN_F: MIS_ARG_COUNT));
if( !strcmp(func,"asin") ) return (((argc==1)? ASIN_F: MIS_ARG_COUNT));
if( !strcmp(func,"acos") ) return (((argc==1)? ACOS_F: MIS_ARG_COUNT));
if( !strcmp(func,"atan") ) return (((argc==1)? ATAN_F: MIS_ARG_COUNT));
if( !strcmp(func,"sinh") ) return (((argc==1)? SINH_F: MIS_ARG_COUNT));
if( !strcmp(func,"cosh") ) return (((argc==1)? COSH_F: MIS_ARG_COUNT));
if( !strcmp(func,"tanh") ) return (((argc==1)? TANH_F: MIS_ARG_COUNT));
if( !strcmp(func,"asinh") ) return (((argc==1)? ASINH_F: MIS_ARG_COUNT));
if( !strcmp(func,"acosh") ) return (((argc==1)? ACOSH_F: MIS_ARG_COUNT));
if( !strcmp(func,"atanh") ) return (((argc==1)? ATANH_F: MIS_ARG_COUNT));
if( !strcmp(func,"atan2") ) return (((argc==2)? ATANTWO_F: MIS_ARG_COUNT));
if( !strcmp(func,"j0") ) return (((argc==1)? J_ZERO_F: MIS_ARG_COUNT));
if( !strcmp(func,"j1") ) return (((argc==1)? J_ONE_F: MIS_ARG_COUNT));
if( !strcmp(func,"jn") ) return (((argc==2)? J_N_F: MIS_ARG_COUNT));
if( !strcmp(func,"y0") ) return (((argc==1)? Y_ZERO_F: MIS_ARG_COUNT));
if( !strcmp(func,"y1") ) return (((argc==1)? Y_ONE_F: MIS_ARG_COUNT));
if( !strcmp(func,"yn") ) return (((argc==2)? Y_N_F: MIS_ARG_COUNT));
if( !strcmp(func,"log") ) return (((argc==1)? LOG_F: MIS_ARG_COUNT));
if( !strcmp(func,"log10") ) return (((argc==1)? LOG_TEN_F: MIS_ARG_COUNT));
if( !strcmp(func,"exp") ) return (((argc==1)? EXP_F: MIS_ARG_COUNT));
if( !strcmp(func,"pow") ) return (((argc==2)? POW_F: MIS_ARG_COUNT));
if( !strcmp(func,"erf") ) return (((argc==1)? ERF_F: MIS_ARG_COUNT));
if( !strcmp(func,"erfc") ) return (((argc==1)? ERFC_F: MIS_ARG_COUNT));
if( !strcmp(func,"sqrt") ) return (((argc==1)? SQRT_F: MIS_ARG_COUNT));
if( !strcmp(func,"min") ) return (MIN_F);
if( !strcmp(func,"max") ) return (MAX_F);
if( !strcmp(func,"abs") ) return (((argc==1)? ABS_F: MIS_ARG_COUNT));
if( !strcmp(func,"floor") ) return (((argc==1)? FLOOR_F: MIS_ARG_COUNT));
if( !strcmp(func,"ceil") ) return (((argc==1)? CEIL_F: MIS_ARG_COUNT));
if( !strcmp(func,"sgn") ) return (((argc==1)? SGN_F: MIS_ARG_COUNT));
if( !strcmp(func,"mod") ) return (((argc==2)? MOD_F: MIS_ARG_COUNT));
if( !strcmp(func,"remainder") ) return (((argc==2)? REMAINDER_F: MIS_ARG_COUNT));
if( !strcmp(func,"factorial") ) return (((argc==1)? FACTORIAL_F: MIS_ARG_COUNT));
if( !strcmp(func,"roundto") ) return (((argc==2)? ROUNDTO_F: MIS_ARG_COUNT));
if( !strcmp(func,"eval_formula") ) return (((argc==3)? EVALUATE_F: MIS_ARG_COUNT));
if( !strcmp(func,"capa_id_plus") ) return (((argc==1 || argc==2)? CAPAID_PLUS: MIS_ARG_COUNT));
if( !strcmp(func,"seat_number") ) return (((argc <2)? SEAT_NUMBER: MIS_ARG_COUNT));
if( !strcmp(func,"duration") ) return (((argc==0)? DURATION: MIS_ARG_COUNT));
if( !strcmp(func,"is_open") ) return (((argc <2)? IS_OPEN_F: MIS_ARG_COUNT));
if( !strcmp(func,"is_due") ) return (((argc <2)? IS_DUE_F: MIS_ARG_COUNT));
if( !strcmp(func,"is_answer") ) return (((argc <2)? IS_ANSWER_F: MIS_ARG_COUNT));
return (UNKNOWN_F);
}
/**********************************************************/
#ifdef SGN
#undef SGN
#endif
#define SGN(xx) ( (xx) > 0 ? 1 : ( (xx) == 0 ? 0 : -1) )
#define MAX_DOUBLE 1.7976931348623157E+308
#define MIN_DOUBLE 2.2250738585072014E-308
#define INT_DIV 0
#define REAL_DIV 1
#define INT_LOWER 0
#define REAL_LOWER 2
#define INT_UPPER 0
#define REAL_UPPER 4
#define ALL_INTEGER 0
int which_set(argc,argp,resultp)
int argc;
ArgNode_t *argp;
Symbol *resultp;
{
char aline[MAX_BUFFER_SIZE], tmpS[MAX_BUFFER_SIZE];
int result=Parse_set;
if( argc == 1 ) {
if( (FIRST_ARGTYPE(argp) == S_VAR ) ||
(FIRST_ARGTYPE(argp) == S_CONSTANT ) ) {
sprintf(aline,"<<ARG TYPE MISMATCH>>");
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave(aline);
sprintf(tmpS, "function %s() cannot accept string as argument.\n",
FuncStack[Func_idx].s_name);
capa_msg(MESSAGE_ERROR,tmpS);
result=-1;
} else {
if( (FIRST_ARGTYPE(argp) == I_VAR ) ||
(FIRST_ARGTYPE(argp) == I_CONSTANT ) ) {
result = FIRST_ARGINT(argp);
} else {
result = FIRST_ARGREAL(argp);
}
}
}
return result;
}
Symbol *
do_function(func,argc,argp)
int func;
int argc;
ArgNode_t *argp;
{
Symbol *resultp;
ArgNode_t *tmpArgp;
char aline[MAX_BUFFER_SIZE], tmpS[MAX_BUFFER_SIZE], fmt_str[FORMAT_STRING_LENG];
char num_str[SMALL_LINE_BUFFER],date_str[SMALL_LINE_BUFFER];
double tmpA=0.0, tmpB=0.0;
int slots, noError, errCode, mo, yy, dd, hh, mm, tmpInt;
long rout;
char *wday[9] = {"Sat,", "Sun,", "Mon,", "Tue,", "Wed,", "Thr,", "Fri,", "Sat,", "\0"};
char *month[SIXTEEN] = { "UNKNOWN", "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "UNKNOWN", "UNKNOWN", "\0"};
resultp = (Symbol *)capa_malloc(1,sizeof(Symbol));
switch(func) {
case RANDOM_F: { int type_flag=0;
double r_lower=0.0, r_upper=1.0, r_division=1.0;
errCode = 0; rout = ignlgi();
switch( FIRST_ARGTYPE(argp) ) {
case I_VAR: case I_CONSTANT: break;
case R_VAR: case R_CONSTANT: type_flag = (type_flag | 1); break;
case S_VAR: case S_CONSTANT: errCode = 1; break;
}
switch( SECOND_ARGTYPE(argp) ) {
case I_VAR: case I_CONSTANT: break;
case R_VAR: case R_CONSTANT: type_flag = (type_flag | 2); break;
case S_VAR: case S_CONSTANT: errCode = 2; break;
}
if( argc == 3 ) {
switch( THIRD_ARGTYPE(argp) ) {
case I_VAR: case I_CONSTANT: break;
case R_VAR: case R_CONSTANT: type_flag = (type_flag | 4); break;
case S_VAR: case S_CONSTANT: errCode = 4; break;
}
}
if( errCode == 0 ) {
if( argc == 3 ) {
switch(type_flag) {
case 0: r_division = (double)FIRST_ARGINT(argp);
r_upper = (double)SECOND_ARGINT(argp);
r_lower = (double)THIRD_ARGINT(argp); break;
case 2: r_division = (double)FIRST_ARGINT(argp);
r_upper = SECOND_ARGREAL(argp);
r_lower = (double)THIRD_ARGINT(argp); break;
case 4: r_division = (double)FIRST_ARGINT(argp);
r_upper = (double)SECOND_ARGINT(argp);
r_lower = THIRD_ARGREAL(argp); break;
case 6: r_division = (double)FIRST_ARGINT(argp);
r_upper = SECOND_ARGREAL(argp);
r_lower = THIRD_ARGREAL(argp); break;
case 1: r_division = FIRST_ARGREAL(argp);
r_upper = (double)SECOND_ARGINT(argp);
r_lower = (double)THIRD_ARGINT(argp); break;
case 3: r_division = FIRST_ARGREAL(argp);
r_upper = SECOND_ARGREAL(argp);
r_lower = (double)THIRD_ARGINT(argp); break;
case 5: r_division = FIRST_ARGREAL(argp);
r_upper = (double)SECOND_ARGINT(argp);
r_lower = THIRD_ARGREAL(argp); break;
case 7: r_division = FIRST_ARGREAL(argp);
r_upper = SECOND_ARGREAL(argp);
r_lower = THIRD_ARGREAL(argp); break;
}
} else { /* two args */
switch(type_flag) {
case 0: r_upper = (double)FIRST_ARGINT(argp);
r_lower = (double)SECOND_ARGINT(argp); break;
case 1: r_upper = FIRST_ARGREAL(argp);
r_lower = (double)SECOND_ARGINT(argp); break;
case 2: r_upper = (double)FIRST_ARGINT(argp);
r_lower = SECOND_ARGREAL(argp); break;
case 3: r_upper = FIRST_ARGREAL(argp);
r_lower = SECOND_ARGREAL(argp); break;
}
r_division = 1.0;
}
if( r_upper >= r_lower ) {
slots = 1 + (int)floor( (r_upper - r_lower)/r_division );
if( type_flag == 0 ) {
resultp->s_type = I_CONSTANT;
resultp->s_int = (int)r_lower + ((int)r_division)*(rout % slots );
} else {
resultp->s_type = R_CONSTANT;
resultp->s_real = r_lower + r_division*(double)(rout % slots );
}
} else {
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave("<<2ND ARG MUST .GE. 1ST ARG>>");
sprintf(tmpS,"random()'s second arg. must be greater than the first arg.\n");
capa_msg(MESSAGE_ERROR,tmpS);
}
} else {
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave("<<ARG CANNOT BE STRING>>");
sprintf(tmpS,"random() cannot accept string as argument.\n");
capa_msg(MESSAGE_ERROR,tmpS);
}
} break;
case CHOOSE_F: { int ii, pick=1;
ArgNode_t *tmpArgp;
noError = 1;
tmpArgp = argp; ii=0;
while( ii < argc-1 ) {tmpArgp = tmpArgp->a_next; ii++; }
switch( FIRST_ARGTYPE(tmpArgp) ) {
case IDENTIFIER:
sprintf(tmpS,"The first argument to choose(): \"%s\" has not been defined yet. I will choose the first element.\n",FIRST_ARGNAME(tmpArgp));
capa_msg(MESSAGE_ERROR,tmpS);
pick = 1;
break;
case I_VAR: case I_CONSTANT:
pick = FIRST_ARGINT(tmpArgp); break;
case R_VAR: case R_CONSTANT:
pick = (int)FIRST_ARGREAL(tmpArgp);
sprintf(tmpS,"The first argument to choose() is a real number: \"%.15g\", it must be an integer, I will use %d instead.\n",FIRST_ARGREAL(tmpArgp),pick);
capa_msg(MESSAGE_ERROR,tmpS);
break;
case S_VAR: case S_CONSTANT:
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave("CHOOSE: first argument must be an integer");
sprintf(tmpS,"The first argument to choose() cannot be a string, I will choose the first element.\n");
capa_msg(MESSAGE_ERROR,tmpS);
pick = 1;
break;
}
if( noError ) {
if( (pick <= 0) || (pick > argc-1) ) {
sprintf(tmpS,"The first argument to choose() is out of bounds, tt is %d, but should be in the range [1,%d].\n", pick, argc-1);
capa_msg(MESSAGE_ERROR,tmpS);
pick = argc-1;
} else { pick = argc - pick; }
for(ii=1,tmpArgp = argp;(ii < pick)&&(ii < argc-1);ii++) { tmpArgp = tmpArgp->a_next; }
resultp->s_type = (tmpArgp->a_sp)->s_type;
switch((tmpArgp->a_sp)->s_type) {
case IDENTIFIER:
sprintf(tmpS,"The variable \"%s\" selected by choose() has not yet been defined.\n",(tmpArgp->a_sp)->s_name);
capa_msg(MESSAGE_ERROR,tmpS);
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave(tmpS);
break;
case I_VAR: case I_CONSTANT:
resultp->s_type = I_CONSTANT;
resultp->s_int = (tmpArgp->a_sp)->s_int; break;
case R_VAR: case R_CONSTANT:
resultp->s_type = R_CONSTANT;
resultp->s_real = (tmpArgp->a_sp)->s_real; break;
case S_VAR: case S_CONSTANT:
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave((tmpArgp->a_sp)->s_str); break; /********* */
}
}
} break;
case PIN_F: {
if (-1==(tmpInt=which_set(argc,argp,resultp))) break;
resultp->s_type = I_CONSTANT;
resultp->s_int=capa_PIN(Parse_student_number,tmpInt,0);
}
break;
case CLASS_F: {
resultp->s_type = S_CONSTANT;
if(strlen(Parse_class) != 0 ) {
resultp->s_str=strsave(Parse_class);
} else {
resultp->s_str=strsave("UNKNOWN");
}
}
break;
case SECTION_F:{ resultp->s_type = I_CONSTANT;
resultp->s_int = Parse_section;
} break;
case PROBLEM_F:{ resultp->s_type = I_CONSTANT;
resultp->s_int= Lexi_qnum+1;
} break;
case SET_F: { resultp->s_type = I_CONSTANT;
resultp->s_int=Parse_set;
} break;
case NAME_F: {
resultp->s_type = S_CONSTANT;
resultp->s_str=strsave(Parse_name);
} break;
case SNUMBER_F: {
resultp->s_type = S_CONSTANT;
resultp->s_str=strsave(Parse_student_number);
} break;
case IS_DUE_F:
case IS_ANSWER_F:
case IS_OPEN_F: {
int whichDate=CHECK_OPEN_DATE;
if (-1==(tmpInt=which_set(argc,argp,resultp))) break;
resultp->s_type = I_CONSTANT;
switch(func) {
case IS_OPEN_F: whichDate=CHECK_OPEN_DATE;break;
case IS_DUE_F: whichDate=CHECK_DUE_DATE;break;
case IS_ANSWER_F: whichDate=CHECK_ANS_DATE;break;
}
if( capa_check_date(whichDate,Parse_student_number,
Parse_section,tmpInt) < 0 ) {
resultp->s_int = 0;
} else {
resultp->s_int = 1;
}
} break;
case DUE_DATE_F:
{ if (-1==(tmpInt=which_set(argc,argp,resultp))) break;
resultp->s_type = S_CONSTANT;
if(capa_get_date(CHECK_DUE_DATE,Parse_student_number,Parse_section,tmpInt,date_str) > 0 ) {
sscanf(date_str,"%4d/%2d/%2d %2d:%2d",&yy, &mo, &dd, &hh, &mm);
sprintf(aline, "%s %s %2d, %4d at %02d:%02d",
wday[weekday(yy,mo,dd)], month[mo], dd, yy, hh, mm);
resultp->s_str= strsave(aline);
} else {
resultp->s_str= strsave("UNKNOWN");
}
} break;
case DUE_DAY_F:
{ if (-1==(tmpInt=which_set(argc,argp,resultp))) break;
resultp->s_type = S_CONSTANT;
if(capa_get_date(CHECK_DUE_DATE,Parse_student_number,Parse_section,tmpInt,date_str) > 0 ) {
sscanf(date_str,"%4d/%2d/%2d %2d:%2d",&yy, &mm, &dd, &hh, &mm);
sprintf(aline, "%s %s %2d, %4d",
wday[weekday(yy,mo,dd)], month[mo], dd, yy);
resultp->s_str= strsave(aline);
} else {
resultp->s_str= strsave("UNKNOWN");
}
} break;
case OPEN_DATE_F:
{ if (-1==(tmpInt=which_set(argc,argp,resultp))) break;
resultp->s_type = S_CONSTANT;
if(capa_get_date(CHECK_OPEN_DATE,Parse_student_number,Parse_section,tmpInt,date_str) > 0 ) {
sscanf(date_str,"%4d/%2d/%2d %2d:%2d",&yy, &mm, &dd, &hh, &mm);
sprintf(aline, "%s %s %2d, %4d at %02d:%02d",
wday[weekday(yy,mo,dd)], month[mo], dd, yy, hh, mm);
resultp->s_str= strsave(aline);
} else {
resultp->s_str= strsave("UNKNOWN");
}
} break;
case ANSWER_DATE_F:
{ if (-1==(tmpInt=which_set(argc,argp,resultp))) break;
resultp->s_type = S_CONSTANT;
if(capa_get_date(CHECK_ANS_DATE,Parse_student_number,Parse_section,tmpInt,date_str) > 0 ) {
sscanf(date_str,"%4d/%2d/%2d %2d:%2d",&yy, &mo, &dd, &hh, &mm);
sprintf(aline, "%s %s %2d, %4d at %02d:%02d",
wday[weekday(yy,mo,dd)], month[mo], dd, yy, hh, mm);
resultp->s_str= strsave(aline);
} else {
resultp->s_str= strsave("UNKNOWN");
}
} break;
case STRLEN_F: {
resultp->s_type = I_CONSTANT;
switch( FIRST_ARGTYPE(argp) ) {
case I_VAR:
case I_CONSTANT:
resultp->s_type = S_CONSTANT;
sprintf(tmpS,"strlen() only accepts string variable, not integer.\n");
capa_msg(MESSAGE_ERROR,tmpS);
resultp->s_str=strsave(tmpS);
break;
case R_VAR:
case R_CONSTANT:
resultp->s_type = S_CONSTANT;
sprintf(tmpS,"strlen() only accepts string variable, not float number.\n");
capa_msg(MESSAGE_ERROR,tmpS);
resultp->s_str=strsave(tmpS);
break;
case S_VAR:
case S_CONSTANT:
resultp->s_int = strlen( FIRST_ARGSTR(argp) );
break;
case IDENTIFIER:
sprintf(tmpS,"Unknown variable, %s, argument to function strlen()\n",argp->a_sp->s_name);
capa_msg(MESSAGE_ERROR,tmpS);
resultp->s_str=strsave(tmpS);
break;
}
} break;
case TO_STRING_F:
{ char aline[MAX_BUFFER_SIZE],rline[MAX_BUFFER_SIZE];
resultp->s_type = S_CONSTANT;
if( argc == 1 ) {
switch( FIRST_ARGTYPE(argp) ) {
case I_VAR:
case I_CONSTANT:
sprintf(aline,"%ld",FIRST_ARGINT(argp));
resultp->s_str = strsave(aline); break;
case R_VAR:
case R_CONSTANT:
sprintf(aline,"%.15g",FIRST_ARGREAL(argp));
resultp->s_str = strsave(aline); break;
case S_VAR:
case S_CONSTANT:
resultp->s_str = strsave(FIRST_ARGSTR(argp)); break;
case IDENTIFIER:
sprintf(tmpS,"Unknown variable, %s, argument to function to_string()\n",argp->a_sp->s_name);
capa_msg(MESSAGE_ERROR,tmpS);
resultp->s_str=strsave(tmpS);
break;
}
} else {
switch( FIRST_ARGTYPE(argp) ) {
case I_VAR:
case I_CONSTANT:
case R_VAR:
case R_CONSTANT:
sprintf(tmpS,
"to_string()'s second arg. must be a string.\n");
capa_msg(MESSAGE_ERROR,tmpS);
sprintf(aline,"%%.15g");
break;
case S_VAR:
case S_CONSTANT:
sprintf(aline,"%%%s",FIRST_ARGSTR(argp));
break;
case IDENTIFIER:
sprintf(tmpS,"Unknown variable, %s, argument to function to_string()\n",argp->a_next->a_sp->s_name);
capa_msg(MESSAGE_ERROR,tmpS);
resultp->s_str=strsave(tmpS);
break;
}
switch( SECOND_ARGTYPE(argp) ) {
case I_VAR:
case I_CONSTANT:
sprintf(aline,"%ld",SECOND_ARGINT(argp));
resultp->s_str = strsave(aline); break;
case R_VAR:
case R_CONSTANT:
sprintf(rline,aline,SECOND_ARGREAL(argp));
resultp->s_str = strsave(rline); break;
case S_VAR:
case S_CONSTANT:
resultp->s_str = strsave(SECOND_ARGSTR(argp));
break;
case IDENTIFIER:
sprintf(tmpS,"Unknown variable, %s, argument to function to_string()\n",argp->a_sp->s_name);
capa_msg(MESSAGE_ERROR,tmpS);
resultp->s_str=strsave(tmpS);
break;
}
}
} break;
case SUB_STRING_F: /* sub_string(str, 2), 1 is the first char */
/* sub_string(str, 3, 5) means start from the third char and take 5 chars */
{ int idx=1, leng, rleng=0,ii;
char *a_str, *b_str;
resultp->s_type = S_CONSTANT;
if( argc == 2 ) { /* two arguments format */
switch( FIRST_ARGTYPE(argp) ) {
case IDENTIFIER:
sprintf(tmpS,
"sub_string()'s second arg. must be an integer.\n");
capa_msg(MESSAGE_ERROR,tmpS);
break;
case I_VAR:
case I_CONSTANT:
idx = FIRST_ARGINT(argp);
break;
case R_VAR:
case R_CONSTANT:
idx = (int) FIRST_ARGREAL(argp);
break;
case S_VAR:
case S_CONSTANT:
sprintf(tmpS,
"sub_string()'s second arg. must be an integer.\n");
capa_msg(MESSAGE_ERROR,tmpS);
break;
}
switch( SECOND_ARGTYPE(argp) ) {
case IDENTIFIER:
sprintf(tmpS,
"sub_string()'s first arg. is not defined before use.\n");
capa_msg(MESSAGE_ERROR,tmpS);
break;
case I_VAR:
case I_CONSTANT:
sprintf(tmpS,
"sub_string()'s first arg. cannot be an integer.\n");
capa_msg(MESSAGE_ERROR,tmpS);
break;
case R_VAR:
case R_CONSTANT:
sprintf(tmpS,
"sub_string()'s first arg. cannot be a number.\n");
capa_msg(MESSAGE_ERROR,tmpS);
break;
case S_VAR:
case S_CONSTANT:
a_str = SECOND_ARGSTR(argp);
leng = strlen(a_str);
if( (idx<1) || (idx > leng) ) {
sprintf(tmpS, "sub_string()'s second arg. is out of range.\n");
capa_msg(MESSAGE_ERROR,tmpS);
idx = 1;
}
b_str = (char *)&a_str[idx-1];
resultp->s_str = strsave(b_str);
if( SECOND_ARGTYPE(argp) == S_CONSTANT) {
/* freed in free arg_list */
/* capa_mfree((char *)SECOND_ARGSTR(argp)); */
}
break;
}
} else { /* three arguments format sub_string(string, start, length) */
switch( FIRST_ARGTYPE(argp) ) {
case IDENTIFIER:
sprintf(tmpS,
"sub_string()'s third arg. must be an integer.\n");
capa_msg(MESSAGE_ERROR,tmpS);
break;
case I_VAR:
case I_CONSTANT:
rleng = FIRST_ARGINT(argp);
break;
case R_VAR:
case R_CONSTANT:
rleng = (int) FIRST_ARGREAL(argp);
break;
case S_VAR:
case S_CONSTANT:
sprintf(tmpS,
"sub_string()'s third arg. must be an integer.\n");
capa_msg(MESSAGE_ERROR,tmpS);
break;
}
switch( SECOND_ARGTYPE(argp) ) {
case IDENTIFIER:
sprintf(tmpS,
"sub_string()'s second arg. must be an integer.\n");
capa_msg(MESSAGE_ERROR,tmpS);
break;
case I_VAR:
case I_CONSTANT:
idx = SECOND_ARGINT(argp);
break;
case R_VAR:
case R_CONSTANT:
idx = (int) SECOND_ARGREAL(argp);
break;
case S_VAR:
case S_CONSTANT:
sprintf(tmpS,
"sub_string()'s second arg. must be an integer.\n");
capa_msg(MESSAGE_ERROR,tmpS);
break;
}
switch( THIRD_ARGTYPE(argp) ) {
case IDENTIFIER:
sprintf(tmpS,
"sub_string()'s first arg. is not defined before use.\n");
capa_msg(MESSAGE_ERROR,tmpS);
break;
case I_VAR:
case I_CONSTANT:
sprintf(tmpS,
"sub_string()'s first arg. cannot be an integer.\n");
capa_msg(MESSAGE_ERROR,tmpS);
break;
case R_VAR:
case R_CONSTANT:
sprintf(tmpS,
"sub_string()'s first arg. cannot be a number.\n");
capa_msg(MESSAGE_ERROR,tmpS);
break;
case S_VAR:
case S_CONSTANT:
a_str = THIRD_ARGSTR(argp);
leng = strlen(a_str);
if( (idx < 1) || (idx > leng) ) {
sprintf(tmpS, "sub_string()'s second arg. is out of range.\n");
capa_msg(MESSAGE_ERROR,tmpS);
idx = 1;
}
if( (rleng<1) || ((rleng+idx-1) > leng)) {
rleng = leng - idx + 1;
}
b_str = (char *)capa_malloc((rleng+1)*sizeof(char),1);
for(ii=idx-1;ii<(rleng+idx-1);ii++) {
b_str[ii-idx+1] = a_str[ii];
}
resultp->s_str = strsave(b_str);
capa_mfree(b_str);
if( THIRD_ARGTYPE(argp) == S_CONSTANT) {
/* handled in free_arglist() */
/* capa_mfree((char *)THIRD_ARGSTR(argp)); */
}
break;
}
}
} break;
case PICK_F: { int ii, pick=1;
ArgNode_t *tmpArgp;
noError = 1;
rout = ignlgi();
tmpArgp = argp; ii=0;
while( ii < argc-1 ) {tmpArgp = tmpArgp->a_next; ii++; }
switch( FIRST_ARGTYPE(tmpArgp) ) {
case I_VAR:
case I_CONSTANT:
pick = FIRST_ARGINT(tmpArgp);
if( (pick <= 0 ) || (pick > argc-1) ) {
noError = 0;
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave("PICK: first arg out of bound.");
}
break;
case R_VAR:
case R_CONSTANT:
pick = (int)FIRST_ARGREAL(tmpArgp);
if( (pick <= 0 ) || (pick > argc-1) ) {
noError = 0;
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave("PICK: first arg out of bound.");
}
break;
case S_VAR:
case S_CONSTANT: noError = 0;
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave("PICK: first arg must be int");
break;
}
if( noError ) {
for( ii=0; ii< pick; ii++) {
}
}
}
break;
case GET_SEED_F:
{ long seed1, seed2;
char *tmp;
getsd(&seed1,&seed2);
tmp = (char *)capa_malloc(32,1);
sprintf(tmp,"%ld,%ld",seed1,seed2);
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave(tmp);
capa_mfree(tmp);
} break;
case SET_SEED_F:
{ long seed1, seed2;
int leng;
switch( FIRST_ARGTYPE(argp) ) {
case I_VAR: case I_CONSTANT: break;
case R_VAR: case R_CONSTANT: break;
case S_VAR: case S_CONSTANT:
leng = strlen(FIRST_ARGSTR(argp));
if( (index(FIRST_ARGSTR(argp), ' ') != NULL) ) {
sscanf(FIRST_ARGSTR(argp),"%ld,%ld", &seed1, &seed2);
setall(seed1,seed2);
}
break;
}
resultp->s_type = I_CONSTANT;
resultp->s_int = 0;
} break;
case ARRAY_MOMENTS_F: /* it */
{
char *tmp_input;
Symbol *r_p;
switch( FIRST_ARGTYPE(argp) ) {
case I_VAR: case I_CONSTANT:
case R_VAR: case R_CONSTANT:
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave("<<ARG. OF THIS FUNCTION MUST BE AN ARRAY NAME>>");
sprintf(tmpS,"array_moments()'s arg. must be a name of an array.\n");
capa_msg(MESSAGE_ERROR,tmpS);
errCode = 1;
break;
case S_VAR: case S_CONSTANT:
tmp_input = strsave(FIRST_ARGSTR(argp));
errCode = 0;
break;
case IDENTIFIER:
tmp_input = strsave(FIRST_ARGNAME(argp));
errCode = 0;
break;
}
if( errCode == 0 ) {
switch( SECOND_ARGTYPE(argp) ) {
case I_VAR: case I_CONSTANT:
case R_VAR: case R_CONSTANT:
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave("<<ARG. OF THIS FUNCTION MUST BE AN ARRAY NAME>>");
sprintf(tmpS,"array_moments()'s arg. must be a name of an array.\n");
capa_msg(MESSAGE_ERROR,tmpS);
errCode = 1;
break;
case S_VAR: case S_CONSTANT:
r_p = array_moments(SECOND_ARGSTR(argp),tmp_input);
capa_mfree((char *)tmp_input);
/* fprintf(stdout,"DONE array_moments()\n"); fflush(stdout); */
break;
case IDENTIFIER:
r_p = array_moments(SECOND_ARGNAME(argp),tmp_input);
capa_mfree((char *)tmp_input);
break;
}
if(errCode == 0 ) {
capa_mfree((char *)resultp);
resultp = r_p;
}
}
} break;
case ARRAY_SORTED_INDEX_F: /* array_sorted_index(array_name_str, sort_type) */
{
switch( FIRST_ARGTYPE(argp) ) {
case I_VAR: case I_CONSTANT:
switch( FIRST_ARGINT(argp) ) {
case ASCEND_SORT: break;
case DESCEND_SORT: break;
case NUMERICAL_SORT: break;
default: break;
}
break;
case R_VAR: case R_CONSTANT: break;
case S_VAR: case S_CONSTANT:
break;
}
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave("NOT YET");
} break;
case ARRAY_MAX_F:
case ARRAY_MIN_F:
{ int min;
Symbol *r_p;
min = ((func==ARRAY_MIN_F)? 1 : 0);
switch( FIRST_ARGTYPE(argp) ) {
case I_VAR: case I_CONSTANT:
case R_VAR: case R_CONSTANT:
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave("<<ARG. OF THIS FUNCTION MUST BE AN ARRAY NAME>>");
sprintf(tmpS,"%s()'s arg. must be a name of an array.\n",(min ? "min" : "max"));
capa_msg(MESSAGE_ERROR,tmpS);
break;
case S_VAR: case S_CONSTANT: /* this allows the use of min(array[1]) which array[1]="another" */
r_p = array_min_max(FIRST_ARGSTR(argp),min);
if( r_p == NULL ) { /* array name is not in array tree */
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave("<<STRING ARRAY NAME IS NOT YET DEFINED!>>");
} else {
/*
fprintf(stdout,"min_max():: STR arg. R=%g\n",r_p->s_real); fflush(stdout);
*/
capa_mfree((char *)resultp);
resultp = r_p;
}
break;
case IDENTIFIER:
r_p = array_min_max(FIRST_ARGNAME(argp),min);
if( r_p == NULL ) { /* array name is not in array tree */
/* fprintf(stdout,"min_max() return NULL\n"); fflush(stdout); */
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave("<<ARRAY NAME IS NOT YET DEFINED!>>");
} else {
/*
fprintf(stdout,"min_max():: ID arg. R=%g\n",r_p->s_real); fflush(stdout);
*/
capa_mfree((char *)resultp);
resultp = r_p;
}
break;
}
} break;
case SIN_F:
case COS_F:
case TAN_F:
case ASIN_F:
case ACOS_F:
case ATAN_F:
case SINH_F:
case COSH_F:
case TANH_F:
case ASINH_F:
case ACOSH_F:
case ATANH_F:
case J_ZERO_F:
case J_ONE_F:
case Y_ZERO_F:
case Y_ONE_F:
case LOG_F:
case LOG_TEN_F:
case EXP_F:
case ERF_F:
case ERFC_F:
case ABS_F:
case SQRT_F:
case FLOOR_F:
case CEIL_F:
case SGN_F:{ if( (FIRST_ARGTYPE(argp) == S_VAR ) || (FIRST_ARGTYPE(argp) == S_CONSTANT ) ) {
sprintf(aline,"<<ARG TYPE MISMATCH>>");
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave(aline);
sprintf(tmpS,"function %s() cannot accept string as argument.\n", FuncStack[Func_idx].s_name);
capa_msg(MESSAGE_ERROR,tmpS);
} else {
if( (FIRST_ARGTYPE(argp) == I_VAR ) || (FIRST_ARGTYPE(argp) == I_CONSTANT ) ) {
tmpA = (double)FIRST_ARGINT(argp);
} else {
tmpA = (double)FIRST_ARGREAL(argp);
}
resultp->s_type = R_CONSTANT;
switch(func) {
case SIN_F: resultp->s_real = sin(tmpA); break;
case COS_F: resultp->s_real = cos(tmpA); break;
case TAN_F: resultp->s_real = tan(tmpA); break;
case ASIN_F: if(fabs(tmpA) <= 1.0) {
resultp->s_real = asin(tmpA);
} else {
resultp->s_type = S_CONSTANT;
sprintf(aline,"<<ARG OUT OF BOUND>>");
resultp->s_str = strsave(aline);
sprintf(tmpS, "asin()'s arg. is not in the range of [-1.0,+1.0].\n");
capa_msg(MESSAGE_ERROR,tmpS);
}
break;
case ACOS_F: if(fabs(tmpA) <= 1.0) {
resultp->s_real = acos(tmpA);
} else {
resultp->s_type = S_CONSTANT;
sprintf(aline,"<<ARG OUT OF BOUND>>");
resultp->s_str = strsave(aline);
sprintf(tmpS,"acos()'s arg. is not in the range of [-1.0,+1.0].\n");
capa_msg(MESSAGE_ERROR,tmpS);
}
break;
case ATAN_F: resultp->s_real = atan(tmpA); break;
case SINH_F: resultp->s_real = sinh(tmpA); break;
case COSH_F: resultp->s_real = cosh(tmpA); break;
case TANH_F: resultp->s_real = tanh(tmpA); break;
case ASINH_F: resultp->s_real = asinh(tmpA); break;
case ACOSH_F: resultp->s_real = acosh(tmpA); break;
case ATANH_F: resultp->s_real = atanh(tmpA); break;
case J_ZERO_F: resultp->s_real = j0(tmpA); break;
case J_ONE_F: resultp->s_real = j1(tmpA); break;
case Y_ZERO_F: resultp->s_real = y0(tmpA); break;
case Y_ONE_F: resultp->s_real = y1(tmpA); break;
case LOG_F: resultp->s_real = log(tmpA); break;
case LOG_TEN_F: resultp->s_real = log10(tmpA); break;
case EXP_F: resultp->s_real = exp(tmpA); break;
case ERF_F: resultp->s_real = erf(tmpA); break;
case ERFC_F: resultp->s_real = erfc(tmpA); break;
case ABS_F: resultp->s_real = fabs(tmpA); break;
case SQRT_F: if( tmpA >= 0.0) {
resultp->s_real = sqrt(tmpA);
} else {
resultp->s_type = S_CONSTANT;
sprintf(aline,"<<ARG OUT OF BOUND>>");
resultp->s_str = strsave(aline);
sprintf(tmpS, "sqrt()'s arg. is not in the range of [0.0,+Inf].\n");
capa_msg(MESSAGE_ERROR,tmpS);
}
break;
case FLOOR_F: resultp->s_type = I_CONSTANT;
resultp->s_int = (long)floor(tmpA); break;
case CEIL_F: resultp->s_type = I_CONSTANT;
resultp->s_int = (long)ceil(tmpA); break;
case SGN_F: resultp->s_type = I_CONSTANT;
resultp->s_int = (int)SGN(tmpA); break;
}
}
}
break;
case ATANTWO_F:
case J_N_F:
case Y_N_F:
case POW_F: { noError = 1;
switch(FIRST_ARGTYPE(argp)) {
case I_VAR:
case I_CONSTANT: tmpA = (double)FIRST_ARGINT(argp); break;
case R_VAR:
case R_CONSTANT: tmpA = FIRST_ARGREAL(argp); break;
case S_VAR:
case S_CONSTANT: noError = 0;
resultp->s_str = strsave("<<MIS TYPE>>");
sprintf(tmpS,"%s()'s second arg. cannot be string.\n",FuncStack[Func_idx].s_name);
capa_msg(MESSAGE_ERROR,tmpS);
break;
}
switch(SECOND_ARGTYPE(argp)) {
case I_VAR:
case I_CONSTANT: tmpB = (double)SECOND_ARGINT(argp); break;
case R_VAR:
case R_CONSTANT: tmpB = SECOND_ARGREAL(argp); break;
case S_VAR:
case S_CONSTANT: noError = 0;
resultp->s_str = strsave("<<MIS TYPE>>");
sprintf(tmpS,"%s()'s first arg. cannot be string.\n",FuncStack[Func_idx].s_name);
capa_msg(MESSAGE_ERROR,tmpS);
break;
}
if ( POW_F == func ) {
if ((!(((double)((int)tmpA)) == tmpA)) && (tmpB < 0.0)) {
resultp->s_str = strsave("<<ARG OUT OF BOUND>>");
sprintf(tmpS,
"%s()'s arguments would result in a complex number.\n",
FuncStack[Func_idx].s_name);
capa_msg(MESSAGE_ERROR,tmpS);
noError=0;
}
}
if(noError) {
resultp->s_type = R_CONSTANT;
switch( func ) {
case J_N_F: resultp->s_real = jn((int)tmpB, tmpA); break;
case Y_N_F: resultp->s_real = yn((int)tmpB, tmpA); break;
case POW_F: resultp->s_real = pow(tmpB, tmpA); break;
case ATANTWO_F: resultp->s_real = atan2(tmpB, tmpA); break;
}
}else {
resultp->s_type = S_CONSTANT;
}
}
break;
case TEX_F: { if (Parsemode_f != TeX_MODE) {
resultp->s_type = FIRST_ARGTYPE(argp);
switch(FIRST_ARGTYPE(argp)) {
case I_VAR:
case I_CONSTANT: resultp->s_int = FIRST_ARGINT(argp); break;
case R_VAR:
case R_CONSTANT: resultp->s_real = FIRST_ARGREAL(argp); break;
case S_VAR:
case S_CONSTANT: resultp->s_str = strsave(FIRST_ARGSTR(argp)); break;
}
} else {
resultp->s_type = SECOND_ARGTYPE(argp);
switch(SECOND_ARGTYPE(argp)) {
case I_VAR:
case I_CONSTANT: resultp->s_int = SECOND_ARGINT(argp); break;
case R_VAR:
case R_CONSTANT: resultp->s_real = SECOND_ARGREAL(argp); break;
case S_VAR:
case S_CONSTANT: resultp->s_str = strsave(SECOND_ARGSTR(argp)); break;
}
}
} break;
case VAR_IN_TEX_F:{
if (Parsemode_f == TeX_MODE) {
resultp->s_type = FIRST_ARGTYPE(argp);
switch(FIRST_ARGTYPE(argp)) {
case I_VAR:
case I_CONSTANT: resultp->s_int = FIRST_ARGINT(argp); break;
case R_VAR:
case R_CONSTANT: resultp->s_real = FIRST_ARGREAL(argp); break;
case S_VAR:
case S_CONSTANT: resultp->s_str = strsave(FIRST_ARGSTR(argp)); break;
}
} else {
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave("");
}
} break;
case HTML_F: { if (Parsemode_f == HTML_MODE) {
resultp->s_type = FIRST_ARGTYPE(argp);
switch(FIRST_ARGTYPE(argp)) {
case I_VAR:
case I_CONSTANT: resultp->s_int = FIRST_ARGINT(argp); break;
case R_VAR:
case R_CONSTANT: resultp->s_real = FIRST_ARGREAL(argp); break;
case S_VAR:
case S_CONSTANT: resultp->s_str = strsave(FIRST_ARGSTR(argp)); break;
}
} else {
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave("");
}
/* printf("HTML:%s\n",resultp->s_str); */
} break;
case WEB_F:
case FORMAT_F: { /* web(ASCII,TeX,HTML) */
if( argc == 3 ) {
switch(Parsemode_f) {
case HTML_MODE: {
resultp->s_type = FIRST_ARGTYPE(argp);
switch(FIRST_ARGTYPE(argp)) {
case I_VAR:
case I_CONSTANT: resultp->s_int = FIRST_ARGINT(argp); break;
case R_VAR:
case R_CONSTANT: resultp->s_real = FIRST_ARGREAL(argp); break;
case S_VAR:
case S_CONSTANT: resultp->s_str = strsave(FIRST_ARGSTR(argp)); break;
}
} break;
case TeX_MODE: {
resultp->s_type = SECOND_ARGTYPE(argp);
switch(SECOND_ARGTYPE(argp)) {
case I_VAR:
case I_CONSTANT: resultp->s_int = SECOND_ARGINT(argp); break;
case R_VAR:
case R_CONSTANT: resultp->s_real = SECOND_ARGREAL(argp); break;
case S_VAR:
case S_CONSTANT: resultp->s_str = strsave(SECOND_ARGSTR(argp)); break;
}
} break;
default: {
resultp->s_type = THIRD_ARGTYPE(argp);
switch(THIRD_ARGTYPE(argp)) {
case I_VAR:
case I_CONSTANT: resultp->s_int = THIRD_ARGINT(argp); break;
case R_VAR:
case R_CONSTANT: resultp->s_real = THIRD_ARGREAL(argp); break;
case S_VAR:
case S_CONSTANT: resultp->s_str = strsave(THIRD_ARGSTR(argp)); break;
}
} break;
}
} else { /* argc == 2 */
switch(Parsemode_f) {
case TeX_MODE: {
resultp->s_type = FIRST_ARGTYPE(argp);
switch(FIRST_ARGTYPE(argp)) {
case I_VAR:
case I_CONSTANT: resultp->s_int = FIRST_ARGINT(argp); break;
case R_VAR:
case R_CONSTANT: resultp->s_real = FIRST_ARGREAL(argp); break;
case S_VAR:
case S_CONSTANT: resultp->s_str = strsave(FIRST_ARGSTR(argp)); break;
}
} break;
default : {
resultp->s_type = SECOND_ARGTYPE(argp);
switch(SECOND_ARGTYPE(argp)) {
case I_VAR:
case I_CONSTANT: resultp->s_int = SECOND_ARGINT(argp); break;
case R_VAR:
case R_CONSTANT: resultp->s_real = SECOND_ARGREAL(argp); break;
case S_VAR:
case S_CONSTANT: resultp->s_str = strsave(SECOND_ARGSTR(argp)); break;
}
} break;
}
}
} break;
case FACTORIAL_F: {
int ii;
unsigned long long l_fac;
double d_fac;
switch(FIRST_ARGTYPE(argp)) {
case I_VAR:
case I_CONSTANT: {
if( FIRST_ARGINT(argp) < 0 ) {
sprintf(aline,"<<FACTORIAL ERROR>>");
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave(aline);
sprintf(tmpS,"%s()'s arg. cannot be less than zero.\n",FuncStack[Func_idx].s_name);
capa_msg(MESSAGE_ERROR,tmpS);
} else {
if( FIRST_ARGINT(argp) <= 20 ) {
resultp->s_type = I_CONSTANT;
l_fac = 1;
for(ii=2; ii <= FIRST_ARGINT(argp); ii++) { l_fac *= ii; }
resultp->s_int = l_fac;
} else {
resultp->s_type = R_CONSTANT;
d_fac = 362880.0;
for(ii=10; ii <= FIRST_ARGINT(argp); ii++) { d_fac *= ii; }
resultp->s_real = d_fac;
}
}
}
break;
case R_VAR:
case R_CONSTANT: {
if( FIRST_ARGREAL(argp) < 0.0 ) {
sprintf(aline,"<<FACTORIAL ERROR>>");
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave(aline);
sprintf(tmpS,"%s()'s arg. cannot be less than zero.\n", FuncStack[Func_idx].s_name);
capa_msg(MESSAGE_ERROR,tmpS);
} else {
if( FIRST_ARGREAL(argp) <= 20.0 ) {
resultp->s_type = I_CONSTANT;
l_fac = 1;
for(ii=2; ii <= FIRST_ARGREAL(argp); ii++) { l_fac *= ii; }
resultp->s_int = l_fac;
} else {
resultp->s_type = R_CONSTANT;
d_fac = 362880.0;
for(ii=10; ii <= FIRST_ARGREAL(argp); ii++) { d_fac *= ii; }
resultp->s_real = d_fac;
}
}
}
break;
case S_VAR:
case S_CONSTANT: {
sprintf(aline,"<<FACTORIAL ERROR>>");
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave(aline);
sprintf(tmpS,"%s()'s arg. cannot be of string type.\n",FuncStack[Func_idx].s_name);
capa_msg(MESSAGE_ERROR,tmpS);
}
break;
}
} break;
case MOD_F: break;
case REMAINDER_F: break;
case MAX_F:
case MIN_F: { int ii, idx, type;
tmpArgp = argp;
tmpA = ((func == MIN_F)? MAX_DOUBLE : - MAX_DOUBLE);
type = R_CONSTANT; idx = -1;
noError = 1;
for(ii = 0; (ii < argc)&&(noError); ii++) {
switch (FIRST_ARGTYPE(tmpArgp)) {
case I_VAR:
case I_CONSTANT:
if( type == S_CONSTANT) {
sprintf(aline,"<<ARG TYPE>>");
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave(aline);
sprintf(tmpS,"%s()'s arg. type cannot mix string with int or real.\n",FuncStack[Func_idx].s_name);
capa_msg(MESSAGE_ERROR,tmpS);
noError = 0;
} else {
switch(func) {
case MIN_F:
if( tmpA <= FIRST_ARGINT(tmpArgp) ) {
} else {
idx = ii; type = I_CONSTANT;
tmpA = (double)FIRST_ARGINT(tmpArgp);
}
break;
case MAX_F:
if( tmpA >= FIRST_ARGINT(tmpArgp) ) {
} else {
idx = ii; type = I_CONSTANT;
tmpA = (double)FIRST_ARGINT(tmpArgp);
}
break;
}
}
break;
case R_VAR:
case R_CONSTANT:
if( type == S_CONSTANT ) {
sprintf(aline,"<<ARG TYPE>>");
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave(aline);
sprintf(tmpS,"%s()'s arg. type cannot mix string with int or real.\n",FuncStack[Func_idx].s_name);
capa_msg(MESSAGE_ERROR,tmpS);
noError = 0;
} else {
switch(func) {
case MIN_F:
if( tmpA <= FIRST_ARGREAL(tmpArgp) ) {
} else {
idx = ii; type = R_CONSTANT;
tmpA = FIRST_ARGREAL(tmpArgp);
}
break;
case MAX_F:
if( tmpA >= FIRST_ARGREAL(tmpArgp) ) {
} else {
idx = ii; type = R_CONSTANT;
tmpA = FIRST_ARGREAL(tmpArgp);
}
break;
}
}
break;
case S_VAR:
case S_CONSTANT:
if( (ii != 0)&&(type != S_CONSTANT) ) {
sprintf(aline,"<<ARG TYPE>>");
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave(aline);
sprintf(tmpS," %s()'s arg. type cannot mix string with int or real.\n",FuncStack[Func_idx].s_name);
capa_msg(MESSAGE_ERROR,tmpS);
noError = 0;
} else {
if( ii == 0 ) { idx = 0; strcpy(tmpS, FIRST_ARGSTR(tmpArgp)); }
type = S_CONSTANT;
switch( func) {
case MIN_F:
if( strcmp(tmpS, FIRST_ARGSTR(tmpArgp)) <= 0 ) {
} else {
idx = ii;
strcpy(tmpS, FIRST_ARGSTR(tmpArgp));
}
break;
case MAX_F:
if( strcmp(tmpS, FIRST_ARGSTR(tmpArgp)) >= 0 ) {
} else {
idx = ii;
strcpy(tmpS, FIRST_ARGSTR(tmpArgp));
}
break;
}
}
break;
}
tmpArgp = tmpArgp->a_next;
}
if( noError ) {
for(tmpArgp=argp,ii=0; ii<idx; ii++) { tmpArgp=tmpArgp->a_next; }
resultp->s_type = type;
switch(type) {
case I_CONSTANT: resultp->s_int = (tmpArgp->a_sp)->s_int;
break;
case R_CONSTANT: resultp->s_real = (tmpArgp->a_sp)->s_real;
break;
case S_CONSTANT: resultp->s_str = strsave((tmpArgp->a_sp)->s_str);
break;
}
}
}
break;
case ROUNDTO_F: {
noError = 1; hh = 0; /* reuse integer hh and mm */
switch(FIRST_ARGTYPE(argp)) {
case I_VAR:
case I_CONSTANT: mm = FIRST_ARGINT(argp); break;
case R_VAR:
case R_CONSTANT: mm = (int)FIRST_ARGREAL(argp); break;
case S_VAR:
case S_CONSTANT: noError = 0;
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave("<<MIS TYPE>>");
sprintf(tmpS,
"%s()'s second arg. cannot be string.\n",FuncStack[Func_idx].s_name);
capa_msg(MESSAGE_ERROR,tmpS);
break;
}
switch(SECOND_ARGTYPE(argp)) {
case I_VAR:
case I_CONSTANT: hh = SECOND_ARGINT(argp); break;
case R_VAR:
case R_CONSTANT: tmpA = SECOND_ARGREAL(argp); break;
case S_VAR:
case S_CONSTANT: noError = 0;
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave("<<MIS TYPE>>");
sprintf(tmpS,
"%s()'s first arg. cannot be string.\n",
FuncStack[Func_idx].s_name);
capa_msg(MESSAGE_ERROR,tmpS);
break;
}
if(noError) {
resultp->s_type = R_CONSTANT;
if( hh != 0 ) {
resultp->s_type = I_CONSTANT;
resultp->s_int = hh;
} else {
if ( mm >= 0 ) {
sprintf(fmt_str,"%%.%df",mm);
sprintf(num_str,fmt_str,tmpA);
tmpB = atof(num_str);
resultp->s_real = tmpB;
} else {
sprintf(tmpS,"%s()'s second arg. cannot be negative (%d).\n",
FuncStack[Func_idx].s_name,mm);
capa_msg(MESSAGE_ERROR,tmpS);
resultp->s_real = tmpA; /* not changed */
}
}
}
} break;
case EVALUATE_F: { char *f_str, *v_str, *pt_str, *out_come;
noError = 1;
switch(FIRST_ARGTYPE(argp)) { /* now only accepts string like "0.0,0.1,0.2,0.3,0.4,0.5" */
case I_VAR:
case I_CONSTANT: noError = 0;
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave("<<Evaulate Formula: Pts TYPE incorrect>>");
sprintf(tmpS,
"%s()'s third arg. cannot be integer.\n",FuncStack[Func_idx].s_name);
capa_msg(MESSAGE_ERROR,tmpS);
break;
case R_VAR:
case R_CONSTANT: noError = 0;
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave("<<Evaulate Formula: Pts TYPE incorrect>>");
sprintf(tmpS,
"%s()'s third arg. cannot be integer.\n",FuncStack[Func_idx].s_name);
capa_msg(MESSAGE_ERROR,tmpS);
break;
case S_VAR:
case S_CONSTANT:
pt_str = FIRST_ARGSTR(argp);
break;
}
switch(SECOND_ARGTYPE(argp)) {
case I_VAR:
case I_CONSTANT:
case R_VAR:
case R_CONSTANT: noError = 0;
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave("<<Evaluate Formula: Var list TYPE incorrect>>");
sprintf(tmpS,
"%s()'s second arg. cannot be number.\n",FuncStack[Func_idx].s_name);
capa_msg(MESSAGE_ERROR,tmpS);
break;
case S_VAR:
case S_CONSTANT: v_str = SECOND_ARGSTR(argp);
break;
}
switch(THIRD_ARGTYPE(argp)) {
case I_VAR:
case I_CONSTANT:
case R_VAR:
case R_CONSTANT: noError = 0;
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave("<<Evaluate Formula: Formula TYPE incorrect>>");
sprintf(tmpS,
"%s()'s first arg. cannot be number.\n",FuncStack[Func_idx].s_name);
capa_msg(MESSAGE_ERROR,tmpS);
break;
case S_VAR:
case S_CONSTANT: f_str = THIRD_ARGSTR(argp);
break;
}
if(noError) {
resultp->s_type = S_CONSTANT;
/* printf("EVALUATE:::%s,%s,%s\n",f_str, v_str, pt_str); */
out_come = eval_formula_range_str(f_str, v_str, pt_str);
if( !out_come ) {
resultp->s_str = strsave("<<Evaluate formula:: NULL>>");
sprintf(tmpS,
"%s() cannot evaluate the formula correctly.\n",FuncStack[Func_idx].s_name);
capa_msg(MESSAGE_ERROR,tmpS);
} else {
resultp->s_str = out_come;
}
}
}
break;
case CAPAID_PLUS:
{
extern Problem_t* FirstProblem_p;
extern Problem_t* LexiProblem_p;
Problem_t* problem;
int num_char,pin;
errCode = 0;
if (argc==1) {
switch( FIRST_ARGTYPE(argp) ) {
case I_VAR: case I_CONSTANT: num_char=FIRST_ARGINT(argp); break;
case R_VAR: case R_CONSTANT: errCode = 1; break;
case S_VAR: case S_CONSTANT: errCode = 1; break;
}
} else {
switch( SECOND_ARGTYPE(argp) ) {
case I_VAR: case I_CONSTANT: num_char=SECOND_ARGINT(argp); break;
case R_VAR: case R_CONSTANT: errCode = 1; break;
case S_VAR: case S_CONSTANT: errCode = 1; break;
}
}
if( errCode == 0 ) {
if ( FirstProblem_p ) {
problem=FirstProblem_p;
} else {
problem=LexiProblem_p;
}
if (!(problem->capaidplus)) capa_mfree(problem->capaidplus);
if (-1==(tmpInt=which_set(argc-1,argp,resultp))) break;
pin=capa_PIN(Parse_student_number,tmpInt,0);
problem->capaidplus = capa_id_plus(Parse_student_number,
tmpInt,num_char);
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave(problem->capaidplus);
} else {
resultp->s_type = S_CONSTANT;
resultp->s_str = strsave("<<INCORRECT ARGS TO CAPAID_PLUS>>");
}
}
break;
case SEAT_NUMBER:
{
int filenum;
double filedoub;
char *filename;
if ( argc == 1 ) {
switch( FIRST_ARGTYPE(argp)) {
case I_VAR: case I_CONSTANT: filenum=FIRST_ARGINT(argp);
filename=capa_malloc(TMP_LINE_LENGTH,1);
sprintf(filename,"%d",filenum);
break;
case R_VAR: case R_CONSTANT: filedoub=FIRST_ARGREAL(argp);
filename=capa_malloc(TMP_LINE_LENGTH,1);
sprintf(filename,"%f",filedoub);
break;
case S_VAR: case S_CONSTANT:
filename=strsave(FIRST_ARGSTR(argp)); break;
}
} else {
filename=NULL;
}
resultp->s_type = S_CONSTANT;
resultp->s_str = capa_get_seat(Parse_student_number,filename);
if ( filename != NULL ) capa_mfree(filename);
break;
}
case DURATION: { resultp->s_type = I_CONSTANT;
resultp->s_int=capa_get_duration(Parse_student_number,
Parse_section,Parse_set);
} break;
case MIS_ARG_COUNT:
{ resultp->s_type = S_CONSTANT;
resultp->s_str = strsave("<<ARG COUNT>>");
sprintf(tmpS,"%s()'s arg. count is not correct.\n",FuncStack[Func_idx].s_name);
capa_msg(MESSAGE_ERROR,tmpS);
} break;
case UNKNOWN_F:
default: { resultp->s_type = S_CONSTANT;
resultp->s_str = strsave("<<UNKNOWN FUNCTION>>");
sprintf(tmpS,"%s() unknown.\n",FuncStack[Func_idx].s_name);
capa_msg(MESSAGE_ERROR,tmpS);
} break;
}
return (resultp);
}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>