home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / os2 / remind / src / expr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-12  |  37.4 KB  |  1,279 lines

  1. /***************************************************************/
  2. /*                                                             */
  3. /*  EXPR.C                                                     */
  4. /*                                                             */
  5. /*  This file contains routines to parse and evaluate          */
  6. /*  expressions.                                               */
  7. /*                                                             */
  8. /*  Copyright 1992, 1993 by David F. Skoll.                    */
  9. /*                                                             */
  10. /***************************************************************/
  11.  
  12. #include "config.h"
  13. #include <stdio.h>
  14. #include <ctype.h>
  15. #include <string.h>
  16. #ifdef HAVE_STDLIB_H
  17. #include <stdlib.h>
  18. #endif
  19. #ifdef HAVE_MALLOC_H
  20. #include <malloc.h>
  21. #endif
  22. #include "err.h"
  23. #include "types.h"
  24. #include "expr.h"
  25. #include "protos.h"
  26. #include "globals.h"
  27.  
  28. #define ISID(c) (isalnum(c) || (c) == '_')
  29. #define EQ 0
  30. #define GT 1
  31. #define LT 2
  32. #define GE 3
  33. #define LE 4
  34. #define NE 5
  35.  
  36. static char ExprBuf[TOKSIZE+1];
  37. static char CoerceBuf[TOKSIZE+1];
  38. extern int NumFuncs;
  39.  
  40. #ifdef HAVE_PROTOS
  41. PRIVATE int Multiply(void), Divide(void), Mod(void), Add(void),
  42.        Subtract(void), GreaterThan(void), LessThan(void),
  43.        EqualTo(void), NotEqual(void), LessOrEqual(void),
  44.        GreaterOrEqual(void), LogAND(void), LogOR(void),
  45.        UnMinus(void), LogNot(void),
  46.        Compare(int);
  47. #else
  48. PRIVATE int Multiply(), Divide(), Mod(), Add(),
  49.        Subtract(), GreaterThan(), LessThan(),
  50.        EqualTo(), NotEqual(), LessOrEqual(),
  51.        GreaterOrEqual(), LogAND(), LogOR(),
  52.            UnMinus(), LogNot(), Compare();
  53. #endif
  54.  
  55. PRIVATE int MakeValue ARGS ((char *s, Value *v, Var *locals));
  56. PRIVATE int PushOpStack ARGS ((Operator *op));
  57. PRIVATE int PopOpStack ARGS ((Operator *op));
  58. PRIVATE int ParseLiteralDate ARGS ((char **s, int *jul));
  59.  
  60. /* Binary operators - all left-associative */
  61.  
  62. /* Make SURE they are sorted lexically... this may die on an EBCDIC
  63.    system... */
  64.  
  65. Operator BinOp[] = {
  66.    { "!=", 15, BIN_OP, NotEqual },
  67.    { "%", 20, BIN_OP, Mod },
  68.    { "&&", 14, BIN_OP, LogAND },
  69.    { "*", 20, BIN_OP, Multiply },
  70.    { "+", 18, BIN_OP, Add },
  71.    { "-", 18, BIN_OP, Subtract },
  72.    { "/", 20, BIN_OP, Divide },
  73.    { "<", 16, BIN_OP, LessThan },
  74.    { "<=", 16, BIN_OP, LessOrEqual },
  75.    { "==", 15, BIN_OP, EqualTo },
  76.    { ">", 16, BIN_OP, GreaterThan },
  77.    { ">=", 16, BIN_OP, GreaterOrEqual },
  78.    { "||", 12, BIN_OP, LogOR },
  79. };
  80. #define NUM_BIN_OPS (sizeof(BinOp) / sizeof(Operator))
  81.  
  82. /* These ones must be sorted too. */
  83. Operator UnOp[] = {
  84.    { "!", 22, UN_OP, LogNot },
  85.    { "-", 22, UN_OP, UnMinus },
  86. };
  87. #define NUM_UN_OPS (sizeof(UnOp) / sizeof(Operator))
  88.  
  89. /* Functions have the same definitions as operators, except the prec field
  90.    is used to indicate how many arguments are needed. */
  91. extern Operator Func[];
  92.  
  93. Operator OpStack[OP_STACK_SIZE];
  94. Value    ValStack[VAL_STACK_SIZE];
  95. int OpStackPtr, ValStackPtr;
  96.  
  97. /***************************************************************/
  98. /*                                                             */
  99. /*  DebugPerform                                               */
  100. /*                                                             */
  101. /*  Execute an operator or function with debugging.            */
  102. /*                                                             */
  103. /***************************************************************/
  104. #ifdef HAVE_PROTOS
  105. PRIVATE int DebugPerform(Operator *op)
  106. #else
  107. static int DebugPerform(op)
  108. Operator *op;
  109. #endif
  110. {
  111.    int r;
  112.  
  113.    if (op->type == UN_OP) {
  114.       fprintf(ErrFp, "%s ", op->name);
  115.       PrintValue(&ValStack[ValStackPtr-1], ErrFp);
  116.    } else { /* Must be binary operator */
  117.       PrintValue(&ValStack[ValStackPtr-2], ErrFp);
  118.       fprintf(ErrFp, " %s ", op->name);
  119.       PrintValue(&ValStack[ValStackPtr-1], ErrFp);
  120.    }
  121.  
  122.    r = (op->func)();
  123.    fprintf(ErrFp, " => ");
  124.    if (!r) {
  125.       PrintValue(&ValStack[ValStackPtr-1], ErrFp);
  126.       putc('\n', ErrFp);
  127.    } else {
  128.       fprintf(ErrFp, "%s\n", ErrMsg[r]);
  129.    }
  130.    return r;
  131. }
  132.  
  133. /***************************************************************/
  134. /*                                                             */
  135. /*  CleanStack                                                 */
  136. /*                                                             */
  137. /*  Clean the stack after an error occurs.                     */
  138. /*                                                             */
  139. /***************************************************************/
  140. #ifdef HAVE_PROTOS
  141. PRIVATE void CleanStack(void)
  142. #else
  143. static void CleanStack()
  144. #endif
  145. {
  146.    int i;
  147.  
  148.    for (i=0; i<ValStackPtr; i++) DestroyValue(&ValStack[i]);
  149.    ValStackPtr = 0;
  150. }
  151.  
  152. /***************************************************************/
  153. /*                                                             */
  154. /*  PeekChar - peek ahead to next char.                        */
  155. /*                                                             */
  156. /***************************************************************/
  157. #ifdef HAVE_PROTOS
  158. PRIVATE char PeekChar(char **s)
  159. #else
  160. static char PeekChar(s)
  161. char **s;
  162. #endif
  163. {
  164.    char *t = *s;
  165.    while (*t && isspace(*t)) t++;
  166.    return *t;
  167. }
  168.  
  169. /***************************************************************/
  170. /*                                                             */
  171. /*  ParseExprToken                                             */
  172. /*                                                             */
  173. /*  Read a token.                                              */
  174. /*                                                             */
  175. /***************************************************************/
  176. #ifdef HAVE_PROTOS
  177. PRIVATE int ParseExprToken(char *out, char **in)
  178. #else
  179. static int ParseExprToken(out, in)
  180. char *out;
  181. char **in;
  182. #endif
  183. {
  184.  
  185.    char c;
  186.    
  187.    *out = 0;
  188. /* Skip white space */
  189.    while (**in && isspace(**in)) (*in)++;
  190.    
  191.    if (!**in) return OK;
  192.  
  193.    *out++ = c = *(*in)++;
  194.    *out = 0;
  195.  
  196.    switch(c) {
  197.       case COMMA:
  198.       case END_OF_EXPR:
  199.       case '+':
  200.       case '-':
  201.       case '*':
  202.       case '/':
  203.       case '(':
  204.       case ')':
  205.       case '%': return OK;
  206.  
  207.       case '&':
  208.       case '|':
  209.       case '=': if (**in == c) {
  210.                 *out++ = c;
  211.                 *out = 0;
  212.                 (*in)++;
  213.            }
  214.              return OK;
  215.              
  216.       case '!':
  217.       case '>':
  218.       case '<': if (**in == '=') {
  219.                 *out++ = '=';
  220.                 *out = 0;
  221.                 (*in)++;
  222.            }
  223.            return OK;
  224.    }           
  225.  
  226.    /* Handle the parsing of quoted strings */
  227.    if (c == '\"') {
  228.       if (!**in) return E_MISS_QUOTE;
  229.       while (**in) if ((c = *out++ = *(*in)++) == '\"') break;
  230.       *out = 0;
  231.       if (c == '\"') return OK ; else return E_MISS_QUOTE;
  232.    }
  233.  
  234.    /* Dates can be specified with single-quotes */
  235.    if (c == '\'') {
  236.       if (!**in) return E_MISS_QUOTE;
  237.       while (**in) if ((c = *out++ = *(*in)++) == '\'') break;
  238.       *out = 0;
  239.       if (c == '\'') return OK ; else return E_MISS_QUOTE;
  240.    }
  241.  
  242.    if (!ISID(c) && c != '$') {
  243.       Eprint("%s '%c'", ErrMsg[E_ILLEGAL_CHAR], c);
  244.       return E_ILLEGAL_CHAR;
  245.    }
  246.  
  247.    /* Parse a constant, variable name or function */
  248.    while (ISID(**in) || **in == ':' || **in == '.' || **in == TIMESEP)
  249.       *out++ = *(*in)++;
  250.  
  251.    /* Chew up any remaining white space */
  252.    while (**in && isspace(**in)) (*in)++;
  253.  
  254.    /* Peek ahead - is it '('?  Then we have a function call */
  255.    if (**in == '(') *out++ = *(*in)++;
  256.  
  257.    *out = 0;
  258.    return OK;
  259. }
  260.  
  261. /***************************************************************/
  262. /*                                                             */
  263. /*  EvalExpr                                                   */
  264. /*  Evaluate an expression.  Return 0 if OK, non-zero if error */
  265. /*  Put the result into value pointed to by v.                 */
  266. /*                                                             */
  267. /***************************************************************/
  268. #ifdef HaveProtos
  269. PUBLIC int EvalExpr(char **e, Value *v)
  270. #else
  271. int EvalExpr(e, v)
  272. char **e;
  273. Value *v;
  274. #endif
  275. {
  276.    int r;
  277.  
  278.    OpStackPtr = 0;
  279.    ValStackPtr = 0;
  280.    r = Evaluate(e, NULL);
  281.  
  282.    /* Put last character parsed back onto input stream */
  283.    if (*ExprBuf) (*e)--;
  284.  
  285.    if (r) {
  286.       CleanStack();
  287.       return r;
  288.    }
  289.    r = CopyValue(v, ValStack);
  290.    DestroyValue(ValStack);
  291.    return r;
  292. }
  293.  
  294. /* Evaluate - do the actual work of evaluation. */
  295. #ifdef HAVE_PROTOS
  296. PUBLIC int Evaluate(char **s, Var *locals)
  297. #else
  298. int Evaluate(s, locals)
  299. char **s;
  300. Var *locals;
  301. #endif
  302. {
  303.    int OpBase, ValBase;
  304.    int r;
  305.    Operator *f;
  306.    int args; /* Number of function arguments */
  307.    Operator op, op2;
  308.    Value va;
  309.    char *ufname = NULL; /* Stop GCC from complaining about use of uninit var */
  310.    
  311.    OpBase = OpStackPtr;
  312.    ValBase = ValStackPtr;
  313.    
  314.    while(1) {
  315. /* Looking for a value.  Accept: value, unary op, func. call or left paren */
  316.       r = ParseExprToken(ExprBuf, s);
  317.       if (r) return r;
  318.       if (!*ExprBuf) return E_EOLN;
  319.  
  320.       if (*ExprBuf == '(') { /* Parenthesized expression */
  321.      r = Evaluate(s, locals);  /* Leaves the last parsed token in ExprBuf */
  322.          if (r) return r;
  323.      if (*ExprBuf != ')') return E_MISS_RIGHT_PAREN;
  324.       } else if (*ExprBuf == '+') continue; /* Ignore unary + */
  325.       else if (*(ExprBuf + strlen(ExprBuf) -1) == '(') { /* Function Call */
  326.      *(ExprBuf + strlen(ExprBuf) - 1) = 0;
  327.      f = FindFunc(ExprBuf, Func, NumFuncs);
  328.      if (!f) {
  329.         ufname = StrDup(ExprBuf);
  330.         if (!ufname) return E_NO_MEM;
  331.      }
  332.      args = 0;
  333.      if (PeekChar(s) == ')') { /* Function has no arguments */
  334.         if (f) r = CallFunc(f, 0);
  335.         else {
  336.            r = CallUserFunc(ufname, 0);
  337.            free(ufname);
  338.         }
  339.         if (r) return r;
  340.         (void) ParseExprToken(ExprBuf, s); /* Guaranteed to be right paren. */
  341.      } else { /* Function has some arguments */
  342.         while(1) {
  343.            args++;
  344.            r = Evaluate(s, locals);
  345.            if (r) {
  346.               if (!f) free(ufname);
  347.               return r;
  348.            }
  349.            if (*ExprBuf == ')') break;
  350.            else if (*ExprBuf != ',') {
  351.               if (!f) free(ufname);
  352.            Eprint("%s: '%c'", ErrMsg[E_EXPECT_COMMA], *ExprBuf);
  353.               return E_EXPECT_COMMA;
  354.                }
  355.             }
  356.         if (f) r = CallFunc(f, args);
  357.         else {
  358.            r = CallUserFunc(ufname, args);
  359.            free(ufname);
  360.         }
  361.         if (r) return r;
  362.          }
  363.       } else { /* Unary operator */
  364.      f = FindFunc(ExprBuf, UnOp, NUM_UN_OPS);
  365.          if (f) {
  366.             r = PushOpStack(f);
  367.             if (r) return r;
  368.         continue;  /* Still looking for an atomic vlue */
  369.      } else if (!ISID(*ExprBuf) && *ExprBuf != '$' 
  370.                 && *ExprBuf != '"' && *ExprBuf != '\'') {
  371.             Eprint("%s '%c'", ErrMsg[E_ILLEGAL_CHAR], *ExprBuf);
  372.         return E_ILLEGAL_CHAR;
  373.      } else { /* Must be a literal value */
  374.         r = MakeValue(ExprBuf, &va, locals);
  375.         if (r) return r;
  376.         r = PushValStack(&va);
  377.         if (r) return r;
  378.      }
  379.       }
  380. /* OK, we've got a literal value; now, we're looking for the end of the
  381.       expression, or a binary operator. */
  382.       r = ParseExprToken(ExprBuf, s);
  383.       if (r) return r;
  384.       if (*ExprBuf == 0 || *ExprBuf == ',' || *ExprBuf == ']' || *ExprBuf == ')') {
  385.    /* We've hit the end of the expression.  Pop off and evaluate until
  386.          OpStackPtr = OpBase and ValStackPtr = ValBase+1 */
  387.          while (OpStackPtr > OpBase) {
  388.             r = PopOpStack(&op);
  389.             if (r) return r;
  390.         if (DebugFlag & DB_PRTEXPR)
  391.            r=DebugPerform(&op);
  392.         else
  393.            r=(op.func)();
  394.           if (r) {
  395.            Eprint("'%s': %s", op.name, ErrMsg[r]);
  396.            return r;
  397.             }
  398.      }
  399.          if (ValStackPtr != ValBase+1) return E_STACK_ERR; else return OK;
  400.       }
  401.       /* Must be a binary operator */
  402.       f = FindFunc(ExprBuf, BinOp, NUM_BIN_OPS);
  403.       if (!f) return E_EXPECTING_BINOP;
  404.  
  405.       /* While operators of higher or equal precedence are on the stack,
  406.          pop them off and evaluate */
  407.       while (OpStackPtr > OpBase && OpStack[OpStackPtr-1].prec >= f->prec) {
  408.          r = PopOpStack(&op2);
  409.          if (r) return r;
  410.      if (DebugFlag & DB_PRTEXPR)
  411.         r=DebugPerform(&op2);
  412.      else
  413.         r=(op2.func)();
  414.      if (r) {
  415.         Eprint("'%s': %s", op2.name, ErrMsg[r]);
  416.         return r;
  417.          }
  418.       }
  419.       r = PushOpStack(f);
  420.       if (r) return r;
  421.    }
  422. }
  423.    
  424. /***************************************************************/
  425. /*                                                             */
  426. /*  MakeValue                                                  */
  427. /*  Generate a literal value.  It's either a string, a number, */
  428. /*  a date or the value of a symbol.                           */
  429. /*                                                             */
  430. /***************************************************************/
  431. #ifdef HAVE_PROTOS
  432. PRIVATE int MakeValue(char *s, Value *v, Var *locals)
  433. #else
  434. static int MakeValue(s, v, locals)
  435. char *s;
  436. Value *v;
  437. Var *locals;
  438. #endif
  439. {
  440.    int len;
  441.    int h, m, r;
  442.  
  443.    if (*s == '\"') { /* It's a literal string */
  444.       len = strlen(s)-1;
  445.       v->type = STR_TYPE;
  446.       v->v.str = (char *) malloc(len);
  447.       if (! v->v.str) {
  448.          v->type = ERR_TYPE;
  449.          return E_NO_MEM;
  450.       }
  451.       strncpy(v->v.str, s+1, len-1);
  452.       *(v->v.str+len-1) = 0;
  453.       return OK;
  454.    } else if (*s == '\'') { /* It's a literal date */
  455.       s++;
  456.       if ((r=ParseLiteralDate(&s, &h))) return r;
  457.       if (*s != '\'') return E_BAD_DATE;
  458.       v->type = DATE_TYPE;
  459.       v->v.val = h;
  460.       return OK;
  461.    } else if (isdigit(*s)) { /* It's a number - use len to hold it.*/
  462.       len = 0;
  463.       while (*s && isdigit(*s)) {
  464.          len *= 10;
  465.          len += (*s++ - '0');
  466.       }
  467.       if (*s == ':' || *s == '.' || *s == TIMESEP) { /* Must be a literal time */
  468.      s++;
  469.      if (!isdigit(*s)) return E_BAD_TIME;
  470.      h = len;
  471.      m = 0;
  472.      while (isdigit(*s)) {
  473.         m *= 10;
  474.         m += *s - '0';
  475.         s++;
  476.      }
  477.      if (*s || h>23 || m>59) return E_BAD_TIME;
  478.      v->type = TIM_TYPE;
  479.      v->v.val = h*60 + m;
  480.      return OK;
  481.       }
  482.       /* Not a time - must be a number */
  483.       if (*s) return E_BAD_NUMBER;
  484.       v->type = INT_TYPE;
  485.       v->v.val = len;
  486.       return OK;
  487.    } else if (*s == '$') { /* A system variable */
  488.      if (DebugFlag & DB_PRTEXPR)
  489.         fprintf(ErrFp, "%s => ", s);
  490.      r = GetSysVar(s+1, v);
  491.    
  492.      if (! (DebugFlag & DB_PRTEXPR)) return r;
  493.      if (r == OK) {
  494.         PrintValue(v, ErrFp);
  495.     putc('\n', ErrFp);
  496.      }
  497.      return r;
  498.    } else /* Must be a symbol */
  499.      if (DebugFlag & DB_PRTEXPR)
  500.         fprintf(ErrFp, "%s => ", s);
  501.      r = GetVarValue(s, v, locals);
  502.      if (! (DebugFlag & DB_PRTEXPR)) return r;
  503.      if (r == OK) {
  504.         PrintValue(v, ErrFp);
  505.     putc('\n', ErrFp);
  506.      }
  507.      return r;
  508. }
  509.  
  510. /***************************************************************/
  511. /*                                                             */
  512. /*  PushOpStack                                                */
  513. /*                                                             */
  514. /*  Push an operator onto the operator stack.                  */
  515. /*                                                             */
  516. /***************************************************************/
  517. #ifdef HAVE_PROTOS
  518. PRIVATE int PushOpStack(Operator *op)
  519. #else
  520. static int PushOpStack(op)
  521. Operator *op;
  522. #endif
  523. {
  524.    if (OpStackPtr >= OP_STACK_SIZE)
  525.       return E_OP_STK_OVER;
  526.    else {
  527.       OpStack[OpStackPtr++] = *op;
  528.       return OK;
  529.    }
  530. }
  531.  
  532. /***************************************************************/
  533. /*                                                             */
  534. /*  PushValStack                                               */
  535. /*                                                             */
  536. /*  Push a value onto the value stack.                         */
  537. /*                                                             */
  538. /***************************************************************/
  539. #ifdef HAVE_PROTOS
  540. PUBLIC int PushValStack(Value *val)
  541. #else
  542. int PushValStack(val)
  543. Value *val;
  544. #endif
  545. {
  546.    if (ValStackPtr >= VAL_STACK_SIZE)
  547.       return E_VA_STK_OVER;
  548.    else {
  549.       ValStack[ValStackPtr++] = *val;
  550.       return OK;
  551.    }
  552. }
  553.  
  554. /***************************************************************/
  555. /*                                                             */
  556. /*  PopOpStack                                                 */
  557. /*                                                             */
  558. /*  Pop an operator from the operator stack.                   */
  559. /*                                                             */
  560. /***************************************************************/
  561. #ifdef HAVE_PROTOS
  562. PRIVATE int PopOpStack(Operator *op)
  563. #else
  564. static int PopOpStack(op)
  565. Operator *op;
  566. #endif
  567. {
  568.    if (OpStackPtr <= 0)
  569.       return E_OP_STK_UNDER;
  570.    else {
  571.       *op = OpStack[--OpStackPtr];
  572.       return OK;
  573.    }
  574. }
  575.  
  576. /***************************************************************/
  577. /*                                                             */
  578. /*  PopValStack                                               */
  579. /*                                                             */
  580. /*  Pop a value onto the value stack.                         */
  581. /*                                                             */
  582. /***************************************************************/
  583. #ifdef HAVE_PROTOS
  584. PUBLIC int PopValStack(Value *val)
  585. #else
  586. int PopValStack(val)
  587. Value *val;
  588. #endif
  589. {
  590.    if (ValStackPtr <= 0)
  591.       return E_VA_STK_UNDER;
  592.    else {
  593.       *val = ValStack[--ValStackPtr];
  594.       return OK;
  595.    }
  596. }
  597.  
  598. /***************************************************************/
  599. /*                                                             */
  600. /*  DoCoerce - actually coerce a value to the specified type.  */
  601. /*                                                             */
  602. /***************************************************************/
  603. #ifdef HAVE_PROTOS
  604. PUBLIC int DoCoerce(char type, Value *v)
  605. #else
  606. int DoCoerce(type, v)
  607. char type;
  608. Value *v;
  609. #endif
  610. {
  611.    int h, d, m, y, i;
  612.    char *s;
  613.    
  614.    /* Do nothing if value is already the right type */
  615.    if (type == v->type) return OK;
  616.    
  617.    switch(type) {
  618.       case STR_TYPE:
  619.          switch(v->type) {
  620.             case INT_TYPE: sprintf(CoerceBuf, "%d", v->v.val); break;
  621.             case TIM_TYPE: sprintf(CoerceBuf, "%02d%c%02d", v->v.val / 60, 
  622.                    TIMESEP, v->v.val % 60);
  623.                break;
  624.         case DATE_TYPE: FromJulian(v->v.val, &y, &m, &d);
  625.                 sprintf(CoerceBuf, "%04d%c%02d%c%02d",
  626.                     y, DATESEP, m+1, DATESEP, d);
  627.                 break;
  628.             default: return E_CANT_COERCE;
  629.          }
  630.          v->type = STR_TYPE;
  631.      v->v.str = StrDup(CoerceBuf);
  632.      if (!v->v.str) {
  633.         v->type = ERR_TYPE;
  634.         return E_NO_MEM;
  635.      }
  636.      return OK;
  637.  
  638.       case INT_TYPE:
  639.      i = 0;
  640.      m = 1;
  641.      switch(v->type) {
  642.         case STR_TYPE:
  643.            s = v->v.str;
  644.            if (*s == '-') {
  645.           m = -1;
  646.           s++;
  647.            }
  648.            while(*s && isdigit(*s)) {
  649.                   i *= 10;
  650.                   i += (*s++) - '0';
  651.                }
  652.                if (*s) {
  653.           free (v->v.str);
  654.                   v->type = ERR_TYPE;
  655.                   return E_CANT_COERCE;
  656.                }
  657.                free(v->v.str);
  658.                v->type = INT_TYPE;
  659.            v->v.val = i * m;
  660.            return OK;
  661.  
  662.         case DATE_TYPE:
  663.         case TIM_TYPE:
  664.            v->type = INT_TYPE;
  665.            return OK;
  666.  
  667.             default: return E_CANT_COERCE;
  668.      }
  669.  
  670.       case DATE_TYPE:
  671.      switch(v->type) {
  672.         case INT_TYPE:
  673.            if(v->v.val >= 0) {
  674.           v->type = DATE_TYPE;
  675.           return OK;
  676.            } else return E_2LOW;
  677.  
  678.         case STR_TYPE:
  679.            s = v->v.str;
  680.            if (ParseLiteralDate(&s, &i)) return E_CANT_COERCE;
  681.            if (*s) return E_CANT_COERCE;
  682.            v->type = DATE_TYPE;
  683.            free(v->v.str);
  684.            v->v.val = i;
  685.            return OK;
  686.  
  687.         default: return E_CANT_COERCE;
  688.      }
  689.  
  690.       case TIM_TYPE:
  691.      switch(v->type) {
  692.         case INT_TYPE:
  693.            v->type = TIM_TYPE;
  694.            v->v.val %= 1440;
  695.            if (v->v.val < 0) v->v.val += 1440;
  696.            return OK;
  697.  
  698.         case STR_TYPE:
  699.            h = 0;
  700.            m = 0;
  701.            s = v->v.str;
  702.            if (!isdigit(*s)) return E_CANT_COERCE;
  703.            while (isdigit(*s)) {
  704.           h *= 10;
  705.           h += *s++ - '0';
  706.            }
  707.            if (*s != ':' && *s != '.' && *s != TIMESEP)
  708.               return E_CANT_COERCE;
  709.            s++;
  710.            if (!isdigit(*s)) return E_CANT_COERCE;
  711.            while (isdigit(*s)) {
  712.           m *= 10;
  713.           m += *s++ - '0';
  714.            }
  715.            if (*s || h>23 || m>59) return E_CANT_COERCE;
  716.            v->type = TIM_TYPE;
  717.            free(v->v.str);
  718.            v->v.val = h*60+m;
  719.            return OK;
  720.  
  721.         default: return E_CANT_COERCE;
  722.      }
  723.       default: return E_CANT_COERCE;
  724.    }
  725. }
  726.  
  727. /***************************************************************/
  728. /*                                                             */
  729. /*  DestroyValue                                               */
  730. /*                                                             */
  731. /*  If value is of type string, deallocate string memory.      */
  732. /*                                                             */
  733. /***************************************************************/
  734. #ifdef HAVE_PROTOS
  735. PUBLIC void DestroyValue(Value *v)
  736. #else
  737. void DestroyValue(v)
  738. Value *v;
  739. #endif
  740. {
  741.    if (v->type == STR_TYPE && v->v.str) free(v->v.str);
  742.    v->type = ERR_TYPE;
  743. }
  744.  
  745. /***************************************************************/
  746. /*                                                             */
  747. /*  Add                                                        */
  748. /*                                                             */
  749. /*  Perform addition.                                          */
  750. /*                                                             */
  751. /***************************************************************/
  752. #ifdef HAVE_PROTOS
  753. PRIVATE int Add(void)
  754. #else
  755. static int Add()
  756. #endif
  757. {
  758.    Value v1, v2, v3;
  759.    int r;
  760.    
  761.    if ( (r = PopValStack(&v2)) )return r;
  762.    if ( (r = PopValStack(&v1)) ) {
  763.       DestroyValue(&v2);
  764.       return r;
  765.    }
  766.    
  767. /* If both are ints, just add 'em */
  768.    if (v2.type == INT_TYPE && v1.type == INT_TYPE) {
  769.       v2.v.val += v1.v.val;
  770.       return (PushValStack(&v2));
  771.    }
  772.  
  773. /* If it's a date plus an int, add 'em */
  774.    if ((v1.type == DATE_TYPE && v2.type == INT_TYPE) ||
  775.        (v1.type == INT_TYPE && v2.type == DATE_TYPE)) {
  776.       v1.v.val += v2.v.val;
  777.       if (v1.v.val < 0) return E_DATE_OVER;
  778.       v1.type = DATE_TYPE;
  779.       return PushValStack(&v1);
  780.    }
  781.    
  782. /* If it's a time plus an int, add 'em mod 1440 */
  783.    if ((v1.type == TIM_TYPE && v2.type == INT_TYPE) ||
  784.        (v1.type == INT_TYPE && v2.type == TIM_TYPE)) {
  785.       v1.v.val = (v1.v.val + v2.v.val) % 1440;
  786.       if (v1.v.val < 0) v1.v.val += 1440;
  787.       v1.type = TIM_TYPE;
  788.       return PushValStack(&v1);
  789.    }       
  790.  
  791. /* If either is a string, coerce them both to strings and concatenate */
  792.    if (v1.type == STR_TYPE || v2.type == STR_TYPE) {
  793.       if ( (r = DoCoerce(STR_TYPE, &v1)) ) {
  794.            DestroyValue(&v1); DestroyValue(&v2);
  795.          return r;
  796.       }
  797.       if ( (r = DoCoerce(STR_TYPE, &v2)) ) {
  798.            DestroyValue(&v1); DestroyValue(&v2);
  799.            return r;
  800.       }
  801.       v3.type = STR_TYPE;
  802.       v3.v.str = (char *) malloc(strlen(v1.v.str) + strlen(v2.v.str) + 1);
  803.       if (!v3.v.str) {
  804.            DestroyValue(&v1); DestroyValue(&v2);
  805.      return E_NO_MEM;
  806.       }
  807.       strcpy(v3.v.str, v1.v.str);
  808.       strcat(v3.v.str, v2.v.str);
  809.       DestroyValue(&v1); DestroyValue(&v2);
  810.       return (PushValStack(&v3));
  811.    }
  812.  
  813.    /* Don't handle other types yet */
  814.    return E_BAD_TYPE;
  815. }
  816.       
  817. /***************************************************************/
  818. /*                                                             */
  819. /*  Subtract                                                   */
  820. /*                                                             */
  821. /*  Perform subtraction.                                       */
  822. /*                                                             */
  823. /***************************************************************/
  824. #ifdef HAVE_PROTOS
  825. PRIVATE int Subtract(void)
  826. #else
  827. static int Subtract()
  828. #endif
  829. {
  830.    Value v1, v2;
  831.    int r;
  832.    
  833.    if ( (r = PopValStack(&v2)) ) return r;
  834.    if ( (r = PopValStack(&v1)) ) {
  835.       DestroyValue(&v2);
  836.       return r;
  837.    }
  838.  
  839.    /* If they're both INTs, do subtraction */
  840.    if (v1.type == INT_TYPE && v2.type == INT_TYPE) {
  841.       v1.v.val -= v2.v.val;
  842.       return PushValStack(&v1);
  843.    }
  844.  
  845.    /* If it's a date minus an int, do subtraction, checking for underflow */
  846.    if (v1.type == DATE_TYPE && v2.type == INT_TYPE) {
  847.       v1.v.val -= v2.v.val;
  848.       if (v1.v.val < 0) return E_DATE_OVER;
  849.       return PushValStack(&v1);
  850.    }
  851.  
  852.    /* If it's a time minus an int, do subtraction mod 1440 */
  853.    if (v1.type == TIM_TYPE && v2.type == INT_TYPE) {
  854.       v1.v.val = (v1.v.val - v2.v.val) % 1440;
  855.       if (v1.v.val < 0) v1.v.val += 1440;
  856.       return PushValStack(&v1);
  857.    }
  858.  
  859.    /* If it's a time minus a time or a date minus a date, do it */
  860.    if ((v1.type == TIM_TYPE && v2.type == TIM_TYPE) ||
  861.        (v1.type == DATE_TYPE && v2.type == DATE_TYPE)) {
  862.       v1.v.val -= v2.v.val;
  863.       v1.type = INT_TYPE;
  864.       return PushValStack(&v1);
  865.    }
  866.  
  867.    /* Must be types illegal for subtraction */
  868.    DestroyValue(&v1); DestroyValue(&v2);
  869.    return E_BAD_TYPE;
  870. }
  871.  
  872. /***************************************************************/
  873. /*                                                             */
  874. /*  Multiply                                                   */
  875. /*                                                             */
  876. /*  Perform multiplication.                                    */
  877. /*                                                             */
  878. /***************************************************************/
  879. #ifdef HAVE_PROTOS
  880. PRIVATE int Multiply(void)
  881. #else
  882. static int Multiply()
  883. #endif
  884. {
  885.    Value v1, v2;
  886.    int r;
  887.  
  888.    if ( (r = PopValStack(&v2)) ) return r;
  889.    if ( (r = PopValStack(&v1)) ) {
  890.       DestroyValue(&v2);
  891.       return r;
  892.    }
  893.  
  894.    if (v1.type == INT_TYPE && v2.type == INT_TYPE) {
  895.       v1.v.val *= v2.v.val;
  896.       return PushValStack(&v1);
  897.    }
  898.    DestroyValue(&v1); DestroyValue(&v2);
  899.    return E_BAD_TYPE;
  900. }
  901.  
  902. /***************************************************************/
  903. /*                                                             */
  904. /*  Divide                                                     */
  905. /*                                                             */
  906. /*  Perform division.                                          */
  907. /*                                                             */
  908. /***************************************************************/
  909. #ifdef HAVE_PROTOS
  910. PRIVATE int Divide(void)
  911. #else
  912. static int Divide()
  913. #endif
  914. {
  915.    Value v1, v2;
  916.    int r;
  917.  
  918.    if ( (r = PopValStack(&v2)) ) return r;
  919.    if ( (r = PopValStack(&v1)) ) {
  920.       DestroyValue(&v2);
  921.       return r;
  922.    }
  923.  
  924.    if (v1.type == INT_TYPE && v2.type == INT_TYPE) {
  925.       if (v2.v.val == 0) return E_DIV_ZERO;
  926.       v1.v.val /= v2.v.val;
  927.       return PushValStack(&v1);
  928.    }
  929.    DestroyValue(&v1); DestroyValue(&v2);
  930.    return E_BAD_TYPE;
  931. }
  932.  
  933. /***************************************************************/
  934. /*                                                             */
  935. /*  Mod                                                        */
  936. /*                                                             */
  937. /*  Perform modulus function.                                  */
  938. /*                                                             */
  939. /***************************************************************/
  940. #ifdef HAVE_PROTOS
  941. PRIVATE int Mod(void)
  942. #else
  943. static int Mod()
  944. #endif
  945. {
  946.    Value v1, v2;
  947.    int r;
  948.  
  949.    if ( (r = PopValStack(&v2)) ) return r;
  950.    if ( (r = PopValStack(&v1)) ) {
  951.       DestroyValue(&v2);
  952.       return r;
  953.    }
  954.  
  955.    if (v1.type == INT_TYPE && v2.type == INT_TYPE) {
  956.       if (v2.v.val == 0) return E_DIV_ZERO;
  957.       v1.v.val %= v2.v.val;
  958.       return PushValStack(&v1);
  959.    }
  960.    DestroyValue(&v1); DestroyValue(&v2);
  961.    return E_BAD_TYPE;
  962. }
  963.  
  964.  
  965. /***************************************************************/
  966. /*                                                             */
  967. /*  GreaterThan, LessThan, EqualTo, NotEqual, LessOrEqual,     */
  968. /*  GreaterOrEqual                                             */
  969. /*                                                             */
  970. /*  All the comparison functions.                              */
  971. /*                                                             */
  972. /***************************************************************/
  973. #ifdef HAVE_PROTOS
  974. PRIVATE int GreaterThan(void) {return Compare(GT);}
  975. PRIVATE int LessThan(void) {return Compare(LT);}
  976. PRIVATE int EqualTo(void) {return Compare(EQ);}
  977. PRIVATE int NotEqual(void) {return Compare(NE);}
  978. PRIVATE int LessOrEqual(void) {return Compare(LE);}
  979. PRIVATE int GreaterOrEqual(void) {return Compare(GE);}
  980. #else
  981. static int GreaterThan() {return Compare(GT);}
  982. static int LessThan() {return Compare(LT);}
  983. static int EqualTo() {return Compare(EQ);}
  984. static int NotEqual() {return Compare(NE);}
  985. static int LessOrEqual() {return Compare(LE);}
  986. static int GreaterOrEqual() {return Compare(GE);}
  987. #endif
  988.  
  989. /***************************************************************/
  990. /*                                                             */
  991. /*  Compare                                                    */
  992. /*  Do the actual work of comparison.                          */
  993. /*                                                             */
  994. /***************************************************************/
  995. #ifdef HAVE_PROTOS
  996. PRIVATE int Compare(int how)
  997. #else
  998. static int Compare(how)
  999. int how;
  1000. #endif
  1001. {
  1002.    Value v1, v2, v3;
  1003.    int r;
  1004.  
  1005.    if ( (r = PopValStack(&v2)) ) return r;
  1006.    if ( (r = PopValStack(&v1)) ) {
  1007.       DestroyValue(&v2);
  1008.       return r;
  1009.    }
  1010.  
  1011. /* Special case for EQ and NE */
  1012.  
  1013.    v3.type = INT_TYPE;
  1014.    if (v1.type != v2.type) {
  1015.       DestroyValue(&v1); DestroyValue(&v2);
  1016.       if (how == EQ) {
  1017.          v3.v.val = 0;
  1018.      return PushValStack(&v3);
  1019.       } else if (how == NE) {
  1020.          v3.v.val = 1;
  1021.      return PushValStack(&v3);
  1022.       } else return E_BAD_TYPE;
  1023.    }
  1024.  
  1025.    if (v1.type == STR_TYPE) {
  1026.       switch(how) {
  1027.          case EQ: v3.v.val = (strcmp(v1.v.str, v2.v.str) == 0); break;
  1028.          case NE: v3.v.val = (strcmp(v1.v.str, v2.v.str) != 0); break;
  1029.          case LT: v3.v.val = (strcmp(v1.v.str, v2.v.str) < 0); break;
  1030.          case GT: v3.v.val = (strcmp(v1.v.str, v2.v.str) > 0); break;
  1031.          case LE: v3.v.val = (strcmp(v1.v.str, v2.v.str) <= 0); break;
  1032.          case GE: v3.v.val = (strcmp(v1.v.str, v2.v.str) >= 0); break;
  1033.       }
  1034.    } else {
  1035.       switch(how) {
  1036.          case EQ: v3.v.val = (v1.v.val == v2.v.val); break;
  1037.          case NE: v3.v.val = (v1.v.val != v2.v.val); break;
  1038.          case LT: v3.v.val = (v1.v.val < v2.v.val); break;
  1039.          case GT: v3.v.val = (v1.v.val > v2.v.val); break;
  1040.          case LE: v3.v.val = (v1.v.val <= v2.v.val); break;
  1041.          case GE: v3.v.val = (v1.v.val >= v2.v.val); break;
  1042.       }
  1043.    }
  1044.    DestroyValue(&v1); DestroyValue(&v2);
  1045.    return PushValStack(&v3);
  1046. }
  1047.  
  1048. /***************************************************************/
  1049. /*                                                             */
  1050. /*  LogOR                                                      */
  1051. /*                                                             */
  1052. /*  Do logical OR                                              */
  1053. /*                                                             */
  1054. /***************************************************************/
  1055. #ifdef HAVE_PROTOS
  1056. PRIVATE int LogOR(void)
  1057. #else
  1058. static int LogOR()
  1059. #endif
  1060. {
  1061.    Value v1, v2;
  1062.    int r;
  1063.  
  1064.    if ( (r = PopValStack(&v2)) ) return r;
  1065.    if ( (r = PopValStack(&v1)) ) {
  1066.       DestroyValue(&v2);
  1067.       return r;
  1068.    }
  1069.  
  1070.    if (v1.type == INT_TYPE && v2.type == INT_TYPE) {
  1071.       v1.v.val = (v1.v.val || v2.v.val) ? 1 : 0;
  1072.       return PushValStack(&v1);
  1073.    }
  1074.    DestroyValue(&v1); DestroyValue(&v2);
  1075.    return E_BAD_TYPE;
  1076. }
  1077.  
  1078. /***************************************************************/
  1079. /*                                                             */
  1080. /*  LogAND                                                     */
  1081. /*                                                             */
  1082. /*  Do logical AND                                             */
  1083. /*                                                             */
  1084. /***************************************************************/
  1085. #ifdef HAVE_PROTOS
  1086. PRIVATE int LogAND(void)
  1087. #else
  1088. static int LogAND()
  1089. #endif
  1090. {
  1091.    Value v1, v2;
  1092.    int r;
  1093.  
  1094.    if ( (r = PopValStack(&v2)) ) return r;
  1095.    if ( (r = PopValStack(&v1)) ) {
  1096.       DestroyValue(&v2);
  1097.       return r;
  1098.    }
  1099.  
  1100.    if (v1.type == INT_TYPE && v2.type == INT_TYPE) {
  1101.       v1.v.val = (v1.v.val && v2.v.val) ? 1 : 0;
  1102.       return PushValStack(&v1);
  1103.    }
  1104.    DestroyValue(&v1); DestroyValue(&v2);
  1105.    return E_BAD_TYPE;
  1106. }
  1107.  
  1108. /***************************************************************/
  1109. /*                                                             */
  1110. /*  UnMinus                                                    */
  1111. /*                                                             */
  1112. /*  Unary Minus                                                */
  1113. /*                                                             */
  1114. /***************************************************************/
  1115. #ifdef HAVE_PROTOS
  1116. PRIVATE int UnMinus(void)
  1117. #else
  1118. static int UnMinus()
  1119. #endif
  1120. {
  1121.    Value *v = &ValStack[ValStackPtr-1];
  1122.    if (v->type != INT_TYPE) return E_BAD_TYPE;
  1123.    v->v.val = -v->v.val;
  1124.    return OK;
  1125. }
  1126.  
  1127. /***************************************************************/
  1128. /*                                                             */
  1129. /*  LogNot                                                     */
  1130. /*                                                             */
  1131. /*  Logical NOT                                                */
  1132. /*                                                             */
  1133. /***************************************************************/
  1134. #ifdef HAVE_PROTOS
  1135. PRIVATE int LogNot(void)
  1136. #else
  1137. static int LogNot()
  1138. #endif
  1139. {
  1140.    Value *v = &ValStack[ValStackPtr-1];
  1141.    if (v->type != INT_TYPE) return E_BAD_TYPE;
  1142.    if (v->v.val) v->v.val = 0; else v->v.val = 1;
  1143.    return OK;
  1144. }
  1145.  
  1146. /***************************************************************/
  1147. /*                                                             */
  1148. /*  FindFunc                                                   */
  1149. /*                                                             */
  1150. /*  Find a function.                                           */
  1151. /*                                                             */
  1152. /***************************************************************/
  1153. #ifdef HAVE_PROTOS
  1154. Operator *FindFunc(char *name, Operator where[], int num)
  1155. #else
  1156. Operator *FindFunc(name, where, num)
  1157. char *name;
  1158. Operator where[];
  1159. int num;
  1160. #endif
  1161. {
  1162.    int top=num-1, bot=0;
  1163.    int mid, r;
  1164.    while (top >= bot) {
  1165.       mid = (top + bot) / 2;
  1166.       r = StrCmpi(name, where[mid].name);
  1167.       if (!r) return &where[mid];
  1168.       else if (r > 0) bot = mid+1;
  1169.       else top = mid-1;
  1170.    }
  1171.    return NULL;
  1172. }
  1173.     
  1174. /***************************************************************/
  1175. /*                                                             */
  1176. /*  PrintValue                                                 */
  1177. /*                                                             */
  1178. /*  Print a value to stdout for debugging purposes.            */
  1179. /*                                                             */
  1180. /***************************************************************/
  1181. #ifdef HAVE_PROTOS
  1182. PUBLIC void PrintValue (Value *v, FILE *fp)
  1183. #else
  1184. void PrintValue(v, fp)
  1185. Value *v;
  1186. FILE *fp;
  1187. #endif
  1188. {
  1189.    int y, m, d;
  1190.    char *s;
  1191.  
  1192.    if (v->type == STR_TYPE) {
  1193.       s=v->v.str;
  1194.       putc('"', fp);
  1195.       for (y=0; y<MAX_PRT_LEN && *s; y++) putc(*s++, fp);
  1196.       putc('"',fp);
  1197.       if (*s) fprintf(fp, "...");
  1198.    }      
  1199.    else if (v->type == INT_TYPE) fprintf(fp, "%d", v->v.val);
  1200.    else if (v->type == TIM_TYPE) fprintf(fp, "%02d%c%02d", v->v.val / 60, 
  1201.                      TIMESEP, v->v.val % 60);
  1202.    else if (v->type == DATE_TYPE) {
  1203.       FromJulian(v->v.val, &y, &m, &d);
  1204.       fprintf(fp, "%04d%c%02d%c%02d", y, DATESEP, m+1, DATESEP, d);
  1205.    }
  1206.    else fprintf(fp, "ERR");
  1207. }
  1208.  
  1209. /***************************************************************/
  1210. /*                                                             */
  1211. /*  CopyValue                                                  */
  1212. /*                                                             */
  1213. /*  Copy a value.                                              */
  1214. /*                                                             */
  1215. /***************************************************************/
  1216. #ifdef HAVE_PROTOS
  1217. PUBLIC int CopyValue(Value *dest, const Value *src)
  1218. #else
  1219. int CopyValue(dest, src)
  1220. Value *dest, *src;
  1221. #endif
  1222. {
  1223.    dest->type = ERR_TYPE;
  1224.    if (src->type == STR_TYPE) {
  1225.       dest->v.str = StrDup(src->v.str);
  1226.       if (!dest->v.str) return E_NO_MEM;
  1227.    } else {
  1228.       dest->v.val = src->v.val;
  1229.    }
  1230.    dest->type = src->type;
  1231.    return OK;
  1232. }
  1233.  
  1234. /***************************************************************/
  1235. /*                                                             */
  1236. /*  ParseLiteralDate                                           */
  1237. /*                                                             */
  1238. /*  Parse a literal date.  Return result in jul, update s.     */
  1239. /*                                                             */
  1240. /***************************************************************/
  1241. #ifdef HAVE_PROTOS
  1242. PRIVATE int ParseLiteralDate(char **s, int *jul)
  1243. #else
  1244. static int ParseLiteralDate(s, jul)
  1245. char **s;
  1246. int *jul;
  1247. #endif
  1248. {
  1249.    int y, m, d;
  1250.  
  1251.    y=0; m=0; d=0;
  1252.  
  1253.    if (!isdigit(**s)) return E_BAD_DATE;
  1254.    while (isdigit(**s)) {
  1255.       y *= 10;
  1256.       y += *(*s)++ - '0';
  1257.    }
  1258.    if (**s != '/' && **s != '-' && **s != DATESEP) return E_BAD_DATE;
  1259.    (*s)++;
  1260.    if (!isdigit(**s)) return E_BAD_DATE;
  1261.    while (isdigit(**s)) {
  1262.       m *= 10;
  1263.       m += *(*s)++ - '0';
  1264.    }
  1265.    m--;
  1266.    if (**s != '/' && **s != '-' && **s != DATESEP) return E_BAD_DATE;
  1267.    (*s)++;
  1268.    if (!isdigit(**s)) return E_BAD_DATE;
  1269.    while (isdigit(**s)) {
  1270.       d *= 10;
  1271.       d += *(*s)++ - '0';
  1272.    }
  1273.    if (!DateOK(y, m, d)) return E_BAD_DATE;
  1274.    
  1275.    *jul = Julian(y, m, d);
  1276.  
  1277.    return OK;
  1278. }
  1279.