antoine-source/appleworksgs/Spell/Src/MEMORY.C
2023-03-04 03:45:20 +01:00

1 line
6.2 KiB
C
Executable File

/***********************************************************************\
Filename: memory.c
\***********************************************************************/
#include <memory.h>
#include "proxlib.h"
#include "proxio.h"
#include "spmemory.h"
#include "scdef.h"
#include "sp.h"
#include "spdef.h"
#ifndef MM_NBLKS
#define MM_NBLKS 4 /* Default number of blocks to use */
#endif
/* Control structure for each buffer. */
typedef struct mb_struct {
HANDLE mb_file; /* file the block came from */
UCHAR *mb_blk; /* block-sized buffer (actual data) */
int mb_blknum; /* block's block number in the file */
UCHAR mb_flags; /* priority and usage requested */
UCHAR mb_age; /* how long block has been in list */
struct mb_struct *mb_newer;/* pointer to newer block */
struct mb_struct *mb_older;/* pointer to older block */
} MEMBLK;
int Memup[] = { 0 }; /* Memory is initialized */
static MEMBLK Memlist[MM_NBLKS];/* Memory headers */
static MEMBLK *Memnewest[1]; /* Newest memory block */
/* Initialize the block buffering system. */
meminit()
{
register MEMBLK *mp;
/* If this has already been done, return. */
if (Memup[0])
return(1);
/* Allocate space for each memory block; initialize each control
structure. */
for (mp = Memlist + MM_NBLKS; --mp >= Memlist; )
{
if (!(mp->mb_blk = (char *) zalloc(_SPTHID[0], MM_BLKSIZE)))
return(0);
mp->mb_file = H_ERROR;
mp->mb_flags = 0;
mp->mb_newer = mp - 1;
mp->mb_older = mp + 1;
}
/* Make the linked list into a circular queue. */
Memlist[0].mb_newer = &Memlist[MM_NBLKS - 1];
Memlist[MM_NBLKS - 1].mb_older = Memlist;
/* Initialize the top of memory pointer. */
Memnewest[0] = Memlist;
/* Memory has been initialized */
Memup[0] = 1;
return(1);
}
/* See if a block for a given file is in memory. */
MEMBLK *memcheck(file, blknum)
HANDLE file; /* The file the block is in. */
int blknum; /* The block number. */
{
register MEMBLK *mp;
mp = Memnewest[0];
while (mp->mb_file != file || mp->mb_blknum != blknum)
{
mp = mp->mb_older;
if (mp == Memnewest[0])
return (NULL);
}
return (mp);
}
/* Put a buffer at the top of the list. This is the only routine that
changes the memory control links. */
void
memlink(mp)
register MEMBLK *mp;
{
register MEMBLK *new;
/* Do nothing if the buffer is already at the top of the list. */
new = Memnewest[0];
if (new == mp)
return;
/* Unlink the buffer from the list. */
mp->mb_newer->mb_older = mp->mb_older;
mp->mb_older->mb_newer = mp->mb_newer;
/* Add it to the top of the list. */
Memnewest[0] = mp;
mp->mb_newer = new->mb_newer;
mp->mb_older = new;
new->mb_newer->mb_older = mp;
new->mb_newer = mp;
}
/* Make a buffer unused. If the buffer contained modified data, write that
data to disk. */
memdel(mp)
register MEMBLK *mp;
{
/* Write the block, if it was modified. */
if (!memwrite(mp))
return (FALSE);
/* make the buffer unused. */
mp->mb_file = H_ERROR;
mp->mb_flags = 0;
/* Make this buffer the newest; since the list is circular, moving
the newest pointer down to the next oldest will make this block
the oldest. */
memlink(mp);
Memnewest[0] = (Memnewest[0])->mb_older;
return (TRUE);
}
/* Write a block to disk. */
memwrite(mp)
register MEMBLK *mp;
{
/* Do not write it if it was not modified. */
if (!(mp->mb_flags & MM_WRITE))
return (TRUE);
/* Seek to the proper place and then write the buffer. */
if (stdseek((long)mp->mb_blknum * MM_BLKSIZE, mp->mb_file)
|| stdwrite((char *)mp->mb_blk, MM_BLKSIZE, mp->mb_file)
!= MM_BLKSIZE)
return (FALSE);
/* Mark the buffer as no longer modified. */
mp->mb_flags &= ~MM_WRITE;
return (TRUE);
}
/* Get a buffer for a block. */
UCHAR *
memread(blknum, file, flags)
int blknum; /* Block number in file. */
HANDLE file; /* File to read. */
int flags; /* Read flags. */
{
MEMBLK *mp;
/* Look for the block in memory. If it is not in memory then read
it. */
if ((mp = memcheck(file, blknum)) == NULL)
{
/* Find a buffer to read into. */
mp = Memnewest[0];
while (1)
{
mp = mp->mb_newer;
if (mp == Memnewest[0])
{
mp = mp->mb_newer;
break;
}
if (mp->mb_age >= (flags & MM_PRMASK))
break;
}
/* Free the buffer. */
if (!memdel(mp))
return (NULL);
/* if MM_READ was specified, read the block from the file */
if (flags & MM_READ)
{
if (stdseek((long)blknum * MM_BLKSIZE, file) || stdread((char *)
mp->mb_blk, MM_BLKSIZE, file) != MM_BLKSIZE)
return (NULL);
}
/* Initialize the memory data. */
mp->mb_file = file;
mp->mb_blknum = blknum;
mp->mb_flags = flags;
}
else
/* Make this block the newest; update its modify flag; store its
priority and return the block. */
mp->mb_flags |= flags & MM_WRITE;
mp->mb_age = flags & MM_PRMASK;
memlink(mp);
return (mp->mb_blk);
}
/* If file is NULLPTR write all modified blocks to disk. If not, release
all memory associated with the file. */
memflush(file)
HANDLE file; /* The file to flush. */
{
MEMBLK *mp;
for (mp = Memlist + MM_NBLKS; --mp >= Memlist; )
{
if (!file)
{
if (!memwrite(mp))
return (ERROR);
}
else if (mp->mb_file == file && !memdel(mp))
return (ERROR);
}
return (OKAY);
}
/* Change the block number associated with a block already in memory. */
int
memswitch(file, oldnum, newnum)
HANDLE file; /* The file to do it to. */
int oldnum; /* The old block number */
int newnum; /* The new block number */
{
register MEMBLK *mp;
if ((mp = memcheck(file, oldnum)) == NULL) {
return (FALSE);
}
mp->mb_blknum = newnum;
return (TRUE);
}