/*
 * File: ocomp.c
 *  Contents: lexeq, lexge, lexgt, lexle, lexlt, lexne, numeq, numge,
 *		numgt, numle, numlt, numne, eqv, neqv
 */

#include "..\h\config.h"
#include "..\h\rt.h"
#include "rproto.h"


/*
 * x == y - test if x is lexically equal to y.
 */

OpDcl(lexeq,2,"==")
   {
   register int t;
   char sbuf1[MaxCvtLen], sbuf2[MaxCvtLen];

   /*
    * Arg1 and Arg2 must be strings.  Save the cvstr return value for Arg2
    *  because Arg2 is the result (if any).
    */
   if (cvstr(&Arg1, sbuf1) == CvtFail) 
      RunErr(103, &Arg1);
   if ((t = cvstr(&Arg2, sbuf2)) == CvtFail) 
      RunErr(103, &Arg2);


   /*
    * If the strings have different lengths they cannot be equal.
    */
   if (StrLen(Arg1) != StrLen(Arg2))
      Fail;

   /*
    * lexcmp does the work.
    */
   if (lexcmp(&Arg1, &Arg2) != Equal)
      Fail;

   /*
    * Return Arg2 as the result of the comparison.  If Arg2 was converted to
    *  a string, a copy of it is allocated.
    */
   Arg0 = Arg2;
   if (t == Cvt) {
      if (strreq(StrLen(Arg0)) == Error) 
         RunErr(0, NULL);
      StrLoc(Arg0) = alcstr(StrLoc(Arg0), StrLen(Arg0));
      }
   Return;
   }

/*
 * x >>= y - test if x is lexically greater than or equal to y.
 */

OpDcl(lexge,2,">>=")
   {
   register int t;
   char sbuf1[MaxCvtLen], sbuf2[MaxCvtLen];

   /*
    * Arg1 and Arg2 must be strings.  Save the cvstr return value for Arg2
    *  because Arg2 is the result (if any).
    */
   if (cvstr(&Arg1, sbuf1) == CvtFail) 
      RunErr(103, &Arg1);
   if ((t = cvstr(&Arg2, sbuf2)) == CvtFail) 
      RunErr(103, &Arg2);

   /*
    * lexcmp does the work.
    */
   if (lexcmp(&Arg1, &Arg2) == Less)
      Fail;

   /*
    * Return Arg2 as the result of the comparison.  If Arg2 was converted to
    *  a string, a copy of it is allocated.
    */
   Arg0 = Arg2;
   if (t == Cvt) {
      if (strreq(StrLen(Arg0)) == Error) 
         RunErr(0, NULL);
      StrLoc(Arg0) = alcstr(StrLoc(Arg0), StrLen(Arg0));
      }
   Return;
   }

/*
 * x >> y - test if x is lexically greater than y.
 */

OpDcl(lexgt,2,">>")
   {
   register int t;
   char sbuf1[MaxCvtLen], sbuf2[MaxCvtLen];

   /*
    * Arg1 and Arg2 must be strings.  Save the cvstr return value for Arg2
    *  because Arg2 is the result (if any).
    */
   if (cvstr(&Arg1, sbuf1) == CvtFail) 
      RunErr(103, &Arg1);
   if ((t = cvstr(&Arg2, sbuf2)) == CvtFail) 
      RunErr(103, &Arg2);

   /*
    * lexcmp does the work.
    */
   if (lexcmp(&Arg1, &Arg2) != Greater)
      Fail;

   /*
    * Return Arg2 as the result of the comparison.  If Arg2 was converted to
    *  a string, a copy of it is allocated.
    */
   Arg0 = Arg2;
   if (t == Cvt) {
      if (strreq(StrLen(Arg0)) == Error) 
         RunErr(0, NULL);
      StrLoc(Arg0) = alcstr(StrLoc(Arg0), StrLen(Arg0));
      }
   Return;
   }

/*
 * x <<= y - test if x is lexically less than or equal to y.
 */

OpDcl(lexle,2,"<<=")
   {
   register int t;
   char sbuf1[MaxCvtLen], sbuf2[MaxCvtLen];

   /*
    * Arg1 and Arg2 must be strings.  Save the cvstr return value for Arg2
    *  because Arg2 is the result (if any).
    */
   if (cvstr(&Arg1, sbuf1) == CvtFail) 
      RunErr(103, &Arg1);
   if ((t = cvstr(&Arg2, sbuf2)) == CvtFail) 
      RunErr(103, &Arg2);

   /*
    * lexcmp does the work.
    */
   if (lexcmp(&Arg1, &Arg2) == Greater)
      Fail;

   /*
    * Return Arg2 as the result of the comparison.  If Arg2 was converted to
    *  a string, a copy of it is allocated.
    */
   Arg0 = Arg2;
   if (t == Cvt) {
      if (strreq(StrLen(Arg0)) == Error) 
         RunErr(0, NULL);
      StrLoc(Arg0) = alcstr(StrLoc(Arg0), StrLen(Arg0));
      }
   Return;
   }

/*
 * x << y - test if x is lexically less than y.
 */

OpDcl(lexlt,2,"<<")
   {
   register int t;
   char sbuf1[MaxCvtLen], sbuf2[MaxCvtLen];

   /*
    * Arg1 and Arg2 must be strings.  Save the cvstr return value for Arg2
    *  because Arg2 is the result (if any).
    */
   if (cvstr(&Arg1, sbuf1) == CvtFail) 
      RunErr(103, &Arg1);
   if ((t = cvstr(&Arg2, sbuf2)) == CvtFail) 
      RunErr(103, &Arg2);

   /*
    * lexcmp does the work.
    */
   if (lexcmp(&Arg1, &Arg2) != Less)
      Fail;

   /*
    * Return Arg2 as the result of the comparison.  If Arg2 was converted to
    *  a string, a copy of it is allocated.
    */
   Arg0 = Arg2;
   if (t == Cvt) {		/* string needs to be allocated */
      if (strreq(StrLen(Arg0)) == Error) 
         RunErr(0, NULL);
      StrLoc(Arg0) = alcstr(StrLoc(Arg0), StrLen(Arg0));
      }
   Return;
   }

/*
 * x ~== y - test if x is lexically not equal to y.
 */

OpDcl(lexne,2,"~==")
   {
   register int t;
   char sbuf1[MaxCvtLen], sbuf2[MaxCvtLen];

   /*
    * Arg1 and Arg2 must be strings.  Save the cvstr return value for Arg2
    *  because Arg2 is the result (if any).
    */
   if (cvstr(&Arg1, sbuf1) == CvtFail) 
      RunErr(103, &Arg1);
   if ((t = cvstr(&Arg2, sbuf2)) == CvtFail) 
      RunErr(103, &Arg2);


   /*
    * If the strings have different lengths they are not equal.
    * If lengths are the same, let lexcmp do the work.
    */
   if (StrLen(Arg1) == StrLen(Arg2) && lexcmp(&Arg1, &Arg2) == Equal)
      Fail;

   /*
    * Return Arg2 as the result of the comparison.  If Arg2 was converted to
    *  a string, a copy of it is allocated.
    */
   Arg0 = Arg2;
   if (t == Cvt) {		/* string needs to be allocated */
      if (strreq(StrLen(Arg0)) == Error) 
         RunErr(0, NULL);
      StrLoc(Arg0) = alcstr(StrLoc(Arg0), StrLen(Arg0));
      }
   Return;
   }

/*
 * x = y - test if x is numerically equal to y.
 */

OpDcl(numeq,2,"=")
   {

   switch (numcmp(&Arg1, &Arg2, &Arg0)) {
      case Equal:
         Return;
      case Greater:
      case Less:
         Fail;
      case Error: 
         RunErr(0, NULL);
      }
   }

/*
 * x >= y - test if x is numerically greater or equal to y.
 */

OpDcl(numge,2,">=")
   {

   switch (numcmp(&Arg1, &Arg2, &Arg0)) {
      case Greater:
      case Equal:
         Return;
      case Less:
         Fail;
      case Error: 
         RunErr(0, NULL);
      }
   }

/*
 * x > y - test if x is numerically greater than y.
 */

OpDcl(numgt,2,">")
   {

   switch (numcmp(&Arg1, &Arg2, &Arg0)) {
      case Greater:
         Return;
      case Less:
      case Equal:
         Fail;
      case Error: 
         RunErr(0, NULL);
      }
   }

/*
 * x <= y - test if x is numerically less than or equal to y.
 */

OpDcl(numle,2,"<=")
   {

   switch (numcmp(&Arg1, &Arg2, &Arg0)) {
      case Less:
      case Equal:
         Return;
      case Greater:
         Fail;
      case Error: 
         RunErr(0, NULL);
      }
   }

/*
 * x < y - test if x is numerically less than y.
 */

OpDcl(numlt,2,"<")
   {

   switch (numcmp(&Arg1, &Arg2, &Arg0)) {
      case Less:
         Return;
      case Greater:
      case Equal:
         Fail;
      case Error: 
         RunErr(0, NULL);
      }
   }

/*
 * x ~= y - test if x is numerically not equal to y.
 */

OpDcl(numne,2,"~=")

   {

   switch (numcmp(&Arg1, &Arg2, &Arg0)) {
      case Less:
      case Greater:
         Return;
      case Equal:
         Fail;
      case Error: 
         RunErr(0, NULL);
      }
   Return;
   }

/*
 * x === y - test equivalence of Arg1 and Arg2.
 */

OpDcl(eqv,2,"===")
   {

   /*
    * Let equiv do all the work, failing if equiv indicates non-equivalence.
    */
   if (!equiv(&Arg1, &Arg2))
      Fail;

   Arg0 = Arg2;
   Return;
   }

/*
 * x ~=== y - test inequivalence of Arg1 and Arg2.
 */

OpDcl(neqv,2,"~===")
   {

   /*
    * equiv does all the work.
    */
   if (equiv(&Arg1, &Arg2))
      Fail;
   Arg0 = Arg2;
   Return;
   }
