home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR24 / CFF51B.ZIP / CFPORT.DJC < prev    next >
Text File  |  1993-10-23  |  14KB  |  657 lines

  1. /* CFPORT.C */
  2. /* PORTABILITY FOR CFF -- MODIFY TO SUIT THE COMPILER/OS IN USE */
  3.  
  4. #include <sys/types.h>
  5. #include <sys/stat.h>
  6. #include <stdlib.h>
  7. #include <fcntl.h>
  8. #include <direct.h>
  9. #include <errno.h>
  10. #include <io.h>
  11. #include <stdio.h>
  12. #include <time.h>
  13. #include <dirent.h>
  14. #include "../cff.h"
  15.  
  16. extern void *mymemmove(void *, void *, long);
  17.  
  18. #define PCDOS 1
  19.  
  20. #define NIBBLE 128
  21. #define CHUNK_SIZE 8192
  22.  
  23. #ifndef HEAPSTART
  24. #define HEAPSTART 0x500000
  25. #endif
  26.  
  27. unsigned long heapcreep;
  28. void *heapstart = (void *)HEAPSTART;
  29.  
  30.  
  31. extern volatile int errno;
  32.  
  33. static STOR BIGZERO;
  34.  
  35.  
  36. /* DUMMY ROUTINES TO PREVENT LINKING UNWANTED MALLOC LIKE STUFF */
  37. int _heapchk(void)
  38. {
  39.     return 0;
  40. }
  41. int _heapset(unsigned a)
  42. {
  43.     return 0;
  44. }
  45. void *_expand (void *mem, size_t new_size)
  46. {
  47.     return NULL;
  48. }
  49. size_t _msize (const void *mem)
  50. {
  51.     return mallocsize(mem);
  52. }
  53. unsigned malloc_usable_size (void *mem)
  54. {
  55.     return mallocsize((const void *)mem);
  56. }
  57.  
  58. /* ---------------- END OF MALLOC DUMMYS ------------- */
  59.  
  60. static __inline__ unsigned long
  61. round_up(long size, long amt)
  62. {
  63.     return (size&(amt-1)) ? size+(amt-(size&(amt-1))) : size;
  64. }
  65.  
  66. static int testflags = 0;
  67. void
  68. cfport_settestflags(int flags)
  69. {
  70.     testflags |= flags;
  71. }
  72. void
  73. cfport_clrtestflags(int flags)
  74. {
  75.     testflags &= ~flags;
  76. }
  77.  
  78. static void
  79. fix_statbuf(struct stat *stat, CFSTAT *sbuf)
  80. {
  81.     sbuf->st_atime = stat->st_atime;
  82.     sbuf->st_mtime = stat->st_mtime;
  83.     sbuf->st_ctime = stat->st_ctime;
  84.     sbuf->st_size = stat->st_size;
  85.     sbuf->st_alloc = stat->st_size;
  86.     sbuf->st_filesize = stat->st_size;
  87.     sbuf->st_filealloc = stat->st_size;
  88.     sbuf->st_blksize = stat->st_blksize;
  89.     sbuf->st_dev = stat->st_dev;
  90.     sbuf->st_ino = stat->st_ino;
  91.     sbuf->st_nlink = stat->st_nlink;
  92.     sbuf->st_uid = stat->st_uid;
  93.     sbuf->st_gid = stat->st_gid;    
  94.     sbuf->st_rdev = stat->st_rdev;
  95.     sbuf->st_mode = stat->st_mode;
  96. }
  97. void *
  98. PORTSBRK(unsigned long amt)
  99. {
  100.     return ((void *)sbrk(amt));
  101. }
  102. void
  103. PORTHEAPSTART(void)
  104. {
  105. void *curstart = sbrk(0);
  106. char *newstart = NULL;
  107.     if(curstart > heapstart)
  108.     {
  109.         cfprintf("CFFINIT: The heap safety zone was exceeded by %d bytes.\n",
  110.             -((long)(heapstart - curstart)));
  111.         exit(-1);
  112.     }
  113.     heapcreep = (unsigned long)(heapstart - curstart);
  114.     if((newstart = (void *)sbrk(heapcreep)) == (void *)-1) {
  115.         cfprintf("Failed to set heap: zone=%lu HEAPSTART=%p curstart=%p.\n",
  116.         heapcreep, heapstart, curstart);
  117.         exit(-2);
  118.     }
  119.     else if(heapcreep && newstart+heapcreep != heapstart) {
  120.         cfprintf("Heap was not set properly: desired=%p result=%p zone=%lu.\n",
  121.         heapstart, newstart, heapcreep);
  122.         exit(-3);
  123.     }
  124. }
  125. int
  126. PORTSTAT(void *path, CFSTAT *sbuf)
  127. {
  128. struct stat _stat;
  129. int result = stat(path, &_stat);
  130.     if(result == 0)
  131.         fix_statbuf(&_stat, sbuf);
  132.     return result;
  133. }
  134. void
  135. PORTFSTAT(int handle, CFSTAT *sbuf)
  136. {
  137. struct stat stat;
  138.  
  139.     fstat(handle, &stat);
  140.     fix_statbuf(&stat, sbuf);    
  141. }
  142.  
  143. long
  144. PORTREAD(long handle, void *mem_addr, STOR dsk_addr, long amount)
  145. {
  146.     lseek(handle, dsk_addr.a0, SEEK_SET);  
  147.     return read(handle, mem_addr, amount);
  148. }
  149. long
  150. PORTWRITE(long handle, void *mem_addr, STOR dsk_addr, long amount)
  151. {
  152.     lseek(handle, dsk_addr.a0, SEEK_SET);  
  153.     return write(handle, mem_addr, amount);
  154. }
  155. void
  156. PORTSEEK(long handle, STOR spot, int mode, STOR *loc)
  157. {
  158. STOR ret;
  159.     switch(mode)
  160.     {
  161.         case S_END:
  162.             mode = SEEK_END;
  163.             break;
  164.         case S_CUR:
  165.             mode = SEEK_CUR;
  166.             break;
  167.         case S_SET:
  168.             mode = SEEK_SET;
  169.             break;
  170.         default:
  171.             mode = -1;
  172.     }
  173.     ret.a4.s1 = 0;
  174.     ret.a4.s0 = lseek((int)handle, spot.a0, mode);
  175.     if(loc)
  176.         *loc = ret;
  177. }
  178. long
  179. PORTOPEN(void *path, int mode)
  180. {
  181. int omode = O_BINARY;
  182.  
  183.     if((mode & F_RDWR) == F_RDONLY)
  184.         omode |= O_RDONLY;
  185.     else if((mode & F_RDWR) == F_WRONLY)
  186.         omode |= O_WRONLY;
  187.     else if((mode & F_RDWR) == F_RDWR)
  188.         omode |= O_RDWR;
  189.     if(mode & F_TRUNC)
  190.         omode |= O_TRUNC;
  191.     if(mode & F_EXCL)
  192.         omode |= O_EXCL;
  193.     if(mode & F_APPEND)
  194.         omode |= O_APPEND;
  195.  
  196.     return open(path,omode);
  197. }
  198. long
  199. PORTCLOSE(long handle)
  200. {
  201.     return close((int)handle);
  202. }
  203. long
  204. PORTCREATE(void *path, int mode)
  205. {
  206.     return creat(path, S_IREAD|S_IWRITE);
  207. }
  208. long
  209. PORTUNLINK(void *path)
  210. {
  211.     return unlink(path);
  212. }
  213. #if PCDOS == 1
  214. static void
  215. dos_truncate(short handle, long amount)
  216. {
  217. #include <dos.h>
  218. union REGS r;
  219.  
  220.     r.h.al = 0;        /* SEEK_SET */
  221.     r.h.ah = 0x42;    /* seek */
  222.     r.x.bx = handle;
  223.     r.x.dx = (short)amount;
  224.     r.x.cx = (short)(amount>>16);
  225.     intdos(&r,&r);
  226.  
  227.     r.h.ah = 0x40;    /* write */
  228.     r.x.bx = handle;
  229.     r.x.cx = 0;        /* amount == 0 */
  230.     intdos(&r,&r);
  231.     
  232.     r.h.ah = 0x3e;    /* close */
  233.     r.x.bx = handle;
  234.     intdos(&r,&r);
  235. }
  236. #endif
  237. long
  238. PORTTRUNCATE(long handle, char *path, STOR amount)
  239. {
  240. #if PCDOS == 1
  241.     /* DJCC has a bugged ftruncate */
  242.     dos_truncate((short)handle, amount.a0);
  243.     return PORTOPEN(path, F_RDWR);
  244. #else
  245.     ftruncate((int)handle, amount.a0);
  246.     return handle;
  247. #endif
  248. }
  249. void
  250. PORTCLOSETRUNC(long handle, STOR amount)
  251. {
  252. #if PCDOS == 1
  253.     /* DJCC has a bugged ftruncate */
  254.     dos_truncate((short)handle, amount.a0);
  255. #else
  256.     ftruncate((int)handle, amount.a0);
  257.     close((int)handle);
  258. #endif
  259. }
  260. void
  261. PORTFLUSH(long handle)
  262. {
  263. #if 0
  264.     if(handle < 0)
  265.          sync();
  266.     else 
  267. #endif
  268.         fsync((int)handle);
  269. }
  270.  
  271. char *
  272. PORTGETCWD(void *buf, int maxlen)
  273. {
  274. char *result;
  275.  
  276.     result = getcwd((char *)buf, maxlen);
  277.     ((char *)buf)[maxlen] = 0;
  278.     if(result)
  279.     {
  280.         while(*((char *)buf))
  281.         {
  282.             if(*((char *)buf) == '\\') *((char *)buf) = '/';
  283.             ++((char *)buf);
  284.         }
  285.      }
  286.     return result;
  287. }
  288.  
  289. long
  290. PORTCHDIR(void *path)
  291. {
  292.     return chdir(path);
  293. }
  294. unsigned long
  295. PORTTIME(void)
  296. {
  297.     return time(NULL);
  298. }
  299. unsigned long
  300. PORTCLOCK(void)
  301. {
  302.     return clock();
  303. }
  304. volatile void
  305. PORTABORT(void)
  306. {
  307. extern volatile void abort();
  308.     abort();
  309. }
  310.  
  311. /* THE BASIC OS DRIVERS */
  312.  
  313. /* Primary Memory driver */
  314. long
  315. pmem_driver(int func, int handle, void *mem_addr, STOR dsk_addr, long amount)
  316. {
  317.     switch(func)
  318.     {
  319.         case    S_GETSPACE:
  320.         {
  321.         unsigned long min, nib, current;
  322.  
  323.             amount = round_up(amount, CHUNK_SIZE);
  324.             min = round_up(amount / 4, CHUNK_SIZE);
  325.             nib = round_up(amount / 16, CHUNK_SIZE);
  326.             current = amount;
  327.             ((STOR *)mem_addr)->a2.size = 0;
  328.             ((STOR *)mem_addr)->a2.type = STO_CHUNK;
  329.  
  330.             while(current >= min) {
  331.               if((((STOR *)mem_addr)->a1 = PORTSBRK(current)) != (void *)-1) {
  332.                 if(((STOR *)mem_addr)->a0 & (NIBBLE-1))
  333.                 {/* Normally the system uses NIBBLE bytes as the alignment */
  334.                   ((STOR *)mem_addr)->a0 = 
  335.                               round_up(((STOR *)mem_addr)->a0, NIBBLE);
  336.                   current -= NIBBLE;
  337.                 }
  338.                 ((STOR *)mem_addr)->a2.size = current;
  339.                 return 0;
  340.               }
  341.               current -= nib;
  342.             }
  343.             return 1;
  344.         }
  345.         case    S_GIVESPACE:
  346.             return 1;
  347.         default:
  348.             return 1;
  349.     }
  350.     return 0;
  351. }
  352.  
  353. /* Secondary Memory driver */
  354. long
  355. smem_driver(int func, int handle, void *mem_addr, STOR dsk_addr, long amount)
  356. {
  357.     if(!(testflags & 1))
  358.     {/* 
  359.         IF SECONDARY MEMORY REALLY EXISTS, THEN PUT A REAL DRIVER HERE.
  360.         The system adapts to a 0 return from S_GETSPACE by mapping 
  361.         secondary memory to primary memory when cfinit is called.
  362.         S_OPEN is never called.
  363.      */
  364.         switch (func)
  365.         {
  366.             case S_GETSPACE:
  367.                 *((long *)mem_addr) = 0;
  368.                 break;
  369.         }
  370.         return -1;
  371.     } /* END: Real driver */
  372.     else {
  373.     /* THIS CODE IS JUST FOR TESTING PURPOSES, IT USES A LOCAL MEMORY BUFFER */
  374.  
  375. #define SMEMMAX (4096*1024)
  376. static char *sbuf = NULL;
  377. static long smemalloc = 0;
  378.  
  379.         if(sbuf == NULL)
  380.             if((sbuf = PORTSBRK(SMEMMAX)) == (void *)-1)
  381.                 return -1;
  382.  
  383.         switch(func)
  384.         {
  385.             case    S_CLOSE:
  386.                 return 0;        /* a real driver would do something */            
  387.             case    S_READBLK:
  388.             case    S_WRITEBLK:
  389.             {
  390.             char *smemaddr = sbuf + dsk_addr.a0;
  391.             long xfer = amount;
  392.                 if(dsk_addr.a0 + amount > smemalloc)
  393.                     xfer = smemalloc - dsk_addr.a0;
  394.                 if(xfer < 0) {
  395.                     return -1;
  396.                 }
  397.                 if(func == S_READBLK)
  398.                      mymemmove(mem_addr, smemaddr, xfer);
  399.                 else mymemmove(smemaddr, mem_addr, xfer);
  400.                 return xfer;
  401.             }
  402.             case    S_GETSPACE:
  403.                 amount = round_up(amount, CHUNK_SIZE);
  404.                 ((STOR *)mem_addr)->a0 = smemalloc;
  405.                 ((STOR *)mem_addr)->a2.size = 0;
  406.                 ((STOR *)mem_addr)->a2.type = STO_CHUNK;
  407.                 if(amount + smemalloc < SMEMMAX) {
  408.                     ((STOR *)mem_addr)->a2.size = amount;
  409.                     smemalloc += amount;
  410.                     return 0;
  411.                 } else {/* Not enough space available, return error + avail */
  412.                     ((STOR *)mem_addr)->a2.size = 
  413.                                     (SMEMMAX - smemalloc) & ~CHUNK_SIZE;
  414.                     return 1;
  415.                 }
  416.             case    S_GIVESPACE:
  417. #if 0
  418. cfprintf("SMEM: GIVESPACE at loc=%lx size=%lu curbase=%lx\n",
  419. ((STOR *)mem_addr)->a0, ((STOR *)mem_addr)->a2.size, smemalloc);
  420. #endif
  421.                 if(((STOR *)mem_addr)->a0 == 
  422.                         smemalloc - ((STOR *)mem_addr)->a2.size)
  423.                 {/* Accept returns if they are at the end */
  424.                     smemalloc -= ((STOR *)mem_addr)->a2.size;
  425. #if 0
  426. cfprintf("SMEM: Truncate to %lu bytes\n", smemalloc);
  427. #endif
  428.                     return 0;
  429.                 }
  430.                 break;
  431.             default:
  432.                 break;
  433.         }
  434.         return 1;
  435.     }/* END: test driver */
  436. }
  437.  
  438. /* Internal file driver */
  439. long
  440. cfile_driver(int func, int handle, void *mem_addr, STOR dsk_addr, long amount)
  441. {
  442. long result = 0;
  443.  
  444.     switch(func)
  445.     {
  446.         case S_READBLK:
  447.             result = PORTREAD(handle, mem_addr, dsk_addr, amount);
  448.             break;
  449.         case S_WRITEBLK:
  450.             result = PORTWRITE(handle, mem_addr, dsk_addr, amount);
  451.             break;
  452.         case    S_GETSPACE:
  453.         {
  454.         u_long result;
  455.         STOR base;
  456.         STOR end;
  457.             PORTSEEK(handle, BIGZERO, S_END, &base);
  458.             amount = round_up(amount, CHUNK_SIZE);
  459.             end.a4.s0 = base.a0 + amount-1;
  460.             end.a4.s1 = 0;
  461.             PORTWRITE(handle, "0", end, 1);
  462.             PORTSEEK(handle, BIGZERO, S_END, &end);
  463.             result = end.a0 - base.a0;
  464.             ((STOR *)mem_addr)->a0 = base.a0;
  465.             ((STOR *)mem_addr)->a2.size = result;
  466.             ((STOR *)mem_addr)->a2.type = STO_CHUNK;
  467.             return (result == amount) ? 0:1;        
  468.         }
  469.         case    S_GIVESPACE:
  470.         {
  471.         STOR base;
  472.             PORTSEEK(handle, BIGZERO, S_END, &base);
  473.             if((((STOR *)mem_addr)->a0 + ((STOR *)mem_addr)->a2.size) == base.a0)
  474.             {/* OK to return space if at end */
  475. #if 0
  476.             long result;
  477.                 base.a0 -= ((STOR *)mem_addr)->a2.size;
  478.                 result = PORTTRUNCATE(handle, base);
  479. #endif
  480.                 return 0;
  481.             }
  482.             else return 1;
  483.         }
  484.         case    S_OPEN:
  485.             result = PORTOPEN(mem_addr, handle);
  486.             break;
  487.         case    S_CLOSE:
  488.             result = PORTCLOSE(handle);
  489.             break;
  490.         case    S_CREATE:
  491.             result = PORTCREATE(mem_addr, handle);
  492.             break;
  493.         case    S_UNLINK:
  494.             result = PORTUNLINK(mem_addr);
  495.             break;
  496.         case    S_SEEK:
  497.             PORTSEEK(handle, dsk_addr, amount, mem_addr);
  498.             break;
  499.         case    S_FLUSH:
  500.             PORTFLUSH(handle);
  501.             break;
  502.         case    S_CLOSETRUNC: /* truncate and close, (PCDOS needs this) */
  503.             PORTCLOSETRUNC(handle, dsk_addr);
  504.             break;
  505.         default:
  506.             return 1;
  507.     }
  508.     return result;
  509. }
  510. /* External file driver */
  511. long
  512. xfile_driver(int func, int handle, void *mem_addr, STOR dsk_addr, long amount)
  513. {
  514. long result = 0;
  515.  
  516.     switch(func)
  517.     {
  518.         case    S_GETSPACE:
  519.             ((STOR *)mem_addr)->a2.size = 0;
  520.         case    S_GIVESPACE:
  521.             return 1;
  522.         case    S_OPEN:
  523.             result = PORTOPEN(mem_addr, handle);
  524.             break;
  525.         case    S_CLOSE:
  526.             result = PORTCLOSE(handle);
  527.             break;
  528.         case    S_UNLINK:
  529.             result = PORTUNLINK(mem_addr);
  530.             break;
  531.         case    S_CREATE:
  532.             result = PORTCREATE(mem_addr,handle);
  533.             break;
  534.         case    S_READBLK:
  535.             result = PORTREAD(handle, mem_addr, dsk_addr, amount);
  536.             break;
  537.         case    S_WRITEBLK:
  538.             result = PORTWRITE(handle, mem_addr, dsk_addr, amount);
  539.             break;
  540.         case    S_SEEK:
  541.             PORTSEEK(handle, dsk_addr, amount, mem_addr);
  542.             break;
  543.         case    S_FLUSH:
  544.             PORTFLUSH(handle);
  545.             break;
  546.         default:
  547.             return 1;
  548.     }
  549.     return result;
  550. }
  551. void *
  552. PORTOPENDIR(char *name)
  553. {
  554.     return opendir(name);
  555. }
  556. void *
  557. PORTREADDIR(void *it, CFDIRENT *d)
  558. {
  559. struct dirent *rd;
  560.     if((rd = readdir(it))) {
  561.         d->d_namlen = rd->d_namlen;
  562.         d->d_name = rd->d_name;
  563.         d->d_mode = M_EXTRNFILE;
  564.     }
  565.     return rd;
  566. }
  567. void
  568. PORTTELLDIR(void *it, STOR *loc)
  569. {
  570. STOR me;
  571.     me.item = 0;
  572.     me.a0 = telldir(it); 
  573.     if(loc)
  574.         *loc = me;
  575. }
  576. void
  577. PORTSEEKDIR(void *it, STOR *loc)
  578. {
  579.     seekdir(it, loc->a0);
  580. }
  581. void
  582. PORTREWINDDIR(void *it)
  583. {
  584.     rewinddir(it);
  585. }
  586. long
  587. PORTCLOSEDIR(void *it)
  588. {
  589.     return closedir(it);
  590. }
  591. int
  592. PORTPRINT(int c)
  593. {
  594.     return write(1, &c, 1);
  595. }
  596.  
  597. #if 0
  598. /* 
  599.     THIS CODE IS FOR SAMPLE PURPOSES ONLY -- THE REAL CODE IS IN THE LIBRARY
  600.     PROGRAMMERS WHO WISH TO CREATE CUSTOM COMPARISON ROUTINES CAN USE THESE
  601.     FUNCTIONS AS MODELS.
  602. */
  603. /*
  604.     default_keycmp - system key comparison
  605.  
  606.     Return:    LESS    if keya <  keyb
  607.             EQUAL    if keya == keyb
  608.             GREATER    if keya >  keyb
  609. */
  610. static __inline__ int
  611. mymemcmp(unsigned char *a, unsigned char *b, int len)
  612. {
  613. int result = 0;
  614.     do {
  615.         if((result = ((int)*a++) - ((int)*b++)))
  616.             return result;
  617.     } while(--len);
  618.     return result;
  619. }
  620. int
  621. default_keycmp (void *keya, int    lena, void *keyb, int lenb)
  622. {
  623. int    result;
  624.  
  625.     if (lena == 0)
  626.         return ( (lenb == 0) ? EQUAL : LESS );
  627.     else if (lenb == 0)
  628.         return (GREATER);
  629.  
  630.  
  631.     result = mymemcmp (keya, keyb, ((lena<lenb)?lena:lenb));
  632.  
  633.     if (result < 0)
  634.         return LESS;
  635.     if (result > 0)
  636.         return GREATER;
  637.  
  638.     return ((lena == lenb) ? EQUAL : ((lena < lenb) ? LESS : GREATER));
  639.  
  640. }
  641. /*
  642.     default_itemcmp - system item comparison
  643.  
  644.     Return:    LESS-1        if itema <  itemb
  645.             EQUAL+1        if itema == itemb
  646.             GREATER+1    if itema >  itemb
  647. */
  648.  
  649. int
  650. default_itemcmp (Item *a, Item *b)
  651. {
  652.     return ( (a->item == b->item) ? 
  653.                 EQUAL+1 : ((a->item < b->item) ? LESS-1 : GREATER+1) );
  654. }
  655.  
  656. #endif
  657.