home *** CD-ROM | disk | FTP | other *** search
- /* DATA.C DATA.C DATA.C DATA.C DATA.C DATA.C
-
- DATA INITIALIZE AND CALCULATE XXXX X XXXXX X
- X X X X X X X
- July 1, 1987 X X X X X X X
- X X X X X X X
- X X XXXXX X XXXXX
- X X X X X X X
- XXXX X X X X X
- */
- #include "ctype.h"
- #include "string.h"
- #include "math.h"
- #include "struct.def"
- #include "defin.h"
-
- extern struct vars allvars[];
- extern char inline[];
- extern int col;
- extern int errcode,colerr;
- extern char strngout[];
- extern int valattr;
-
- /* ****************************************************** initdata */
- /* This function is used to initialize all of the variables to the */
- /* starting values including their variable names. */
- void initdata(struct vars *pnt)
- {
- int index;
- for (index = 0;index < 6;++index){
- (pnt+index)->varname[0] = 'A' + index;
- (pnt+index)->varname[1] = 0;
- (pnt+index)->outtype = 'F';
- (pnt+index)->value = 0.0;
- }
- for (index = 6;index < 12;++index){
- (pnt+index)->varname[0] = 'I' + index - 6;
- (pnt+index)->varname[1] = 0;
- (pnt+index)->outtype = 'D';
- (pnt+index)->value = 0;
- }
- (pnt+4)->value = 2.718281828459045;
- (pnt+5)->value = 3.141592653589793;
- (pnt+11)->value = 16777215;
- }
-
- /* ******************************************************* getnames */
- /* This function reads in a new list of variable names to be used */
- /* in place of the names A to F. This is only as a convenience for */
- /* the user, so he can use more meaningful names. */
- void getnames(void)
- {
- char var,index;
- char dummy[80];
-
- col = 1; /* skip over and ignore the # sign */
- do {
- if (inline[col] == ' ') col++; /* ignore all leading blanks */
- else {
- var = inline[col] - 'A';
- if ((var >= 0) && (var <= 5)) { /* A through F */
- col++;
- if (inline[col] != '-') { /* should be a dash */
- errchk(14);
- errout();
- return;
- }
- col++;
- for (index = 0;index < 6;index++)
- if (isalpha(inline[col]) || isdigit(inline[col])) {
- dummy[index] = inline[col];
- dummy[index + 1] = 0;
- col++;
- }
- if (index > 0) {
- strcpy(allvars[var].varname,dummy);
- strcpy(strngout," "); /* this is for */
- strngout[6-strlen(dummy)] = 0; /* leading blanks */
- strcat(strngout,dummy);
- strngdis(var + 1,1,valattr);
- }
- }
- else if ((var >= 8) && (var <= 13)) { /* I through N */
- col++;
- if (inline[col] != '-') { /* should be a dash */
- errchk(14);
- errout();
- return;
- }
- col++;
- if ((inline[col] == 'O') || (inline[col] == 'D') ||
- (inline[col] == 'H') || (inline[col] == 'X')) {
- var -= 2;
- allvars[var].outtype = inline[col];
- col++;
- }
- else {
- errchk(15);
- errout();
- return;
- }
- }
- else { /* unknown variable name */
- errchk(3);
- errout();
- return;
- }
- }
- } while (inline[col] && (errcode == 0));
- }
-
- /* ******************************************************* calcdata */
- /* This is the function that actually does the work of deciding */
- /* what calculations need to be done. The method used is described */
- /* in detail below. */
- /* Three variables and two operators are number1 */
- /* stored as per the list. "op1" is always op1 */
- /* a plus or minus, and op2 is always a number2 */
- /* multiplication or divide. If a plus or op2 */
- /* minus is found for op2, number1 and number3 */
- /* number2 are combined according to op1 */
- /* and the result becomes number1, the new op2 becomes op1, and */
- /* number3 becomes number2. If op2 is either a multiplication or */
- /* divide, number2 and number3 are combined according to op2 and */
- /* the result is placed in number2. When a parentheses is found, */
- /* a recursive call is made and the expression in the parenthe- */
- /* ses is evaluated. A bit of study will be very fruitful in */
- /* understanding this operation. */
- void calcdata(double *newval)
- {
- double number1,number2,number3,getnum();
- char op1,op2,getop();
- number1 = 0.0;
- op1 = '+';
- number2 = 0.0;
- while (inline[col] == ' ') col++; /* ignore blanks */
- /* check for unary operator */
- if ((inline[col] == '+') || (inline[col] == '-')) {
- op1 = inline[col];
- col++;
- }
-
- number2 = getnum(); /* (inline[col]== 0 ) = End of line */
- /* (inline[col]=='$') = End of line */
- if ((inline[col] == 0) || (inline[col] =='$')) {
- calcdat(&number1,&op1,&number2);
- *newval = number1;
- return;
- }
- for (;;){
- op2 = getop();
- col++;
- /* check for end of line 0, ), or $ */
- if (op2 == '$') op2 = 0; /* force a $ to lool like eol */
- if ((op2 == 0) || (op2 == ')')) {
- col++;
- calcdat(&number1,&op1,&number2);
- *newval = number1;
- return;
- }
- number3 = getnum();
- if ((op2 == '*') || (op2 == '/')){
- calcdat(&number2,&op2,&number3);
- }
- else{
- calcdat(&number1,&op1,&number2);
- op1 = op2;
- number2 = number3;
- }
- } /* end of infinite for loop */
- }
-
- /* ******************************************************** calcdat */
- /* This function actually does the calculations described in the */
- /* function above. */
- void calcdat(double *number1,char *op1,double *number2)
- {
- switch (*op1) {
- case '*' : *number1 = (*number1)*(*number2);
- break;
- case '/' : if (*number2 == 0.0) {
- errchk(10);
- break;
- }
- *number1 = (*number1)/(*number2);
- break;
- case '+' : *number1 = *number1 + *number2;
- break;
- case '-' : *number1 = *number1 - *number2;
- break;
- default : break;
- }
- return;
- }
-
- /* ********************************************************* getnum */
- /* This is the workhorse of the program. It actually scans the data */
- /* input field and converts the data into numbers which are in the */
- /* internal format of the computer so the calculations can be done. */
- double getnum(void)
- {
- int index,i,decpt;
- double newval;
- char name[7];
- double sqrt(), exp(), log(), sin(), cos(), atan();
-
- while (inline[col] == ' ') col++; /* ignore blanks */
-
- index = inline[col];
- if (index == '('){
- col++;
- calcdata(&newval); /* recursive call */
- col--;
- return(newval);
- }
-
- decpt = 0; /* search for a decimal point */
- i = col;
- index = inline[i];
- while ((index >= '0') && (index <= '9')) {
- i++;
- index = inline[i];
- if (index == '.') decpt = 1;
- }
-
- index = inline[col];
- if (((index > '0') && (index <= '9')) ||
- ((index == '0') && (decpt == 1)) ||
- (index == '.')) { /* floating number */
- newval = 0.0;
- while ((index >= '0') && (index <= '9')) {
- newval = 10.0*newval + (index - '0');
- col++;
- index = inline[col];
- }
- if (index == '.') {
- double constant = 0.1;
- col++;
- index = inline[col];
- while ((index >= '0') && (index <= '9')) {
- newval = newval + (index - '0') * constant;
- constant *= 0.1;
- col++;
- index = inline[col];
- }
- }
- return(newval);
- } /* end of floating point number */
-
- if (index == '0') { /* octal or hexadecimal */
- col++;
- index = inline[col];
- if ((index == 'x') || (index == 'X')){ /* hexadecimal */
- col++;
- index = inline[col];
- newval = 0.0;
- while (((index >= '0') && (index <= '9')) ||
- ((index >= 'A') && (index <= 'F')) ||
- ((index >= 'a') && (index <= 'f'))) {
- switch (index) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':i = index - '0';
- break;
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':i = index - 'A' + 10;
- break;
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':i = index - 'a' + 10;
- break;
- default :break;
- }
- newval = 16.0*newval + i;
- col++;
- index = inline[col];
- }
- return(newval);
- } /* end of hexadecimal 'if' */
-
- else { /* octal */
- newval = 0.0;
- while ((index >= '0') && (index <= '7')) {
- newval = 8.0*newval + (index - '0');
- col++;
- index = inline[col];
- }
- return(newval);
- } /* end of octal 'else' */
-
- } /* end of octal or hexadecimal numbers */
-
- /* find variable or function name */
- if ((inline[col] >= 'A') && (inline[col] <= 'Z')) {
- name[0] = inline[col++];
- i = 1;
- while ((((inline[col] >= 'A') && (inline[col] <= 'Z')) ||
- ((inline[col] >= '0') && (inline[col] <= '9'))) &&
- (i <= 5)) { /* continue var or function name */
- name[i++] = inline[col++];
- }
- name[i] = 0; /* name found */
-
- if (inline[col] == '('){ /* function call */
- col++;
- if (strcmp(name,"ABS") == 0) {
- calcdata(&newval);
- if (newval < 0.0) newval = -newval;
- }
- else if (strcmp(name,"SQRT") == 0) {
- calcdata(&newval);
- if (newval < 0.0) {
- errchk(5); /* Neg value for SQRT */
- newval = 0.0;
- }
- else newval = sqrt(newval);
- }
- else if (strcmp(name,"FACT") == 0) {
- calcdata(&newval);
- if (newval < 0.0) {
- errchk(16); /* Neg value for FACT */
- newval = 0.0;
- }
- else {
- double count;
- int howmany;
- count = newval;
- newval = 1.0;
- for (howmany = count;howmany > 1;howmany--) {
- count = howmany;
- newval = newval * count;
- }
- }
- }
- else if (strcmp(name,"EXP") == 0) {
- calcdata(&newval);
- newval = exp(newval);
- }
- else if (strcmp(name,"LOG") == 0) {
- calcdata(&newval);
- if (newval < 0.0) {
- errchk(7); /* Neg value for LOG */
- newval = 0.0;
- }
- else newval = log(newval);
- }
- else if (strcmp(name,"SIN") == 0){
- calcdata(&newval);
- newval = sin(newval);
- }
- else if (strcmp(name,"COS") == 0){
- calcdata(&newval);
- newval = cos(newval);
- }
- else if (strcmp(name,"ATAN") == 0){
- calcdata(&newval);
- newval = atan(newval);
- }
- else {
- errchk(6); /* function not found */
- newval = 0.0;
- }
- col--;
- return(newval);
- } /* end of function call */
-
- else { /* variable name */
- for (i = 0;i < 12;i++) {
- if ((strcmp(name,allvars[i].varname)) == 0) {
- newval = allvars[i].value;
- return(newval);
- }
- }
- errchk(3); /* variable not found */
- newval = 0.0;
- return(newval);
- } /* end of variable call */
-
- } /* end of variable or function call */
- errchk(9);
- return(0.0); /* invalid data found */
- }
-
- /* ********************************************************** getop */
- /* A call to this function expects to find an operator, end of line */
- /* or a close parenthesis. */
- char getop(void)
- {
- while (inline[col] == ' ') col++; /* ignore blanks */
- switch (inline[col]){
- case '$':
- case ')':
- case 0 :
- case '+':
- case '-':
- case '*':
- case '/': break;
- default : errchk(4); /* invalid operator */
- }
- return(inline[col]);
- }
-
- /* ********************************************************* errchk */
- /* The error code is stored by this function and the cursor column */
- /* is adjusted in an attempt to put the cursor near the error that */
- /* caused the problem. */
- void errchk(int err)
- {
- if(errcode) return; /* error already found */
- else { /* only the first error is stored */
- errcode = err; /* store the error number */
- switch (err){
- case 2 :
- case 4 :
- case 8 :
- case 9 :
- case 10 :
- case 11 :
- case 12 : colerr = col;
- break;
- case 1 :
- case 3 : colerr = col - 1;
- break;
- case 6 : colerr = col - 2;
- break;
- case 5 :
- case 7 : colerr = col - 3;
- break;
- default : colerr = col;
- }
- }
- }
-