home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / progm / ctutor2.zip / DATA.C < prev    next >
C/C++ Source or Header  |  1989-11-10  |  15KB  |  447 lines

  1. /*    DATA.C   DATA.C    DATA.C    DATA.C    DATA.C    DATA.C
  2.  
  3. DATA INITIALIZE AND CALCULATE      XXXX     X    XXXXX    X
  4.                                    X   X   X X     X     X X
  5. Oct 18, 1988                       X   X  X   X    X    X   X
  6.                                    X   X  X   X    X    X   X
  7.                                    X   X  XXXXX    X    XXXXX
  8.                                    X   X  X   X    X    X   X
  9.                                    XXXX   X   X    X    X   X
  10. */
  11. #include "ctype.h"
  12. #include "string.h"
  13. #include "math.h"
  14. #include "struct.def"
  15. #include "defin.h"
  16.  
  17. extern struct vars allvars[];
  18. extern char inline[];
  19. extern int col;
  20. extern int errcode,colerr;
  21. extern char strngout[];
  22. extern int valattr;
  23.  
  24. /* ****************************************************** initdata */
  25. /* This function is used to initialize all of the variables to the */
  26. /* starting values including their variable names.                 */
  27. void initdata(struct vars *pnt)
  28. {
  29. int index;
  30.     for (index = 0;index < 6;++index){
  31.        (pnt+index)->varname[0] = 'A' + index;
  32.        (pnt+index)->varname[1] = 0;
  33.        (pnt+index)->outtype = 'F';
  34.        (pnt+index)->value = 0.0;
  35.     }
  36.     for (index = 6;index < 12;++index){
  37.        (pnt+index)->varname[0] = 'I' + index - 6;
  38.        (pnt+index)->varname[1] = 0;
  39.        (pnt+index)->outtype = 'D';
  40.        (pnt+index)->value = 0;
  41.     }
  42.     (pnt+4)->value = 2.718281828459045;
  43.     (pnt+5)->value = 3.141592653589793;
  44.     (pnt+11)->value = 16777215;
  45. }
  46.  
  47. /* ******************************************************* getnames */
  48. /* This function reads in a new list of variable names to be used   */
  49. /* in place of the names A to F. This is only as a convenience for  */
  50. /* the user, so he can use more meaningful names.                   */
  51. void getnames(void)
  52. {
  53. char var,index;
  54. char dummy[80];
  55.  
  56.    col = 1;                      /* skip over and ignore the # sign */
  57.    do {
  58.       if (inline[col] == ' ') col++;   /* ignore all leading blanks */
  59.       else {
  60.          var = inline[col] - 'A';
  61.          if ((var >= 0) && (var <= 5)) {             /* A through F */
  62.             col++;
  63.             if (inline[col] != '-') {           /* should be a dash */
  64.                errchk(14);
  65.                errout();
  66.                return;
  67.             }
  68.             col++;
  69.             for (index = 0;index < 6;index++)
  70.                if (isalpha(inline[col]) || isdigit(inline[col])) {
  71.                   dummy[index] = inline[col];
  72.                   dummy[index + 1] = 0;
  73.                   col++;
  74.                }
  75.             if (index > 0) {
  76.                strcpy(allvars[var].varname,dummy);
  77.                strcpy(strngout,"      ");         /* this is for    */
  78.                strngout[6-strlen(dummy)] = 0;     /* leading blanks */
  79.                strcat(strngout,dummy);
  80.                strngdis(var + 1,1,valattr);
  81.             }
  82.          }
  83.          else if ((var >= 8) && (var <= 13)) {       /* I through N */
  84.             col++;
  85.             if (inline[col] != '-') {           /* should be a dash */
  86.                errchk(14);
  87.                errout();
  88.                return;
  89.             }
  90.             col++;
  91.             if ((inline[col] == 'O') || (inline[col] == 'D') ||
  92.                 (inline[col] == 'H') || (inline[col] == 'X')) {
  93.                var -= 2;
  94.                allvars[var].outtype = inline[col];
  95.                col++;
  96.             }
  97.             else {
  98.                errchk(15);
  99.                errout();
  100.                return;
  101.             }
  102.          }
  103.          else {                            /* unknown variable name */
  104.             errchk(3);
  105.             errout();
  106.             return;
  107.          }
  108.       }
  109.    } while (inline[col] && (errcode == 0));
  110. }
  111.  
  112. /* ******************************************************* calcdata */
  113. /* This is the function that actually does the work of deciding     */
  114. /* what calculations need to be done. The method used is described  */
  115. /* in detail below.                                                 */
  116. /*    Three variables and two operators are         number1         */
  117. /*    stored as per the list. "op1" is always         op1           */
  118. /*    a plus or minus, and op2 is always a          number2         */
  119. /*    multiplication or divide. If a plus or          op2           */
  120. /*    minus is found for op2, number1 and           number3         */
  121. /*    number2 are combined according to op1                         */
  122. /*    and the result becomes number1, the new op2 becomes op1, and  */
  123. /*    number3 becomes number2. If op2 is either a multiplication or */
  124. /*    divide, number2 and number3 are combined according to op2 and */
  125. /*    the result is placed in number2. When a parentheses is found, */
  126. /*    a recursive call is made and the expression in the parenthe-  */
  127. /*    ses is evaluated. A bit of study will be very fruitful in     */
  128. /*    understanding this operation.                                 */
  129. void calcdata(double *newval)
  130. {
  131. double number1,number2,number3,getnum();
  132. char op1,op2,getop();
  133.    number1 = 0.0;
  134.    op1 = '+';
  135.    number2 = 0.0;
  136.    while (inline[col] == ' ') col++;               /* ignore blanks */
  137.                                         /* check for unary operator */
  138.    if ((inline[col] == '+') || (inline[col] == '-')) {
  139.       op1 = inline[col];
  140.       col++;
  141.    }
  142.  
  143.    number2 = getnum();          /* (inline[col]== 0 ) = End of line */
  144.                                 /* (inline[col]=='$') = End of line */
  145.    if ((inline[col] == 0) || (inline[col] =='$')) {
  146.       calcdat(&number1,&op1,&number2);
  147.       *newval = number1;
  148.       return;
  149.    }
  150.    for (;;){
  151.       op2 = getop();
  152.       col++;
  153.                                /* check for end of line  0, ), or $ */
  154.       if (op2 == '$') op2 = 0;        /* force a $ to lool like eol */
  155.       if ((op2 == 0) || (op2 == ')')) {
  156.          col++;
  157.          calcdat(&number1,&op1,&number2);
  158.          *newval = number1;
  159.          return;
  160.       }
  161.       number3 = getnum();
  162.       if ((op2 == '*') || (op2 == '/')){
  163.          calcdat(&number2,&op2,&number3);
  164.       }
  165.       else{
  166.          calcdat(&number1,&op1,&number2);
  167.          op1 = op2;
  168.          number2 = number3;
  169.       }
  170.    } /* end of infinite for loop */
  171. }
  172.  
  173. /* ******************************************************** calcdat */
  174. /* This function actually does the calculations described in the    */
  175. /* function above.                                                  */
  176. void calcdat(double *number1,char *op1,double *number2)
  177. {
  178.    switch (*op1) {
  179.       case '*' : *number1 = (*number1)*(*number2);
  180.                  break;
  181.       case '/' : if (*number2 == 0.0) {
  182.                      errchk(10);
  183.                      break;
  184.                  }
  185.                  *number1 = (*number1)/(*number2);
  186.                  break;
  187.       case '+' : *number1 = *number1 + *number2;
  188.                  break;
  189.       case '-' : *number1 = *number1 - *number2;
  190.                  break;
  191.       default  : break;
  192.    }
  193.    return;
  194. }
  195.  
  196. /* ********************************************************* getnum */
  197. /* This is the workhorse of the program. It actually scans the data */
  198. /* input field and converts the data into numbers which are in the  */
  199. /* internal format of the computer so the calculations can be done. */
  200. double getnum(void)
  201. {
  202. int index,i,decpt;
  203. double newval;
  204. char name[7];
  205. double sqrt(), exp(), log(), sin(), cos(), atan();
  206.  
  207.    while (inline[col] == ' ') col++;               /* ignore blanks */
  208.  
  209.    index = inline[col];
  210.    if (index == '('){
  211.        col++;
  212.        calcdata(&newval);                         /* recursive call */
  213.        col--;
  214.        return(newval);
  215.    }
  216.  
  217.    decpt = 0;                         /* search for a decimal point */
  218.    i = col;
  219.    index = inline[i];
  220.    while ((index >= '0') && (index <= '9')) {
  221.       i++;
  222.       index = inline[i];
  223.       if (index == '.') decpt = 1;
  224.    }
  225.  
  226.    index = inline[col];
  227.    if (((index > '0') && (index <= '9')) ||
  228.        ((index == '0') && (decpt == 1))  ||
  229.         (index == '.')) {                        /* floating number */
  230.       newval = 0.0;
  231.       while ((index >= '0') && (index <= '9')) {
  232.          newval = 10.0*newval + (index - '0');
  233.          col++;
  234.          index = inline[col];
  235.       }
  236.       if (index == '.') {
  237.          double constant = 0.1;
  238.          col++;
  239.          index = inline[col];
  240.          while ((index >= '0') && (index <= '9')) {
  241.             newval = newval + (index - '0') * constant;
  242.             constant *= 0.1;
  243.             col++;
  244.             index = inline[col];
  245.          }
  246.       }
  247.       return(newval);
  248.    }                                /* end of floating point number */
  249.  
  250.    if (index == '0') {                      /* octal or hexadecimal */
  251.       col++;
  252.       index = inline[col];
  253.       if ((index == 'x') || (index == 'X')){         /* hexadecimal */
  254.          col++;
  255.          index = inline[col];
  256.          newval = 0.0;
  257.          while (((index >= '0') && (index <= '9')) ||
  258.                 ((index >= 'A') && (index <= 'F')) ||
  259.                 ((index >= 'a') && (index <= 'f'))) {
  260.             switch (index) {
  261.                case '0':
  262.                case '1':
  263.                case '2':
  264.                case '3':
  265.                case '4':
  266.                case '5':
  267.                case '6':
  268.                case '7':
  269.                case '8':
  270.                case '9':i = index - '0';
  271.                         break;
  272.                case 'A':
  273.                case 'B':
  274.                case 'C':
  275.                case 'D':
  276.                case 'E':
  277.                case 'F':i = index - 'A' + 10;
  278.                         break;
  279.                case 'a':
  280.                case 'b':
  281.                case 'c':
  282.                case 'd':
  283.                case 'e':
  284.                case 'f':i = index - 'a' + 10;
  285.                         break;
  286.                default :break;
  287.             }
  288.             newval = 16.0*newval + i;
  289.             col++;
  290.             index = inline[col];
  291.          }
  292.       return(newval);
  293.       }                                  /* end of hexadecimal 'if' */
  294.  
  295.       else {                                               /* octal */
  296.          newval = 0.0;
  297.          while ((index >= '0') && (index <= '7')) {
  298.             newval = 8.0*newval + (index - '0');
  299.             col++;
  300.             index = inline[col];
  301.          }
  302.       return(newval);
  303.       }                                      /* end of octal 'else' */
  304.  
  305.    }                         /* end of octal or hexadecimal numbers */
  306.  
  307.                                   /* find variable or function name */
  308.    if ((inline[col] >= 'A') && (inline[col] <= 'Z')) {
  309.       name[0] = inline[col++];
  310.       i = 1;
  311.       while ((((inline[col] >= 'A') && (inline[col] <= 'Z')) ||
  312.              ((inline[col] >= '0') && (inline[col] <= '9'))) &&
  313.              (i <= 5)) {           /* continue var or function name */
  314.          name[i++] = inline[col++];
  315.       }
  316.       name[i] = 0;                                    /* name found */
  317.  
  318.       if (inline[col] == '('){                     /* function call */
  319.          col++;
  320.          if (strcmp(name,"ABS") == 0) {
  321.             calcdata(&newval);
  322.             if (newval < 0.0) newval = -newval;
  323.          }
  324.          else if (strcmp(name,"SQRT") == 0) {
  325.             calcdata(&newval);
  326.             if (newval < 0.0) {
  327.                errchk(5);                     /* Neg value for SQRT */
  328.                newval = 0.0;
  329.             }
  330.             else newval = sqrt(newval);
  331.          }
  332.          else if (strcmp(name,"FACT") == 0) {
  333.             calcdata(&newval);
  334.             if (newval < 0.0) {
  335.                errchk(16);                    /* Neg value for FACT */
  336.                newval = 0.0;
  337.             }
  338.             else {
  339.             double count;
  340.             int howmany;
  341.                count = newval;
  342.                newval = 1.0;
  343.                for (howmany = count;howmany > 1;howmany--) {
  344.                   count = howmany;
  345.                   newval = newval * count;
  346.                }
  347.             }
  348.          }
  349.          else if (strcmp(name,"EXP") == 0) {
  350.             calcdata(&newval);
  351.             newval = exp(newval);
  352.          }
  353.          else if (strcmp(name,"LOG") == 0) {
  354.             calcdata(&newval);
  355.             if (newval < 0.0) {
  356.                errchk(7);                      /* Neg value for LOG */
  357.                newval = 0.0;
  358.             }
  359.             else newval = log(newval);
  360.          }
  361.          else if (strcmp(name,"SIN") == 0){
  362.             calcdata(&newval);
  363.             newval = sin(newval);
  364.          }
  365.          else if (strcmp(name,"COS") == 0){
  366.             calcdata(&newval);
  367.             newval = cos(newval);
  368.          }
  369.          else if (strcmp(name,"ATAN") == 0){
  370.             calcdata(&newval);
  371.             newval = atan(newval);
  372.          }
  373.          else {
  374.             errchk(6);                        /* function not found */
  375.             newval = 0.0;
  376.          }
  377.          col--;
  378.          return(newval);
  379.       }                                     /* end of function call */
  380.  
  381.       else {                                       /* variable name */
  382.          for (i = 0;i < 12;i++) {
  383.             if ((strcmp(name,allvars[i].varname)) == 0) {
  384.                newval = allvars[i].value;
  385.                return(newval);
  386.             }
  387.          }
  388.          errchk(3);                           /* variable not found */
  389.          newval = 0.0;
  390.          return(newval);
  391.       }                                     /* end of variable call */
  392.  
  393.    }                            /* end of variable or function call */
  394.    errchk(9);
  395.    return(0.0);                               /* invalid data found */
  396. }
  397.  
  398. /* ********************************************************** getop */
  399. /* A call to this function expects to find an operator, end of line */
  400. /* or a close parenthesis.                                          */
  401. char getop(void)
  402. {
  403.    while (inline[col] == ' ') col++;               /* ignore blanks */
  404.    switch (inline[col]){
  405.       case '$':
  406.       case ')':
  407.       case  0 :
  408.       case '+':
  409.       case '-':
  410.       case '*':
  411.       case '/': break;
  412.       default : errchk(4);                      /* invalid operator */
  413.    }
  414.    return(inline[col]);
  415. }
  416.  
  417. /* ********************************************************* errchk */
  418. /* The error code is stored by this function and the cursor column  */
  419. /* is adjusted in an attempt to put the cursor near the error that  */
  420. /* caused the problem.                                              */
  421. void errchk(int err)
  422. {
  423.    if(errcode) return;                       /* error already found */
  424.    else {                         /* only the first error is stored */
  425.       errcode = err;                      /* store the error number */
  426.       switch (err){
  427.          case 2  :
  428.          case 4  :
  429.          case 8  :
  430.          case 9  :
  431.          case 10 :
  432.          case 11 :
  433.          case 12 : colerr = col;
  434.                    break;
  435.          case 1  :
  436.          case 3  : colerr = col - 1;
  437.                    break;
  438.          case 6  : colerr = col - 2;
  439.                    break;
  440.          case 5  :
  441.          case 7  : colerr = col - 3;
  442.                    break;
  443.          default : colerr = col;
  444.       }
  445.    }
  446. }
  447.