/*
 * File: fscan.c
 *  Contents: move, pos, tab.
 */

#include "..\h\config.h"
#include "..\h\rt.h"
#include "rproto.h"


/*
 * move(i) - move &pos by i, return substring of &subject spanned.
 *  Reverses effects if resumed.
 */
FncDcl(move,1)
   {
   register word i, j;
   word oldpos;

   /*
    * Arg1 must be a (non-long) integer.
    */
   switch (cvint(&Arg1)) {

      case T_Integer:
         j = (word)IntVal(Arg1);
         break;

      default:
         RunErr(101, &Arg1);
      }

   /*
    * Save old &pos.  Local variable i holds &pos before the move.
    */
   oldpos = i = k_pos;

   /*
    * If attempted move is past either end of the string, fail.
    */
   if (i + j <= 0 || i + j > StrLen(k_subject) + 1)
      Fail;

   /*
    * Set new &pos.
    */
   k_pos += j;

   /*
    * Make sure j >= 0.
    */
   if (j < 0) {
      i += j;
      j = -j;
      }

   /*
    * Suspend substring of &subject that was moved over.
    */
   StrLen(Arg0) = j;
   StrLoc(Arg0) = StrLoc(k_subject) + i - 1;
   Suspend;

   /*
    * If move is resumed, restore the old position and fail.
    */
   if (oldpos > StrLen(k_subject) + 1) {
      RunErr(205, &tvky_pos.kyval)
      }
   else
      k_pos = oldpos;
   Fail;
   }

/*
 * pos(i) - test if &pos is at position i in &subject.
 */
FncDcl(pos,1)
   {
   register word i;

   /*
    * Arg1 must be an integer.
    */
   if (cvint(&Arg1) == CvtFail) 
      RunErr(101, &Arg1);

   /*
    * Fail if &pos is not equivalent to Arg1, return Arg1 otherwise.
    */
   if ((i = cvpos(IntVal(Arg1), StrLen(k_subject))) != k_pos)
      Fail;
   MakeInt(i, &Arg0);
   Return;
   }

/*
 * tab(i) - set &pos to i, return substring of &subject spanned.
 *  Reverses effects if resumed..
 */

FncDcl(tab,1)
   {
   register word i, j;
   word t, oldpos;

   /*
    * Arg1 must be an integer.
    */
   if (cvint(&Arg1) == CvtFail) 
      RunErr(101, &Arg1);

   /*
    * Convert it to an absolute position.
    */
   j = cvpos(IntVal(Arg1), StrLen(k_subject));
   if (j == CvtFail)
      Fail;

   /*
    * Save old &pos.  Local variable i holds &pos before the tab.
    */
   oldpos = i = k_pos;

   /*
    * Set new &pos.
    */
   k_pos = j;

   /*
    *  Make j the length of the substring &subject[i:j]
    */
   if (i > j) {
      t = i;
      i = j;
      j = t - j;
      }
   else
      j = j - i;

   /*
    * Suspend the portion of &subject that was tabbed over.
    */
   StrLoc(Arg0) = StrLoc(k_subject) + i - 1;
   StrLen(Arg0) = j;
   Suspend;

   /*
    * If tab is resumed, restore the old position and fail.
    */
   if (oldpos > StrLen(k_subject) + 1) {
      RunErr(205, &tvky_pos.kyval);
      }
   else
      k_pos = oldpos;
   Fail;
   }
