Contributor: SWAG SUPPORT TEAM        

Unit LongJump;

{ This Unit permits a long jump from deeply nested Procedures/Functions back }
{ to a predetermined starting point.                                         }

{ Whilst the purists may shudder at such a practice there are times when such}
{ an ability can be exceedingly useful.  An example of such a time is in a   }
{ BBS Program when the carrier may be lost unexpectedly whilst a user is on  }
{ line and the requirement is to "back out" to the initialisation reoutines  }
{ at the start of the Program.                                               }

{ to use the facility, it is required that a call be made to the SetJump     }
{ Function at the point to where you wish the execution to resume after a    }
{ long jump. When the time comes to return to that point call FarJump.       }

{ if you are an inexperienced Programmer, I do not recommend that this Unit  }
{ be used For other than experimentation.  Usually there are better ways to  }
{ achieve what you want to do by proper planning and structuring.  It is     }
{ rare to find a well written Program that will need such and ability.       }


  normal = -1;                         { return was not from a LongJump call }
  jumpType = Record                        { the data need For a return jump }
                bp,sp,cs,ip : Word;

Function  SetJump(Var JumpData : jumpType): Integer;
Procedure FarJump(JumpData : jumpType; IDInfo : Integer);


  WordPtr = ^Word;

Function SetJump(Var JumpData : jumpType): Integer;
  begin                     { store the return address (the old bp register) }
    JumpData.bp := WordPtr(ptr(SSeg,SPtr+2))^;
    JumpData.ip := WordPtr(ptr(SSeg,SPtr+4))^;
    JumpData.cs := WordPtr(ptr(SSeg,SPtr+6))^;
    JumpData.SP := SPtr;
    SetJump := normal;                { show that this is not a FarJump call }
  end;  { SetJump }

Procedure FarJump(JumpData : jumpType; IDInfo : Integer );
    { change the return address of the calling routine of the stack so that  }
    { a return can be made to the caller of SetJump                          }
    { Use IDInfo as an identifier of the routine the jump occurred from      }
    WordPtr(ptr(SSeg,JumpData.SP))^   := JumpData.bp;
    WordPtr(ptr(SSeg,JumpData.SP+2))^ := JumpData.ip;
    WordPtr(ptr(SSeg,JumpData.SP+4))^ := JumpData.cs;
    Inline($8b/$46/$06);                                     { mov ax,[bp+6] }
    Inline($8b/$ae/$fa/$ff);                                 { mov bp,[bp-6] }
  end;  { FarJump }

end.  { LongJump }