/* class MemServLib */!!

inherit(ProvidedLibs, #MemServLib, #(memoryServerInstance), 2, nil)!!

now(class(MemServLib))!!

/* semiPRIVATE -- should only be called via require(XMemoryLib)
   Define entry points and load library.  Define any structs required.
*/
Def provide(self, path)
{
  ^initialise( new(self:ancestor), path )
}
!!

now(MemServLib)!!

/* Swap bytes in a word. */
Def swapBytesInWord(self, word | temp)
{ 
  if pcallLock(self)
    /* note: no return code; returns swapped bytes. */
    temp := pcall(procs[#MEMSWAPBYTESINWORD], word);
    pcallUNLock(self);
    lastError := GOOD;
  else
    lastError := ERR_PCALL_RECURSION;
  endif;

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

/* Swap bytes in a long. */
Def swapBytesInLong(self, long | temp)
{ 
  if pcallLock(self)
    /* note: no return code; returns swapped bytes. */
    temp := pcall(procs[#MEMSWAPBYTESINLONG], long);
    pcallUNLock(self);
    lastError := GOOD;
  else
    lastError := ERR_PCALL_RECURSION;
  endif;

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

/* PUBLIC
   Call memory DLL entry point to load memory verification error info.
*/
Def processVerifyError(self)
{
  if pcallLock(self) 
    lastError := pcall(procs[#MEMPROCESSVERIFYERROR]);
    pcallUNLock(self);
  else
    lastError := ERR_PCALL_RECURSION;
  endif;
  
  /* we're already in the middle of processing an error, so ignore
     error if any to prevent recursion. */
  ^GOOD;
}
!!
/* return the memory server instance */
Def memoryServer(self)
{
   ^memoryServerInstance;
}!!

/* 8/17/1992 17:22 - PUBLIC
  Ask memory server to flush caches
*/
Def memCacheInvalidate(self)
{ 
  if pcallLock(self) then
    lastError := pcall( procs[#MEMCACHEINVALIDATE] );
    pcallUNLock(self);
  else
    lastError := ERR_PCALL_RECURSION;
  endif;

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

/* 8/17/1992 17:22 - PUBLIC
  Set up a Source range addresses to be notified by the Memory server when the
  range is changed.
*/
Def setSourceMemoryRange(self, rangeDesc, rangeID)
{ 
  if pcallLock(self) then
    lastError := pcall( procs[#MEMSETSOURCERANGE], rangeDesc, asInt(rangeID));
    pcallUNLock(self);
  else
    lastError := ERR_PCALL_RECURSION;
  endif;

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

/* PRIVATE
   Define all entry points for library as prototypes.
*/
Def addImportProcs(self)
{
  add(self, #INITCSERVER,         1, #(0, 0));
  add(self, #MEMCACHEINVALIDATE,  1, nil );
  add(self, #MEMCLOSESESSION,     1, #(1));
  add(self, #MEMCOMPARE,          1, #(1, 1, 1, 1));
  add(self, #MEMCHECKSUM,         1, #(1, 1, 0, 1));
  add(self, #MEMDLGCOPYMEMORY,    1, #(0));
  add(self, #MEMDLGCOMPAREMEMORY, 1, #(0));
  add(self, #MEMFILL,             1, #(1, 1, 1, 0));
  add(self, #MEMGETACCESSSIZE,    1, #(1));
  add(self, #MEMGETVERIFYWRITES,  1, #(1));
  add(self, #MEMINITONCE,         1, nil);
  add(self, #MEMMOVE,             1, #(1, 1, 1));
  add(self, #MEMOPENSESSION,      1, #(1));
  add(self, #MEMPROCESSVERIFYERROR, 1, nil );
  add(self, #MEMREAD,             1, #(1, 0, 1, 0));
  add(self, #MEMSEARCH,           1, #(1, 1, 0, 1, 0, 1));
  add(self, #MEMSETACCESSSIZE,    1, #(0));
  add(self, #MEMSETSOURCERANGE,   1, #(1, 0));
  add(self, #MEMSETVERIFYWRITES,  1, #(0));
  add(self, #MEMSWAPBYTESINLONG,  1, #(1));
  add(self, #MEMSWAPBYTESINWORD,  0, #(0));
  add(self, #MEMTEST,             1, #(1, 1, 1, 1));
  add(self, #MEMWRITE,            1, #(1, 0, 1));
 
}!!

Def initialise(self, path)
{
   setName(self, path);
   addImportProcs(self);
   load(self);  /* raises alert if fails: alert(System, self, #libLoad) */
   initServer(self);
   memoryServerInstance := openSession(self);
}!!

/* PRIVATE */
Def initServer(self)
{
  if pcallLock(self)
  then
    lastError := pcall(procs[#MEMINITONCE]) ;
    pcallUNLock(self);
  else
    lastError := ERR_PCALL_RECURSION ;
  endif;
  displayError(ErrorTextLibClass$Inst,lastError,FORCE_POPUP);
  ^lastError;
}!!

/* PUBLIC
   Open a session with the Memory Server.
   Return a session instance (MemServLib) or nil.
*/
Def openSession(self | sessionInstance)
{
  sessionInstance := new(MemLibInst);

  if sessionInstance  /* pass on library name to offspring */
  then
    initialize(sessionInstance);
    setIVars(sessionInstance,
              hLib, name, ordinals, procs, globalNameSymbol);
  endif;

  ^sessionInstance
}
!!
