home *** CD-ROM | disk | FTP | other *** search
- /* > VSIclib */
-
- /* C library intercepts for high store use */
-
- /*******************************************************
- * Need to put in any C routines that have a different
- * action when called from high area.
- *
- * The alias file for vsilink should include:-
- * remove VSI_remove
- * rename VSI_rename
- * fopen VSI_fopen
- * freopen VSI_freopen
- * setbuf VSI_setbuf
- * setvbuf VSI_setvbuf
- * fread VSI_fread
- * fwrite VSI_fwrite
- * calloc VSI_calloc
- * free VSI_free
- * malloc VSI_malloc
- * realloc VSI_realloc
- * getenv VSI_getenv
- * system VSI_system
- *
- * The following can be included to give access to the
- * low store versions when executing in high store. Its
- * better to have one's one routines in low store for any
- * access to such facilities.
- * low_calloc calloc
- * low_free free
- * low_malloc malloc
- * low_realloc realloc
- *******************************************************/
-
- /*#define TRACE*/
-
- #include <setjmp.h>
- #include <signal.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <kernel.h>
- #include <swis.h>
- #include "VSIman.h"
-
-
- typedef unsigned char bool;
-
- #define FALSE 0
- #define TRUE 1
-
- #define SMALL_MAX 255
-
- extern void *VSI_ZI_Base;
- extern void *VSI_ZI_Limit;
-
- /* stdio.h intercepts */
-
- typedef char filename_t[256];
-
-
- /*
- * remove
- */
-
- int VSI_remove(const char *filename)
- {
- filename_t lname;
-
- strcpy(lname, filename);
- return remove(lname);
- }
-
-
- /*
- * rename
- */
-
- int VSI_rename(const char *old, const char *new)
- {
- filename_t lold, lnew;
-
- strcpy(lold, old);
- strcpy(lnew, new);
-
- return rename(lold, lnew);
- }
-
-
- /*
- * fopen
- */
-
- FILE *VSI_fopen(const char *filename, const char *mode)
- {
- filename_t lname;
-
- strcpy(lname, filename);
-
- return fopen(lname, mode);
- }
-
-
- /*
- * freopen
- */
-
- FILE *VSI_freopen(const char *filename, const char *mode,
- FILE *stream)
- {
- filename_t lname;
-
- strcpy(lname, filename);
-
- return freopen(lname, mode, stream);
- }
-
-
- /*
- * setbuf
- */
-
- void VSI_setbuf(FILE *stream, char *buf)
- {
- if ((unsigned) buf < VSI_Space || (unsigned) buf >= VSI_Top)
- setbuf(stream, buf);
- else
- setvbuf(stream, NULL, _IOFBF, BUFSIZ);
- }
-
-
- /*
- * setvbuf
- */
-
- int VSI_setvbuf(FILE *stream, char *buf, int mode, size_t size)
- {
- if ((unsigned) buf < VSI_Space || (unsigned) buf >= VSI_Top)
- return setvbuf(stream, buf, mode, size);
- else
- return setvbuf(stream, NULL, mode, size);
- }
-
-
- /* fread and fwrite may invoke a direct call to OS_GBPB,
- * I'm not certain if they do at the moment.
- */
-
-
- /* fread - when called from high area shuld check whether
- * area is in high space and if so do a page at a time.
- */
-
- size_t VSI_fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
- {
- size_t rem, len;
- unsigned adr, top;
-
- #ifdef TRACE
- printf("VSI_fread %p %d %d\n", ptr, size, nmemb);
- #endif
-
- if ((unsigned) ptr < VSI_Space || (unsigned) ptr >= VSI_Top)
- return fread(ptr, size, nmemb, stream);
-
- rem = size * nmemb;
-
- if (rem == 0)
- return fread(ptr, size, nmemb, stream);
-
- adr = (unsigned) ptr;
- top = adr + (unsigned) rem - 1;
- len = 0;
-
- while (((adr ^ top) >> VSI_Page_Ln) != 0)
- {
- size_t want, got;
-
- want = ((adr + VSI_PageSize) & ~(VSI_PageSize - 1)) - adr;
-
- #ifdef TRACE
- printf("CALL fread %x %d %d\n", adr, 1, want);
- #endif
-
- /* Make certain area is writable */
-
- VSI_ENSURE_WRITE(adr);
-
- got = fread((void *) adr, 1, want, stream);
- len += got;
- if (want != got)
- return len;
- adr += got;
- }
-
- #ifdef TRACE
- printf("CALL fread %x %d %d\n", adr, 1, top - adr + 1);
- #endif
-
- /* Make certain area is writable */
-
- VSI_ENSURE_WRITE(adr);
-
- len += fread((void *) adr, 1, top - adr + 1, stream);
-
- VSI_ENSURE_OFF();
- VSI_Locked = NULL;
-
- #ifdef TRACE
- printf("End VSI_fread %d\n", len / size);
- #endif
-
- return len / size;
- }
-
-
- /* fwrite - when called from high area shuld check whether
- * area is in high space and if so do a page at a time.
- */
-
- size_t VSI_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
- {
- size_t rem, len;
- unsigned adr, top;
-
- #ifdef TRACE
- printf("VSI_fwrite %p %d %d\n", ptr, size, nmemb);
- #endif
-
- if ((unsigned)ptr < VSI_Space || (unsigned)ptr >= VSI_Top)
- return fwrite(ptr, size, nmemb, stream);
-
- rem = size * nmemb;
-
- if (rem == 0)
- return fwrite(ptr, size, nmemb, stream);
-
- adr = (unsigned) ptr;
- top = adr + (unsigned) rem - 1;
- len = 0;
-
- while (((adr ^ top) >> VSI_Page_Ln) != 0)
- {
- size_t want, got;
-
- want = ((adr + VSI_PageSize) & ~(VSI_PageSize - 1)) - adr;
-
- #ifdef TRACE
- printf("CALL fwrite %x %d %d\n", adr, 1, want);
- #endif
-
- /* Make certain area is readable */
-
- VSI_ENSURE_READ(adr);
-
- got = fwrite((void *) adr, 1, want, stream);
- len += got;
- if (want != got)
- return len;
- adr += got;
- }
-
- #ifdef TRACE
- printf("CALL fwrite %x %d %d\n", adr, 1, top - adr + 1);
- #endif
-
- /* Make certain area is readable */
-
- VSI_ENSURE_READ(adr);
-
- len += fwrite((void *) adr, 1, top - adr + 1, stream);
-
- VSI_ENSURE_OFF();
-
- #ifdef TRACE
- printf("End VSI_fwrite %d\n", len / size);
- #endif
-
- return len / size;
- }
-
-
- /* Storage allocation in the high area
- * Taken from Kernighan and Ritchie
- *
- * free and realloc revert to standard if a high area
- * or NULL not specified.
- */
-
- typedef long Align; /* for alignment to long boundary */
-
- union header { /* block header: */
- struct {
- union header *ptr; /* next block if on free list. */
- unsigned size; /* size of this block */
- } s;
- Align x; /* force alignment of blocks */
- };
-
- typedef union header Header;
-
- static Header base; /* empty list to get started */
- static Header *freep = NULL; /* start of free list */
-
-
- /* free - when called from high area will free space
- * if it was allocated from high space else will call
- * the low version of free.
- */
-
- void VSI_free(void *ptr)
- {
- Header *bp, *p;
-
- #ifdef TRACE
- printf("VSI_free %p\n", ptr);
- #endif
-
- /* If original allocated by standard malloc then */
- /* have to do standard free. */
- /* Standard free deals with NULL ok. */
-
- if ((unsigned) ptr < VSI_Space || (unsigned) ptr >= VSI_Top)
- {
- free(ptr);
- return;
- }
-
- /* free block in high space */
-
- bp = (Header *)ptr - 1; /* point to block header */
-
- for (p = freep; !(bp > p && bp < p->s.ptr); p = p->s.ptr)
- {
- if (p >= p->s.ptr && (bp > p || bp < p->s.ptr))
- {
- /* freed block at start or end of area */
-
- break;
- }
- }
-
- if (bp + bp->s.size == p->s.ptr)
- {
- /* join to upper nbr */
-
- bp->s.size += p->s.ptr->s.size;
- bp->s.ptr = p->s.ptr->s.ptr;
- }
- else
- {
- bp->s.ptr = p->s.ptr;
- }
-
- if (p + p->s.size == bp)
- {
- /* join to lower nbr */
-
- p->s.size += bp->s.size;
- p->s.ptr = bp->s.ptr;
- }
- else
- {
- p->s.ptr = bp;
- }
-
- #ifdef TRACE
- printf("VSI_free ends\n");
- #endif
-
- freep = p;
- }
-
-
- /*
- * morecore - almost a dummy
- */
-
- static bool morecore_done = FALSE;
-
- static Header *morecore(unsigned nu)
- {
- unsigned adr, len;
- Header *up;
-
- #ifdef TRACE
- printf("morecore\n");
- #endif
-
- if (morecore_done)
- return NULL;
- morecore_done = FALSE;
-
- adr = ((unsigned) VSI_ZI_Limit + 3) & -4;
- len = VSI_Top - adr;
-
- up = (Header *) adr;
- up->s.size = len / sizeof(Header);
-
- VSI_free((void *)(up+1));
-
- #ifdef TRACE
- printf("morecore %p %d %d\n", up, up->s.size, sizeof(Header));
- #endif
-
- return freep;
- }
-
-
- /*
- * malloc - when called from high area will allocate
- * pageable space.
- */
-
- void *VSI_malloc(size_t size)
- {
- Header *p, *prevp;
- unsigned nunits;
-
- #ifdef TRACE
- printf("VSI_malloc %d\n", size);
- #endif
-
- nunits = (size+sizeof(Header)-1)/sizeof(Header) + 1;
-
- if ((prevp = freep) == NULL)
- {
- /* no free list yet */
-
- base.s.ptr = freep = prevp = &base;
- base.s.size = 0;
- }
-
- for (p = prevp->s.ptr; ; prevp = p, p = p->s.ptr)
- {
- if (p->s.size >= nunits)
- {
- /* big enough */
-
- if (p->s.size == nunits)
- {
- /* exactly */
-
- prevp->s.ptr = p->s.ptr;
- }
- else
- {
- /* allocate till end */
-
- p->s.size -= nunits;
- p += p->s.size;
-
- p->s.size = nunits;
- }
-
- freep = prevp;
-
- #ifdef TRACE
- printf("VSI_malloc returns %p\n", (void *)(p+1));
- #endif
-
- return (void *)(p+1);
- }
-
- if (p == freep) /* wrapped around free list */
- {
- if ((p = morecore(nunits)) == NULL)
- {
- #ifdef TRACE
- printf("VSI_malloc returns NULL\n");
- #endif
- return NULL; /* none left */
- }
- }
- }
- }
-
-
- /*
- * calloc - when called from high area will allocate
- * pageable space.
- */
-
- extern void *VSI_calloc(size_t nmemb, size_t size)
- {
- size_t len = nmemb * size;
- void *ptr = VSI_malloc(len);
-
- #ifdef TRACE
- printf("VSI_calloc %ptr nmemb %d size %d\n", ptr, nmemb, size);
- #endif
-
- return memset(ptr, 0, len);
- }
-
-
- /*
- * realloc - when called from high area will allocate
- * pageable space.
- */
-
- void *VSI_realloc(void *ptr, size_t size)
- {
- void *newptr;
- unsigned len;
-
- #ifdef TRACE
- printf("VSI_realloc %p size %d\n", ptr, size);
- #endif
-
- if (ptr == NULL)
- return VSI_malloc(size);
-
- /* If original allocated by standard malloc then */
- /* have to do realloc using standard realloc. */
- /* No idea how long original is. */
-
- if ((unsigned) ptr < VSI_Space || (unsigned) ptr >= VSI_Top)
- return realloc(ptr, size);
-
- /* Very simple method, */
- /* - just get new space and copy over. */
-
- len = ((Header *)ptr)[-1].s.size;
- len = (len > size ? size : len);
-
- newptr = VSI_malloc(size);
-
- memcpy(newptr, ptr, len);
-
- VSI_free(ptr);
-
- return newptr;
- }
-
-
- /*
- * getenv
- */
-
- extern char *VSI_getenv(const char *name)
- {
- char lname[256];
-
- #ifdef TRACE
- printf("VSI_getenv %s\n", name);
- #endif
-
- strcpy(lname, name);
-
- return getenv(lname);
- }
-
-
- /*
- * system
- */
-
- extern int VSI_system(const char *string)
- {
- char lstring[256];
- int resp;
-
- #ifdef TRACE
- printf("VSI_system %s\n", string);
- #endif
-
- strcpy(lstring, string);
-
- VSI_Save();
-
- resp = system(lstring);
-
- VSI_Restore();
-
- return resp;
- }
-