home *** CD-ROM | disk | FTP | other *** search
- /* CFPORT.C */
- /* PORTABILITY FOR CFF -- MODIFY TO SUIT THE COMPILER/OS IN USE */
-
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <stdlib.h>
- #include <fcntl.h>
- #include <direct.h>
- #include <errno.h>
- #include <io.h>
- #include <stdio.h>
- #include <time.h>
- #include <dirent.h>
- #include "../cff.h"
-
- extern void *mymemmove(void *, void *, long);
-
- #define PCDOS 1
-
- #define NIBBLE 128
- #define CHUNK_SIZE 8192
-
- #ifndef HEAPSTART
- #define HEAPSTART 0x500000
- #endif
-
- unsigned long heapcreep;
- void *heapstart = (void *)HEAPSTART;
-
-
- extern volatile int errno;
-
- static STOR BIGZERO;
-
-
- /* DUMMY ROUTINES TO PREVENT LINKING UNWANTED MALLOC LIKE STUFF */
- int _heapchk(void)
- {
- return 0;
- }
- int _heapset(unsigned a)
- {
- return 0;
- }
- void *_expand (void *mem, size_t new_size)
- {
- return NULL;
- }
- size_t _msize (const void *mem)
- {
- return mallocsize(mem);
- }
- unsigned malloc_usable_size (void *mem)
- {
- return mallocsize((const void *)mem);
- }
-
- /* ---------------- END OF MALLOC DUMMYS ------------- */
-
- static __inline__ unsigned long
- round_up(long size, long amt)
- {
- return (size&(amt-1)) ? size+(amt-(size&(amt-1))) : size;
- }
-
- static int testflags = 0;
- void
- cfport_settestflags(int flags)
- {
- testflags |= flags;
- }
- void
- cfport_clrtestflags(int flags)
- {
- testflags &= ~flags;
- }
-
- static void
- fix_statbuf(struct stat *stat, CFSTAT *sbuf)
- {
- sbuf->st_atime = stat->st_atime;
- sbuf->st_mtime = stat->st_mtime;
- sbuf->st_ctime = stat->st_ctime;
- sbuf->st_size = stat->st_size;
- sbuf->st_alloc = stat->st_size;
- sbuf->st_filesize = stat->st_size;
- sbuf->st_filealloc = stat->st_size;
- sbuf->st_blksize = stat->st_blksize;
- sbuf->st_dev = stat->st_dev;
- sbuf->st_ino = stat->st_ino;
- sbuf->st_nlink = stat->st_nlink;
- sbuf->st_uid = stat->st_uid;
- sbuf->st_gid = stat->st_gid;
- sbuf->st_rdev = stat->st_rdev;
- sbuf->st_mode = stat->st_mode;
- }
- void *
- PORTSBRK(unsigned long amt)
- {
- return ((void *)sbrk(amt));
- }
- void
- PORTHEAPSTART(void)
- {
- void *curstart = sbrk(0);
- char *newstart = NULL;
- if(curstart > heapstart)
- {
- cfprintf("CFFINIT: The heap safety zone was exceeded by %d bytes.\n",
- -((long)(heapstart - curstart)));
- exit(-1);
- }
- heapcreep = (unsigned long)(heapstart - curstart);
- if((newstart = (void *)sbrk(heapcreep)) == (void *)-1) {
- cfprintf("Failed to set heap: zone=%lu HEAPSTART=%p curstart=%p.\n",
- heapcreep, heapstart, curstart);
- exit(-2);
- }
- else if(heapcreep && newstart+heapcreep != heapstart) {
- cfprintf("Heap was not set properly: desired=%p result=%p zone=%lu.\n",
- heapstart, newstart, heapcreep);
- exit(-3);
- }
- }
- int
- PORTSTAT(void *path, CFSTAT *sbuf)
- {
- struct stat _stat;
- int result = stat(path, &_stat);
- if(result == 0)
- fix_statbuf(&_stat, sbuf);
- return result;
- }
- void
- PORTFSTAT(int handle, CFSTAT *sbuf)
- {
- struct stat stat;
-
- fstat(handle, &stat);
- fix_statbuf(&stat, sbuf);
- }
-
- long
- PORTREAD(long handle, void *mem_addr, STOR dsk_addr, long amount)
- {
- lseek(handle, dsk_addr.a0, SEEK_SET);
- return read(handle, mem_addr, amount);
- }
- long
- PORTWRITE(long handle, void *mem_addr, STOR dsk_addr, long amount)
- {
- lseek(handle, dsk_addr.a0, SEEK_SET);
- return write(handle, mem_addr, amount);
- }
- void
- PORTSEEK(long handle, STOR spot, int mode, STOR *loc)
- {
- STOR ret;
- switch(mode)
- {
- case S_END:
- mode = SEEK_END;
- break;
- case S_CUR:
- mode = SEEK_CUR;
- break;
- case S_SET:
- mode = SEEK_SET;
- break;
- default:
- mode = -1;
- }
- ret.a4.s1 = 0;
- ret.a4.s0 = lseek((int)handle, spot.a0, mode);
- if(loc)
- *loc = ret;
- }
- long
- PORTOPEN(void *path, int mode)
- {
- int omode = O_BINARY;
-
- if((mode & F_RDWR) == F_RDONLY)
- omode |= O_RDONLY;
- else if((mode & F_RDWR) == F_WRONLY)
- omode |= O_WRONLY;
- else if((mode & F_RDWR) == F_RDWR)
- omode |= O_RDWR;
- if(mode & F_TRUNC)
- omode |= O_TRUNC;
- if(mode & F_EXCL)
- omode |= O_EXCL;
- if(mode & F_APPEND)
- omode |= O_APPEND;
-
- return open(path,omode);
- }
- long
- PORTCLOSE(long handle)
- {
- return close((int)handle);
- }
- long
- PORTCREATE(void *path, int mode)
- {
- return creat(path, S_IREAD|S_IWRITE);
- }
- long
- PORTUNLINK(void *path)
- {
- return unlink(path);
- }
- #if PCDOS == 1
- static void
- dos_truncate(short handle, long amount)
- {
- #include <dos.h>
- union REGS r;
-
- r.h.al = 0; /* SEEK_SET */
- r.h.ah = 0x42; /* seek */
- r.x.bx = handle;
- r.x.dx = (short)amount;
- r.x.cx = (short)(amount>>16);
- intdos(&r,&r);
-
- r.h.ah = 0x40; /* write */
- r.x.bx = handle;
- r.x.cx = 0; /* amount == 0 */
- intdos(&r,&r);
-
- r.h.ah = 0x3e; /* close */
- r.x.bx = handle;
- intdos(&r,&r);
- }
- #endif
- long
- PORTTRUNCATE(long handle, char *path, STOR amount)
- {
- #if PCDOS == 1
- /* DJCC has a bugged ftruncate */
- dos_truncate((short)handle, amount.a0);
- return PORTOPEN(path, F_RDWR);
- #else
- ftruncate((int)handle, amount.a0);
- return handle;
- #endif
- }
- void
- PORTCLOSETRUNC(long handle, STOR amount)
- {
- #if PCDOS == 1
- /* DJCC has a bugged ftruncate */
- dos_truncate((short)handle, amount.a0);
- #else
- ftruncate((int)handle, amount.a0);
- close((int)handle);
- #endif
- }
- void
- PORTFLUSH(long handle)
- {
- #if 0
- if(handle < 0)
- sync();
- else
- #endif
- fsync((int)handle);
- }
-
- char *
- PORTGETCWD(void *buf, int maxlen)
- {
- char *result;
-
- result = getcwd((char *)buf, maxlen);
- ((char *)buf)[maxlen] = 0;
- if(result)
- {
- while(*((char *)buf))
- {
- if(*((char *)buf) == '\\') *((char *)buf) = '/';
- ++((char *)buf);
- }
- }
- return result;
- }
-
- long
- PORTCHDIR(void *path)
- {
- return chdir(path);
- }
- unsigned long
- PORTTIME(void)
- {
- return time(NULL);
- }
- unsigned long
- PORTCLOCK(void)
- {
- return clock();
- }
- volatile void
- PORTABORT(void)
- {
- extern volatile void abort();
- abort();
- }
-
- /* THE BASIC OS DRIVERS */
-
- /* Primary Memory driver */
- long
- pmem_driver(int func, int handle, void *mem_addr, STOR dsk_addr, long amount)
- {
- switch(func)
- {
- case S_GETSPACE:
- {
- unsigned long min, nib, current;
-
- amount = round_up(amount, CHUNK_SIZE);
- min = round_up(amount / 4, CHUNK_SIZE);
- nib = round_up(amount / 16, CHUNK_SIZE);
- current = amount;
- ((STOR *)mem_addr)->a2.size = 0;
- ((STOR *)mem_addr)->a2.type = STO_CHUNK;
-
- while(current >= min) {
- if((((STOR *)mem_addr)->a1 = PORTSBRK(current)) != (void *)-1) {
- if(((STOR *)mem_addr)->a0 & (NIBBLE-1))
- {/* Normally the system uses NIBBLE bytes as the alignment */
- ((STOR *)mem_addr)->a0 =
- round_up(((STOR *)mem_addr)->a0, NIBBLE);
- current -= NIBBLE;
- }
- ((STOR *)mem_addr)->a2.size = current;
- return 0;
- }
- current -= nib;
- }
- return 1;
- }
- case S_GIVESPACE:
- return 1;
- default:
- return 1;
- }
- return 0;
- }
-
- /* Secondary Memory driver */
- long
- smem_driver(int func, int handle, void *mem_addr, STOR dsk_addr, long amount)
- {
- if(!(testflags & 1))
- {/*
- IF SECONDARY MEMORY REALLY EXISTS, THEN PUT A REAL DRIVER HERE.
- The system adapts to a 0 return from S_GETSPACE by mapping
- secondary memory to primary memory when cfinit is called.
- S_OPEN is never called.
- */
- switch (func)
- {
- case S_GETSPACE:
- *((long *)mem_addr) = 0;
- break;
- }
- return -1;
- } /* END: Real driver */
- else {
- /* THIS CODE IS JUST FOR TESTING PURPOSES, IT USES A LOCAL MEMORY BUFFER */
-
- #define SMEMMAX (4096*1024)
- static char *sbuf = NULL;
- static long smemalloc = 0;
-
- if(sbuf == NULL)
- if((sbuf = PORTSBRK(SMEMMAX)) == (void *)-1)
- return -1;
-
- switch(func)
- {
- case S_CLOSE:
- return 0; /* a real driver would do something */
- case S_READBLK:
- case S_WRITEBLK:
- {
- char *smemaddr = sbuf + dsk_addr.a0;
- long xfer = amount;
- if(dsk_addr.a0 + amount > smemalloc)
- xfer = smemalloc - dsk_addr.a0;
- if(xfer < 0) {
- return -1;
- }
- if(func == S_READBLK)
- mymemmove(mem_addr, smemaddr, xfer);
- else mymemmove(smemaddr, mem_addr, xfer);
- return xfer;
- }
- case S_GETSPACE:
- amount = round_up(amount, CHUNK_SIZE);
- ((STOR *)mem_addr)->a0 = smemalloc;
- ((STOR *)mem_addr)->a2.size = 0;
- ((STOR *)mem_addr)->a2.type = STO_CHUNK;
- if(amount + smemalloc < SMEMMAX) {
- ((STOR *)mem_addr)->a2.size = amount;
- smemalloc += amount;
- return 0;
- } else {/* Not enough space available, return error + avail */
- ((STOR *)mem_addr)->a2.size =
- (SMEMMAX - smemalloc) & ~CHUNK_SIZE;
- return 1;
- }
- case S_GIVESPACE:
- #if 0
- cfprintf("SMEM: GIVESPACE at loc=%lx size=%lu curbase=%lx\n",
- ((STOR *)mem_addr)->a0, ((STOR *)mem_addr)->a2.size, smemalloc);
- #endif
- if(((STOR *)mem_addr)->a0 ==
- smemalloc - ((STOR *)mem_addr)->a2.size)
- {/* Accept returns if they are at the end */
- smemalloc -= ((STOR *)mem_addr)->a2.size;
- #if 0
- cfprintf("SMEM: Truncate to %lu bytes\n", smemalloc);
- #endif
- return 0;
- }
- break;
- default:
- break;
- }
- return 1;
- }/* END: test driver */
- }
-
- /* Internal file driver */
- long
- cfile_driver(int func, int handle, void *mem_addr, STOR dsk_addr, long amount)
- {
- long result = 0;
-
- switch(func)
- {
- case S_READBLK:
- result = PORTREAD(handle, mem_addr, dsk_addr, amount);
- break;
- case S_WRITEBLK:
- result = PORTWRITE(handle, mem_addr, dsk_addr, amount);
- break;
- case S_GETSPACE:
- {
- u_long result;
- STOR base;
- STOR end;
- PORTSEEK(handle, BIGZERO, S_END, &base);
- amount = round_up(amount, CHUNK_SIZE);
- end.a4.s0 = base.a0 + amount-1;
- end.a4.s1 = 0;
- PORTWRITE(handle, "0", end, 1);
- PORTSEEK(handle, BIGZERO, S_END, &end);
- result = end.a0 - base.a0;
- ((STOR *)mem_addr)->a0 = base.a0;
- ((STOR *)mem_addr)->a2.size = result;
- ((STOR *)mem_addr)->a2.type = STO_CHUNK;
- return (result == amount) ? 0:1;
- }
- case S_GIVESPACE:
- {
- STOR base;
- PORTSEEK(handle, BIGZERO, S_END, &base);
- if((((STOR *)mem_addr)->a0 + ((STOR *)mem_addr)->a2.size) == base.a0)
- {/* OK to return space if at end */
- #if 0
- long result;
- base.a0 -= ((STOR *)mem_addr)->a2.size;
- result = PORTTRUNCATE(handle, base);
- #endif
- return 0;
- }
- else return 1;
- }
- case S_OPEN:
- result = PORTOPEN(mem_addr, handle);
- break;
- case S_CLOSE:
- result = PORTCLOSE(handle);
- break;
- case S_CREATE:
- result = PORTCREATE(mem_addr, handle);
- break;
- case S_UNLINK:
- result = PORTUNLINK(mem_addr);
- break;
- case S_SEEK:
- PORTSEEK(handle, dsk_addr, amount, mem_addr);
- break;
- case S_FLUSH:
- PORTFLUSH(handle);
- break;
- case S_CLOSETRUNC: /* truncate and close, (PCDOS needs this) */
- PORTCLOSETRUNC(handle, dsk_addr);
- break;
- default:
- return 1;
- }
- return result;
- }
- /* External file driver */
- long
- xfile_driver(int func, int handle, void *mem_addr, STOR dsk_addr, long amount)
- {
- long result = 0;
-
- switch(func)
- {
- case S_GETSPACE:
- ((STOR *)mem_addr)->a2.size = 0;
- case S_GIVESPACE:
- return 1;
- case S_OPEN:
- result = PORTOPEN(mem_addr, handle);
- break;
- case S_CLOSE:
- result = PORTCLOSE(handle);
- break;
- case S_UNLINK:
- result = PORTUNLINK(mem_addr);
- break;
- case S_CREATE:
- result = PORTCREATE(mem_addr,handle);
- break;
- case S_READBLK:
- result = PORTREAD(handle, mem_addr, dsk_addr, amount);
- break;
- case S_WRITEBLK:
- result = PORTWRITE(handle, mem_addr, dsk_addr, amount);
- break;
- case S_SEEK:
- PORTSEEK(handle, dsk_addr, amount, mem_addr);
- break;
- case S_FLUSH:
- PORTFLUSH(handle);
- break;
- default:
- return 1;
- }
- return result;
- }
- void *
- PORTOPENDIR(char *name)
- {
- return opendir(name);
- }
- void *
- PORTREADDIR(void *it, CFDIRENT *d)
- {
- struct dirent *rd;
- if((rd = readdir(it))) {
- d->d_namlen = rd->d_namlen;
- d->d_name = rd->d_name;
- d->d_mode = M_EXTRNFILE;
- }
- return rd;
- }
- void
- PORTTELLDIR(void *it, STOR *loc)
- {
- STOR me;
- me.item = 0;
- me.a0 = telldir(it);
- if(loc)
- *loc = me;
- }
- void
- PORTSEEKDIR(void *it, STOR *loc)
- {
- seekdir(it, loc->a0);
- }
- void
- PORTREWINDDIR(void *it)
- {
- rewinddir(it);
- }
- long
- PORTCLOSEDIR(void *it)
- {
- return closedir(it);
- }
- int
- PORTPRINT(int c)
- {
- return write(1, &c, 1);
- }
-
- #if 0
- /*
- THIS CODE IS FOR SAMPLE PURPOSES ONLY -- THE REAL CODE IS IN THE LIBRARY
- PROGRAMMERS WHO WISH TO CREATE CUSTOM COMPARISON ROUTINES CAN USE THESE
- FUNCTIONS AS MODELS.
- */
- /*
- default_keycmp - system key comparison
-
- Return: LESS if keya < keyb
- EQUAL if keya == keyb
- GREATER if keya > keyb
- */
- static __inline__ int
- mymemcmp(unsigned char *a, unsigned char *b, int len)
- {
- int result = 0;
- do {
- if((result = ((int)*a++) - ((int)*b++)))
- return result;
- } while(--len);
- return result;
- }
- int
- default_keycmp (void *keya, int lena, void *keyb, int lenb)
- {
- int result;
-
- if (lena == 0)
- return ( (lenb == 0) ? EQUAL : LESS );
- else if (lenb == 0)
- return (GREATER);
-
-
- result = mymemcmp (keya, keyb, ((lena<lenb)?lena:lenb));
-
- if (result < 0)
- return LESS;
- if (result > 0)
- return GREATER;
-
- return ((lena == lenb) ? EQUAL : ((lena < lenb) ? LESS : GREATER));
-
- }
- /*
- default_itemcmp - system item comparison
-
- Return: LESS-1 if itema < itemb
- EQUAL+1 if itema == itemb
- GREATER+1 if itema > itemb
- */
-
- int
- default_itemcmp (Item *a, Item *b)
- {
- return ( (a->item == b->item) ?
- EQUAL+1 : ((a->item < b->item) ? LESS-1 : GREATER+1) );
- }
-
- #endif
-