/* CLASS: StkLibInst   StkLibinst
   Provide multiple instances of the StackLib
*/!!

inherit(StackLib, #StkLibInst, #(sessionID /* id of session */
stackSize /* size of stack in bytes - U32 */
alarmLimit /* address of alarm limit - U32 */
alarmPercent /* AlarmPercentage */
currentSP /* current StackPointer - U32 */
baseAddr /* address of stack base - U32 */
hwMarkAddr /* address of HWMark */
enableStkAlarm /* boolean flag */
enableStkHWMark /* boolean flag */
lowToHigh /* boolean flag of grow direction */), 2, nil)!!

now(class(StkLibInst))!!

/* 3/2/1992 17:06 - semiPRIVATE 
  called by StackLib:openSession() only */
Def new(self, hWnd)
{
  ^initialize( new(self:ancestor), hWnd )
}

!!

now(StkLibInst)!!

/* 07/14/93 - 08:30 - PUBLIC 
  Set the current stack context alarm percent.
*/
Def setAlarmLimitPercent(self, setAlarmPercent)
{ 
  if pcallLock(self)
  then
    lastError = pcall( procs[#STKSETALARMLIMITPERCENT], sessionID, setAlarmPercent);
    pcallUNLock(self);
  else 
    lastError := ERR_PCALL_RECURSION ;
  endif ;

  if (lastError <> GOOD) then
    displayError(ErrorTextLibClass$Inst,lastError, CHECK_MODE);
    ^nil;
  endif;
  alarmPercent := setAlarmPercent;    
  ^GOOD;
}
!!
/* 3/3/1992 15:14 - PUBLIC 
  Set stack base address and stack size, destroy the input addrDesc.
  NOTES: stkBaseDesc is kept by Stack Server until the session is closed.
  It will be destroyed by the Stack Server even if error occurrs.
*/
Def setStackBaseAndSize(self, stkBaseDesc, stkSize )
{   
  if not(baseAddr := getOffset(AddressLibClass$Inst, stkBaseDesc)) then
    /* Destroy the addrDesc because of error */
    destroyAddress(AddressLibClass$Inst, stkBaseDesc);
    ^nil;
  endif;

  /* Set stack base for server */    
  if pcallLock(self)
  then
    lastError = pcall( procs[#STKSETSTACKBASEANDSIZE], sessionID, stkBaseDesc, 
		stkSize);
    pcallUNLock(self);
  else 
    lastError := ERR_PCALL_RECURSION ;
  endif ;

  if (lastError <> GOOD) then
    displayError(ErrorTextLibClass$Inst,lastError, CHECK_MODE);
    ^nil;
  endif; 
  ^GOOD;
}
!!

/* 7/1/1993 14:07 - PUBLIC
  Get all stack session information in one shot.
  if success return tuple of stack info else return nil; 
  NOTES: #(currentSP, baseAddr, stackSize, alarmPercent, alarmLimit, 
    enableStkAlarm, hwMarkAddr, enableStkHWMark, lowToHigh); 
*/
Def getStackInfo(self | 
  stkBasePtr, isBaseValidPtr, stkSizePtr, alarmLimitPtr,
  alarmPercentPtr, isAlarmValidPtr, isAlarmEnabledPtr,
  hwmPtr, isHWMEnabledPtr, directionPtr)
{ 
  if not(getCurrentSP(self)) 
    ^nil;
  endif;
  stkBasePtr        := new(Struct, 4);
  isBaseValidPtr    := new(Struct, 2);
  stkSizePtr        := new(Struct, 4);
  alarmLimitPtr     := new(Struct, 4);
  alarmPercentPtr   := new(Struct, 4);
  isAlarmValidPtr   := new(Struct, 2);
  isAlarmEnabledPtr := new(Struct, 2);
  hwmPtr            := new(Struct, 4);
  isHWMEnabledPtr   := new(Struct, 2);
  directionPtr      := new(Struct, 4);

  if pcallLock(self)
  then
    lastError := pcall(procs[#STKGETSTACKINFO], sessionID, 
        stkBasePtr, isBaseValidPtr, stkSizePtr,
        alarmLimitPtr, alarmPercentPtr, isAlarmValidPtr, 
        isAlarmEnabledPtr, hwmPtr, isHWMEnabledPtr,
        directionPtr);
    pcallUNLock(self);
  else 
    lastError := ERR_PCALL_RECURSION ;
  endif ;
  /* Error if base is not valid */
  if (lastError <> GOOD) cor 
      (wordAt(isBaseValidPtr, 0) = BOOL_FALSE) then
    displayError(ErrorTextLibClass$Inst,lastError, CHECK_MODE);
    ^nil;
  endif;
  /* stack Base is valid - call addr to get offset value */
  baseAddr := getOffset(AddressLibClass$Inst, longAt(stkBasePtr,0)); 
  destroyAddress(AddressLibClass$Inst, longAt(stkBasePtr, 0));
  if not(baseAddr) 
    ^nil; 
  endif;
  /* stack size */
  stackSize := longAt(stkSizePtr, 0);
  
  /* Alarm stuffs - only significant when it's enabled */
  alarmPercent := longAt(alarmPercentPtr, 0); 
  enableStkAlarm := wordAt(isAlarmEnabledPtr, 0);
  if (wordAt(isAlarmValidPtr, 0) = BOOL_TRUE) then
    alarmLimit := getOffset(AddressLibClass$Inst, longAt(alarmLimitPtr,0));
  endif;  
  destroyAddress(AddressLibClass$Inst, longAt(alarmLimitPtr,0)); 
  
  /* HighWaterMark stuffs - only significant when enabled */
  enableStkHWMark := wordAt(isHWMEnabledPtr, 0);
  if (enableStkHWMark = BOOL_TRUE) then
    hwMarkAddr := getOffset(AddressLibClass$Inst, longAt(hwmPtr,0));
  endif;  
  destroyAddress(AddressLibClass$Inst, longAt(hwmPtr, 0)); 
  /* stack direction */
  lowToHigh := byteAt(directionPtr, 0);  
  /* return tuple of information */
  ^tuple(currentSP, baseAddr, stackSize, alarmPercent, alarmLimit, 
    enableStkAlarm, hwMarkAddr, enableStkHWMark, lowToHigh);
}
!!

/* 8/17/1992 13:13 - PBULIC
  Get the current SP register of the stack server session.
*/
Def getCurrentSP(self | spDesc, val )
{ 
  if (spDesc := getStackPointer(CpuLibClass$Inst)) cand
    (val := getOffset(AddressLibClass$Inst, spDesc)) then
    currentSP := val;
  endif;
  if spDesc then    
    destroyAddress(AddressLibClass$Inst, spDesc);
  endif;  
  ^currentSP;
}
!!

/* 3/2/1992 17:07 - PUBLIC
  opensesion() is defined in StackLib
 */
Def closeSession(self)
{
  if open?(self) then
    if pcallLock(self) then
      lastError := pcall(procs[#STKENDSESSION], sessionID) ;
      pcallUNLock(self);
    else 
      lastError := ERR_PCALL_RECURSION ;
    endif ; 
  else
    ^nil
  endif;

  if (lastError <> GOOD) then
    displayError(ErrorTextLibClass$Inst,lastError,FORCE_POPUP);
    ^nil;
  endif;
  sessionID := nil ;    
  ^GOOD;

}
 
!!

/* 3/3/1992 11:21 - PUBLIC */
Def disableAlarmLimit(self)
{ 
  if pcallLock(self)
  then
    lastError := pcall(procs[#STKDISABLEALARMLIMIT], sessionID) ;
    pcallUNLock(self);
  else 
    lastError := ERR_PCALL_RECURSION ;
  endif ;

  if (lastError <> GOOD) then
     displayError(ErrorTextLibClass$Inst,lastError,FORCE_POPUP);
     ^nil;
  endif;
  ^GOOD;    
}
!!

/* 3/3/1992 12:14 - PUBLIC*/
Def disableHighWaterMark(self)
{ 
  if pcallLock(self)
  then
    lastError := pcall(procs[#STKDISABLEHIGHWATERMARK], sessionID);
    pcallUNLock(self);
  else 
    lastError := ERR_PCALL_RECURSION ;
  endif ;

  if (lastError <> GOOD) then
     displayError(ErrorTextLibClass$Inst,lastError, CHECK_MODE);
     ^nil;
  endif;    
  ^GOOD;    
}


!!

/* 3/3/1992 12:14 - PUBLIC*/
Def enableAlarmLimit(self)
{ 
  if pcallLock(self)
  then
    lastError := pcall(procs[#STKENABLEALARMLIMIT], sessionID);
    pcallUNLock(self);
  else 
    lastError := ERR_PCALL_RECURSION ;
  endif ;

  if (lastError <> GOOD) then
    displayError(ErrorTextLibClass$Inst,lastError, CHECK_MODE);
    ^nil;
  endif;
  ^GOOD;
}


!!

/* 3/3/1992 12:14 - PUBLIC*/
Def enableHighWaterMark(self)
{ 
  if pcallLock(self)
  then
    lastError := pcall(procs[#STKENABLEHIGHWATERMARK], sessionID);
    pcallUNLock(self);
  else 
    lastError := ERR_PCALL_RECURSION ;
  endif ;

  if (lastError <> GOOD) then
    if (lastError <> ER_STK_FILL_STACK_AREA) then
      displayError(ErrorTextLibClass$Inst,lastError, CHECK_MODE);
    endif;  
    ^nil;
  endif;
  ^GOOD;    
}


!!

/* 3/3/1992 13:31 - PUBLIC 
  Return nil or tuple = #(alarmEnableState, alarmLimit, alarmPrecent).
*/
Def getAlarmLimit(self | alarmLimitPtr, alarmPercentPtr, isValid, isEnabled)
{ 
  /* Stack Alarm enable, so get new value - else return old value */
  alarmLimitPtr := new(Struct, 4);
  alarmPercentPtr := new(Struct, 4);
  isValid := new(Struct, 2);
  isEnabled := new(Struct, 2);

  if pcallLock(self) then
    lastError := pcall( procs[#STKGETALARMLIMIT], sessionID, 
                       alarmLimitPtr, alarmPercentPtr, isValid, isEnabled);
    pcallUNLock(self);
  else 
    lastError := ERR_PCALL_RECURSION ;
  endif ;
  if (lastError <> GOOD) then
    displayError(ErrorTextLibClass$Inst,lastError, CHECK_MODE);
    destroyAddress(AddressLibClass$Inst, longAt(alarmLimitPtr,0)); 
    ^nil;
  else
    /* Check if Alarm is enabled */  
    enableStkAlarm := byteAt(isEnabled, 0);  
    alarmPercent   := longAt(alarmPercentPtr, 0);
    alarmLimit     := getOffset(AddressLibClass$Inst, 
                                    longAt(alarmLimitPtr,0));  
    /* Destroy the unused descriptor */
    destroyAddress(AddressLibClass$Inst, longAt(alarmLimitPtr,0)); 
  endif;    
  ^tuple(enableStkAlarm, alarmLimit, alarmPercent); 
}
!!

/* 3/3/1992 16:20 - PUBLIC 
  Return a #true or nil value for Alarm enable or disable.
*/
Def getAlarmState(self | alarmStatePtr)
{ 
  alarmStatePtr := new( Struct, 2 );
  if pcallLock(self) then
    lastError := pcall( procs[#STKGETALARMSTATE], sessionID, 
                          alarmStatePtr);
    pcallUNLock(self);
  else 
    lastError := ERR_PCALL_RECURSION ;
  endif ;

  if (lastError <> GOOD) then
     displayError(ErrorTextLibClass$Inst,lastError, CHECK_MODE);
     ^nil;
  endif; 
  /* Boolean value */ 
  ^(wordAt(alarmStatePtr, 0));
}
!!

/* 3/3/1992 13:31 - PUBLIC 
  Return a TextCollection of stack frame start from startF to endF.
  Text format from the displayBufPtr is:
    [<Stack Addr:8><Code Addr:8><FuncName:{max:256}>+CR+LF]...
 */
Def getFrame(self, startF, endF | displayBufPtr)
{ 
  displayBufPtr := new(Struct, 4);
  if pcallLock(self) then
    lastError := pcall( procs[#STKREADFRAMEN], sessionID, startF, endF,
                        0 /* Batch Mode */, displayBufPtr);
    pcallUNLock(self);
  else 
    lastError := ERR_PCALL_RECURSION ;
  endif ;

  if (lastError <> GOOD) then
    displayError(ErrorTextLibClass$Inst,lastError, CHECK_MODE);
    ^nil;
  endif;
  /* Get the text into a TextCollection for the caller */
  ^getTextFromAddr(self,longAt(displayBufPtr, 0));
}
!!

/* 3/9/1992 13:05 - PUBLIC 
  Return the BOOL_TRUE if stack frames exist or nil */
Def anyFrames(self | frameNumPtr )
{ 
  /* Default to get all frame - eventhough, some do not have symbol */
  frameNumPtr := new(Struct, 2);
  if pcallLock(self) then
    lastError := pcall(procs[#STKANYFRAMES], sessionID, frameNumPtr);
    pcallUNLock(self);
  else 
    lastError := ERR_PCALL_RECURSION ;
  endif;
  if (lastError <> GOOD) then
    displayError(ErrorTextLibClass$Inst,lastError, CHECK_MODE);
    ^nil;
  endif;
  ^wordAt(frameNumPtr, 0);  
}
!!

/* 3/6/1992 13:27 - PUBLIC 
  Return a tupple of information of the specified stack frame number.
  RETURN: #(symDesc, moduleDesc, addrDesc) 
*/
Def getFrameInfo(self, frameNum | symDescPtr, moduleDescPtr, addrDescPtr)
{ 
  symDescPtr := new(Struct, 4);
  moduleDescPtr := new(Struct, 4);
  addrDescPtr := new(Struct, 4);
  if pcallLock(self) then
    lastError := pcall( procs[#STKGETFRAMESYMBOL], sessionID, 
                     asInt(frameNum), symDescPtr, moduleDescPtr, addrDescPtr);
    pcallUNLock(self);
  else 
    lastError := ERR_PCALL_RECURSION ;
  endif ;

  if (lastError <> GOOD) then  
    displayError(ErrorTextLibClass$Inst,lastError, CHECK_MODE);
    ^nil;
  endif;
  /* RETURN: #(symDesc, moduleDesc, addrDesc) */
  ^tuple(longAt(symDescPtr, 0), longAt(moduleDescPtr, 0), longAt(addrDescPtr, 0));   
}
!!

/* 3/3/1992 13:31 - PUBLIC 
  Return a SYM_DESCRIPTOR of the first local symbol. Use getSymbolSibling()
  of the SymbolLib Class to extract all the symbol, go until NULL_SYMBOL
  is returned.  
 */
Def getFrameLocals(self, frameId | numParamPtr, firstLocalPtr)
{ 
  numParamPtr := new(Struct, 2);
  firstLocalPtr := new(Struct, 4);
  if pcallLock(self) then
    lastError := pcall( procs[#STKREADFRAMELOCALS], sessionID, 
                        asInt(frameId), numParamPtr, firstLocalPtr);
    pcallUNLock(self);
  else 
    lastError := ERR_PCALL_RECURSION ;
  endif ;

  if (lastError <> GOOD) then
    displayError(ErrorTextLibClass$Inst,lastError, CHECK_MODE);
    ^nil;
  endif;
  /* RETURN: #(SYM_DESC, numParam) */
  ^tuple(longAt(firstLocalPtr, 0), byteAt(numParamPtr,0)); 
}
!!

/* 3/3/1992 13:31 - PUBLIC */
Def getHighWaterMark(self | hwMarkPtr, enablePtr)
{ 
  hwMarkPtr := new( Struct, 4 );
  enablePtr := new( Struct, 2 );
  if pcallLock(self) then
    lastError := pcall( procs[#STKGETHIGHWATERMARK], sessionID, 
                          hwMarkPtr, enablePtr);
    pcallUNLock(self);
  else 
    lastError := ERR_PCALL_RECURSION ;
  endif ;

  if  (lastError <> GOOD) then
    displayError(ErrorTextLibClass$Inst,lastError, CHECK_MODE);    
    ^nil;
  endif;
  
  /* if highwater mark is valid */
  enableStkHWMark := wordAt(enablePtr, 0);
  if (enableStkHWMark = BOOL_FALSE) then
    displayFormattedError(ErrorTextLibClass$Inst, 
       ER_STACK_HW_DISABLED, FORCE_POPUP, nil, nil, nil);
    destroyAddress(AddressLibClass$Inst, longAt(hwMarkPtr, 0)); 
    ^nil;
  endif;  
  hwMarkAddr := getOffset(AddressLibClass$Inst, longAt(hwMarkPtr,0));
  destroyAddress(AddressLibClass$Inst, longAt(hwMarkPtr, 0)); 
  ^hwMarkAddr;  
}
!!

/* 3/3/1992 13:31 - PUBLIC 
  Return a U32 address value
 */
Def getStackBase(self | stkBasePtr, isValidPtr, baseAddr)
{ 
  stkBasePtr := new( Struct, 4 );
  isValidPtr := new( Struct, 2 );
  if pcallLock(self) then
    lastError := pcall( procs[#STKGETSTACKBASE], sessionID, 
                        stkBasePtr, isValidPtr);
    pcallUNLock(self);
  else 
    lastError := ERR_PCALL_RECURSION ;
  endif ;

  if ((lastError <> GOOD) cand (wordAt(isValidPtr, 0) = BOOL_FALSE)) then
    displayError(ErrorTextLibClass$Inst,lastError, CHECK_MODE);
    destroyAddress(AddressLibClass$Inst, longAt(stkBasePtr, 0));
    ^nil;
  endif;
  /* stack Base is valid - call addr to get offset value */
  baseAddr := getOffset(AddressLibClass$Inst, longAt(stkBasePtr,0)); 
  destroyAddress(AddressLibClass$Inst, longAt(stkBasePtr, 0));
  ^baseAddr;
}
!!

/* 3/11/1992 10:13 - PUBLIC 
  If dirPrt is 1 if stack direction is high->low, else 0 is lowToHigh.
  return nil if error.
*/
Def getStackDirection(self | dirPtr)
{ 
  dirPtr := new(Struct, 4);
   
  if pcallLock(self) then
    lastError := pcall( procs[#STKGETSTACKDIRECTION], sessionID, dirPtr);
    pcallUNLock(self);
  else 
    lastError := ERR_PCALL_RECURSION ;
  endif ;

  if (lastError <> GOOD) then
    displayError(ErrorTextLibClass$Inst,lastError, CHECK_MODE);
    ^(lowToHigh := nil);
  endif;
  ^(lowToHigh := byteAt(dirPtr, 0)); 
}
!!

/* 3/3/1992 13:31 - PUBLIC 
  Return a U32 stack size value
*/
Def getStackSize(self | stkSizePtr)
{ 
  stkSizePtr := new( Struct, 4 );
  if pcallLock(self) then
    lastError := pcall( procs[#STKGETSTACKSIZE], sessionID, stkSizePtr);
    pcallUNLock(self);
  else 
    lastError := ERR_PCALL_RECURSION ;
  endif ;

  if (lastError <> GOOD) then
    displayError(ErrorTextLibClass$Inst,lastError,CHECK_MODE);  
    ^nil;
  endif;
  ^(stackSize := longAt(stkSizePtr, 0));
}
!!

/* 3/6/1992 15:14 - PRIVATE 
  Take a "STK_DISPLAY_PTR *" and convert its text into a collection.
  Free the C storage upon completion. Return nil if failed. 
  */
Def getTextFromAddr(self, longCAddress | txtColl, txtLen, aStruct, handle, numF)
{ 
  /* Check if address is not nil nor NULL */
  if not(longCAddress) cor (longCAddress = 0L) then
    ^nil;
  endif;
  
  /* Get the struct less the text[] */
  aStruct := copyFromLong( new(Struct, 8), longCAddress);
  /* Get number of frame in text[] */
  numF := wordAt(aStruct, 2);    /* keep it */
  /* Get textLength of text[] */
  txtLen := longAt(aStruct, 4);
  /* Get the allocationIndicator - STK_TMALLOC or GlobalAlloc handle */
  handle := wordAt(aStruct, 0);
  
  /* Create a new TextCollection and convert the string into it */
  add((txtColl := new(TextCollection, 1)), "");
  insertText(txtColl, physicalString(copyFromLong(new(Struct, txtLen),
    (longCAddress + 8) )), 0 , 0);
  /* Free the storage */
  if (handle <> 0) then    
    Call GlobalFree(handle);
  else
    cFree( MallocLibClass$Inst, longCAddress);
  endif;
  ^txtColl;
}
!!

/* 3/2/1992 17:12 - PRIVATE */
Def initialize(self, hWnd | sesPtr, bufPtr)
{
  sesPtr := new( Struct, 4 ) ; 
  if pcallLock(self) then
    lastError := pcall( procs(StackLibClass$Inst)
                [#STKSTARTSESSION], hWnd, sesPtr);
    pcallUNLock(self);
  else 
    lastError := ERR_PCALL_RECURSION ;
  endif ;

  if (lastError <> GOOD) 
     displayError(ErrorTextLibClass$Inst,lastError, CHECK_MODE);
     ^nil; 
  endif;
  /* init session variables */
  sessionID       := longAt(sesPtr,0); 
  alarmLimit      := nil;
  alarmPercent    := 95;
  stackSize       := 0;
  currentSP       := 0;
  baseAddr        := 0;
  hwMarkAddr      := 0; 
  enableStkAlarm  := BOOL_FALSE;
  enableStkHWMark := BOOL_FALSE;
  lowToHigh       := nil;
  ^self
}
!!

/* 3/2/1992 17:17 - PUBLIC */
Def open?(self)
{
  ^sessionID  /* session id is nil if not a valid session */
}
 
!!

/* 3/3/1992 13:31 - PUBLIC */
Def openStack(self, frameCount | numFramePtr)
{ 
  numFramePtr := new( Struct, 2 );
  putByte(numFramePtr, frameCount, 0 ) ;
   
  if pcallLock(self) then
    lastError := pcall( procs[#STKOPENSTACK], numFramePtr, sessionID);
    pcallUNLock(self);
  else 
    lastError := ERR_PCALL_RECURSION ;
  endif ;

  if (lastError <> GOOD) then
    displayError(ErrorTextLibClass$Inst,lastError, CHECK_MODE);
    ^nil;
  endif;
  ^wordAt(numFramePtr,0);
}
!!

/* 3/3/1992 15:14 - PUBLIC */
Def setAlarmLimit(self, alarm | addrDesc )
{
  if not(addrDesc := createAddress( AddressLibClass$Inst )) then
    ^nil
  endif;

  /* Prepare to Set alarm limit */
  if ((lastError := setOffset(AddressLibClass$Inst, addrDesc, alarm)) 
    cand (lastError <> GOOD)) then
    destroyAddress(AddressLibClass$Inst, addrDesc);
    ^nil; 
  endif;
  
  if pcallLock(self) then
    lastError = pcall( procs[#STKSETALARMLIMIT], sessionID, addrDesc);
    pcallUNLock(self);
  else 
    lastError := ERR_PCALL_RECURSION ;
  endif ;

  if (lastError <> GOOD) then
    displayError(ErrorTextLibClass$Inst,lastError, CHECK_MODE);
    /* Destroy the addrDesc */
    destroyAddress(AddressLibClass$Inst, addrDesc);
    ^nil;
  endif;
  alarmLimit := alarm;    
  ^GOOD;
}
!!

/* 3/2/1992 17:12 - PRIVATE */
Def setIVars(self, hL, n, o, p, gNS)
{
  hLib     := hL ;
  name     := n  ;
  ordinals := o  ;
  procs    := p  ;
  globalNameSymbol := gNS ;
}

!!

/* 3/3/1992 15:14 - PUBLIC 
  Set stack base address and destroy the input addrDesc.
  NOTES: stkBaseDesc is kept by Stack Server until the session is closed.
  It will be destroyed by the Stack Server.
*/
Def setStackBase(self, stkBaseDesc )
{   
  if not(baseAddr := getOffset(AddressLibClass$Inst, stkBaseDesc)) then
    /* Destroy the addrDesc because of error */
    destroyAddress(AddressLibClass$Inst, stkBaseDesc);
    ^nil;
  endif;

  /* Set stack base for server */    
  if pcallLock(self)
  then
    lastError = pcall( procs[#STKSETSTACKBASE], sessionID, stkBaseDesc);
    pcallUNLock(self);
  else 
    lastError := ERR_PCALL_RECURSION ;
  endif ;

  if (lastError <> GOOD) then
    displayError(ErrorTextLibClass$Inst,lastError, CHECK_MODE);
    /* Always destroy stkBaseDesc */
    destroyAddress(AddressLibClass$Inst, stkBaseDesc);
    ^nil;
  endif; 
  ^GOOD;
}
!!

/* 3/3/1992 15:41 - PUBLIC */
Def setStackSize(self, stkSize | iniValue)
{ 
  if (stkSize cand (stkSize < 0)) then
    /* requested stack size is >=0x80000000L so force to a reasonable number */
    stackSize := 1024;
    displayFormattedError(ErrorTextLibClass$Inst, 
       ER_STACK_TOO_LARGE, FORCE_POPUP, nil, nil, nil);
  endif;

  /* If stackSize = 0, use the value in the pwrviews.ini file, else 1K */
  if not(stkSize) cor (stkSize = 0) then
     if not(iniValue := getIniValueNum(TheProfileInfoObj, "StackInfo", "StackSize")) cor
        (iniValue = 0) cor (iniValue < 0) then
        displayFormattedError(ErrorTextLibClass$Inst, 
           ER_STACK_INVALID_SIZE, FORCE_POPUP, nil, nil, nil);
        stkSize := 1024;      /* 1K default */
     else
        stkSize := iniValue;  /* Use ini value */     
     endif;
  endif;

  if pcallLock(self)
  then
    lastError := pcall( procs[#STKSETSTACKSIZE], sessionID, asLong(stkSize));
    pcallUNLock(self);
  else 
    lastError := ERR_PCALL_RECURSION ;
  endif ;

  if (lastError <> GOOD)
  then
    displayError(ErrorTextLibClass$Inst,lastError, CHECK_MODE);
    ^nil;
  endif;
  stackSize := stkSize;
  ^GOOD; 
}

!!
