⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 calc.c

📁 功能强大的文本编辑器
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  calc.c                                              06.08.02
**
**  integer calculator  
**  
**    library module v2.0
**  
**  
*/


#include "config.h"
#include "standard.h"
#include "microsft.h"
#include "mb_ctype.h"

#undef toupper
#undef tolower
#undef isdigit
#undef isxdigit
#undef isprint
#undef isspace

#include <ctype.h>

#define  __CALC__

#include "calc.h"
#include "calchlp.h"
#include "ansi_out.h"


/**************************************************************
*                                                             *
*                  DEBUG SECTION                              *
*                                                             *
**************************************************************/

#if DEBUG
#define ON_DEB(c)   c
#define D_MSG(f,a)  if (trace) printf("%2d %2d%*s ", nest, level, nest, ""), printf(f,a,a)
#else
#define ON_DEB(c)
#define D_MSG(f,a)
#endif

static char eval_msg[]       = "Evaluate : ";
#if DEBUG
static char fmt_term[]       = "";
static char fmt_expression[] = "Expression \"%s\"\n";
static char fmt_operand[]    = "Operand    \"%s\"\n";
static char fmt_token[]      = "  Token  => \"%s\"\n";
static char fmt_number[]     = "  Number => %ld %lXh\n";
static int  nest;
#endif


/**************************************************************
*                                                             *
*                  DATA SECTION                               *
*                                                             *
**************************************************************/

/*
**  operand delimiters
*/
char delimiter [] = " \t(){}[]!~*/%+-<>=&^|;:,\\\"?@#$";

/*
**  error handling
**
**    1.  remember error number and position
**    2.  avoid multible error outputs
**    3.  call user's error handler
**
*/
struct ERROR {
  char * ptr;                       /* pointer to error position in expr */
  int    no;                        /* error number */
};

static  enum RESULT_TYPE expr_type; /* type of expression  */
static  int expr_err;               /* boolean expression error */
static  struct ERROR error_report;  /* error to report */

static  int level;                  /* parenthese nesting level */

enum TOKEN                          /* symbolic token is index in array(s) */
{
  PAREN,  NOT,    CMPL,   PWR,    MUL,    DIV,    MOD,    MODULO,
  PLUS,   MINUS,
  SL,     SR,     SAL,    SAR,    SHL,    SHR,    ROL,    ROR,    
  LE,     LEQ,    GT,     GEQ,    EQ,     UNEQ,   UNEQU,  AND,    XOR,    OR,
  LAND,   LOR,    ASSIGN, MULASS, DIVASS, MODASS, ADDASS, SUBASS, SALASS,
  SARASS, ANDASS, XORASS, ORASS,  CLPAR,  EOEXPR, INVAL,  OP_NUM
};

/*
**  unary operators
**
**    precedence:     equal
**    associativity:  right to left
**
**  operators
**
**    precedence:     table
**    accociativity:  left to right
**
*/
#define UNARY   0x01
#define NORM    0x02
#define ALL     (NORM | UNARY)

#define OP_MAXL 3

struct OPERATORS
{
  char  lexeme [OP_MAXL+1];
  char  use;
  char  precedence;
}
operators [OP_NUM] =
{
/*lexeme use    p    lexeme use    p    lexeme use    p    lexeme use    p */
  "(",   UNARY, 0,
  "!",   UNARY, 1,   "~",   UNARY, 1,
  "**",  NORM,  2,
  "*",   NORM,  3,   "/",   NORM,  3,   "%",   NORM,  3,   "\\",  NORM,  3,
  "+",   ALL,   4,   "-",   ALL,   4,
  "<<",  NORM,  5,   ">>",  NORM,  5,   "SAL", NORM,  5,   "SAR", NORM,  5,
  "SHL", NORM,  5,   "SHR", NORM,  5,   "ROL", NORM,  5,   "ROR", NORM,  5,   
  "<",   NORM,  6,   "<=",  NORM,  6,   ">",   NORM,  6,   ">=",  NORM,  6,
  "==",  NORM,  7,   "!=",  NORM,  7,   "<>",  NORM,  7,
  "&",   NORM,  8,
  "^",   NORM,  9,
  "|",   NORM,  10,
  "&&",  NORM,  11,
  "||",  NORM,  12,
  "=",   NORM,  13,  "*=",  NORM,  13,  "/=",  NORM,  13,  "%=",  NORM,  13,
  "+=",  NORM,  13,  "-=",  NORM,  13,  "<<=", NORM,  13,  ">>=", NORM,  13,
  "&=",  NORM,  13,  "^=",  NORM,  13,  "|=",  NORM,  13,
  ")",   ALL,   14,
  ";",   NORM,  15,
  "",    ALL,   16
};


/**************************************************************
*                                                             *
*                  ERRORS                                     *
*                                                             *
**************************************************************/

static void error(int err)
{
  if (!expr_err)
  {
    error_report.no = err;
    error_report.ptr = expr_ptr;
    expr_err = TRUE;
  }
}


/**************************************************************
*                                                             *
*                  EVALUATE                                   *
*                                                             *
**************************************************************/

static VAR_T eval_term(enum TOKEN token, VAR_T op1, VAR_T op2)
{
  D_MSG(fmt_term, 0);
  if (trace)
    prints(eval_msg),
      printld(op1), prints(operators[token].lexeme), printld(op2);

  switch (token)
  {
    case NOT:     op1 = !op2;
                  break;

    case CMPL:    op1 = ~op2;
                  break;

    case PWR   :  {
                    VAR_T help = 1;
                    if(op2 < 0)
                      while(op2++) help /= op1;
                    else
                      while(op2--) help *= op1;
                    op1 = help;
                  }
                  break;

    case MUL   :  op1 *= op2;
                  break;

    case DIV   :  if (op2 == 0L)
                    op1 = MAX_VAL, error(DIV_BY_ZERO);
                  else
                    op1 /= op2;
                  break;

    case MODULO:  
    case MOD   :  if (op2 == 0L)
                    op1 = 0;
                  else
                    op1 %= op2;
                  break;

    case PLUS  :  op1 += op2;
                  break;

    case MINUS :  op1 -= op2;
                  break;

    case SL    :
    case SAL   :  op1 <<= op2;
                  break;

    case SR    :
    case SAR   :  op1 >>= op2;
                  break;

    case ROL   :  op1 = _lrotl((unsigned long)op1,(int)op2);
                  break;

    case ROR   :  op1 = _lrotr((unsigned long)op1,(int)op2);
                  break;

    case SHL   :  op1 = (unsigned long)op1 << op2;
                  break;

    case SHR   :  op1 = (unsigned long)op1 >> op2;
                  break;

    case LE    :  op1 = op1 < op2;
                  break;

    case LEQ   :  op1 = op1 <= op2;
                  break;
                  
    case GT    :  op1 = op1 > op2;
                  break;

    case GEQ   :  op1 = op1 >= op2;
                  break;

    case EQ    :  op1 = op1 == op2;
                  break;

    case UNEQU :
    case UNEQ  :  op1 = op1 != op2;
                  break;

    case AND   :  op1 &= op2;
                  break;

    case XOR   :  op1 ^= op2;
                  break;

    case OR    :  op1 |= op2;
                  break;

    case LAND  :  op1 = op1 && op2;
                  break;

    case LOR   :  op1 = op1 || op2;
                  break;

    case ASSIGN:  op1 = op2;
                  break;

    case MULASS:  op1 *= op2;
                  break;

    case DIVASS:  if (op2 == 0L)
                    op1 = MAX_VAL, error(DIV_BY_ZERO);
                  else
                    op1 /= op2;
                  break;

    case MODASS:  if (op2 == 0L)
                    op1 = 0;
                  else
                    op1 %= op2;
                  break;

    case ADDASS:  op1 += op2;
                  break;

    case SUBASS:  op1 -= op2;
                  break;

    case SALASS:  op1 <<= op2;
                  break;

    case SARASS:  op1 >>= op2;
                  break;

    case ANDASS:  op1 &= op2;
                  break;

    case XORASS:  op1 ^= op2;
                  break;

    case ORASS:   op1 |= op2;
                  break;

    case EOEXPR:  
    case CLPAR :  op2 = 0;
                  break;
  }               
  if (trace)
    prints(" = "), printld(op1), putchar('\n');
  return (op1);
}


/**************************************************************
*                                                             *
*                  OPERATOR / TOKEN                           *
*                                                             *
**************************************************************/

/*
**  find operator
**
**    returns:
**      token of matching operator
*/
static int find_operator(char * s, int mask)
{
  int ll, token = 0, lmatch = 0, match = INVAL;
      
  while (token < OP_NUM)
  {
    if (operators[token].use & mask)
      if ((ll = strlcmp(s, operators[token].lexeme)) > lmatch)
      {
        lmatch = ll, match = token;
      }
    token++;
  }
  return (match);
}

/*
**  report if end of expression
*/
static int end_of_expr(int token)
{
  return ((token == EOEXPR) || (token == INVAL));
}

/*
**  report if end of parenthesed expression
*/
static int end_of_paren(int token)
{
  return ((token == CLPAR) || (token == EOEXPR) || (token == INVAL));
}

/*
**  report precedence of operators
**
**    returns:
**      -1  oper1 < oper2
**       0  oper1 = oper2
**       1  oper1 > oper2
*/
static int precedence(int tk1, int tk2)
{
  /* --  special cases: */
  if (end_of_paren(tk1))
    /* --  evaluate unconditionally */
    return (1);

  if ((tk1 == PWR) && (tk2 == PWR))
    /* --  evaluate right to left */
    return (-1);
  
  /* --  return precedence difference */
  return (operators[tk2].precedence - operators[tk1].precedence);
}


/**************************************************************
*                                                             *
*                  PARSING OPERATORS                          *
*                                                             *
**************************************************************/

/*
**  report next token in string
*/
static int look_token(int * token, int mask)
{
  char str [OP_MAXL+1];
  int ll;

  if (!*(expr_ptr = skipwhites(expr_ptr)))
    *token = EOEXPR; /* end of expression string */
  else
  {
    for (ll=0; (ll < OP_MAXL); ll++)
      str[ll] = (char)toupper(expr_ptr[ll]);
    str[ll] = '\0';

    *token = find_operator(str, mask);
  }
  ON_DEB( if (*operators[*token].lexeme)
            D_MSG(fmt_token, operators[*token].lexeme));
  
  return (strlen(operators[*token].lexeme));
}

/*
**  parse token from string
**
**    returns:
**      token,
**      pointer behind operator in expr
*/
static int get_token(int * token, int mask)
{
  int ll = look_token(token, mask);
  if (*expr_ptr)
    advance(ll);
  return (ll);
}


/**************************************************************
*                                                             *
*                  PARSING NUMBERS                            *
*                                                             *
**************************************************************/

/*
**  read decimal constant
*/
long get_decimal(int length)
{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -