home *** CD-ROM | disk | FTP | other *** search
/ APDL Public Domain 1 / APDL_PD1A.iso / program / virtual / VSI_C / c / VSIclib next >
Encoding:
Text File  |  1992-10-07  |  10.6 KB  |  578 lines

  1. /* > VSIclib */
  2.  
  3. /* C library intercepts for high store use */
  4.  
  5. /*******************************************************
  6.  *  Need to put in any C routines that have a different
  7.  *  action when called from high area.
  8.  *
  9.  *  The alias file for vsilink should include:-
  10.  *    remove   VSI_remove
  11.  *    rename   VSI_rename
  12.  *    fopen    VSI_fopen
  13.  *    freopen  VSI_freopen
  14.  *    setbuf   VSI_setbuf
  15.  *    setvbuf  VSI_setvbuf
  16.  *    fread    VSI_fread
  17.  *    fwrite   VSI_fwrite
  18.  *    calloc   VSI_calloc
  19.  *    free     VSI_free
  20.  *    malloc   VSI_malloc
  21.  *    realloc  VSI_realloc
  22.  *    getenv   VSI_getenv
  23.  *    system   VSI_system
  24.  *
  25.  *  The following can be included to give access to the
  26.  *  low store versions when executing in high store. Its
  27.  *  better to have one's one routines in low store for any
  28.  *  access to such facilities.
  29.  *    low_calloc calloc
  30.  *    low_free free
  31.  *    low_malloc malloc
  32.  *    low_realloc realloc
  33.  *******************************************************/
  34.  
  35. /*#define TRACE*/
  36.  
  37. #include <setjmp.h>
  38. #include <signal.h>
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #include <string.h>
  42. #include <kernel.h>
  43. #include <swis.h>
  44. #include "VSIman.h"
  45.  
  46.  
  47. typedef unsigned char bool;
  48.  
  49. #define FALSE 0
  50. #define TRUE 1
  51.  
  52. #define SMALL_MAX 255
  53.  
  54. extern void *VSI_ZI_Base;
  55. extern void *VSI_ZI_Limit;
  56.  
  57. /* stdio.h intercepts */
  58.  
  59. typedef char filename_t[256];
  60.  
  61.  
  62. /*
  63.  *  remove
  64.  */
  65.  
  66. int VSI_remove(const char *filename)
  67. {
  68.     filename_t lname;
  69.  
  70.     strcpy(lname, filename);
  71.     return remove(lname);
  72. }
  73.  
  74.  
  75. /*
  76.  *  rename
  77.  */
  78.  
  79. int VSI_rename(const char *old, const char *new)
  80. {
  81.     filename_t lold, lnew;
  82.  
  83.     strcpy(lold, old);
  84.     strcpy(lnew, new);
  85.  
  86.     return rename(lold, lnew);
  87. }
  88.  
  89.  
  90. /*
  91.  *  fopen
  92.  */
  93.  
  94. FILE *VSI_fopen(const char *filename, const char *mode)
  95. {
  96.     filename_t lname;
  97.  
  98.     strcpy(lname, filename);
  99.  
  100.     return fopen(lname, mode);
  101. }
  102.  
  103.  
  104. /*
  105.  *  freopen
  106.  */
  107.  
  108. FILE *VSI_freopen(const char *filename, const char *mode,
  109.                      FILE *stream)
  110. {
  111.     filename_t lname;
  112.  
  113.     strcpy(lname, filename);
  114.  
  115.     return freopen(lname, mode, stream);
  116. }
  117.  
  118.  
  119. /*
  120.  *  setbuf
  121.  */
  122.  
  123. void VSI_setbuf(FILE *stream, char *buf)
  124. {
  125.     if ((unsigned) buf < VSI_Space || (unsigned) buf >= VSI_Top)
  126.         setbuf(stream, buf);
  127.     else
  128.         setvbuf(stream, NULL, _IOFBF, BUFSIZ);
  129. }
  130.  
  131.  
  132. /*
  133.  *  setvbuf
  134.  */
  135.  
  136. int VSI_setvbuf(FILE *stream, char *buf, int mode, size_t size)
  137. {
  138.     if ((unsigned) buf < VSI_Space || (unsigned) buf >= VSI_Top)
  139.         return setvbuf(stream, buf, mode, size);
  140.     else
  141.         return setvbuf(stream, NULL, mode, size);
  142. }
  143.  
  144.  
  145. /* fread and fwrite may invoke a direct call to OS_GBPB,
  146.  * I'm not certain if they do at the moment.
  147.  */
  148.  
  149.  
  150. /*  fread - when called from high area shuld check whether
  151.  *  area is in high space and if so do a page at a time.
  152.  */ 
  153.  
  154. size_t VSI_fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
  155. {
  156.     size_t rem, len;
  157.     unsigned adr, top;
  158.  
  159. #ifdef TRACE
  160.     printf("VSI_fread %p %d %d\n", ptr, size, nmemb);
  161. #endif
  162.  
  163.     if ((unsigned) ptr < VSI_Space || (unsigned) ptr >= VSI_Top)
  164.         return fread(ptr, size, nmemb, stream);
  165.  
  166.     rem = size * nmemb;
  167.  
  168.     if (rem == 0)
  169.         return fread(ptr, size, nmemb, stream);
  170.  
  171.     adr = (unsigned) ptr;
  172.     top = adr + (unsigned) rem - 1;
  173.     len = 0;
  174.  
  175.     while (((adr ^ top) >> VSI_Page_Ln) != 0)
  176.     {
  177.         size_t want, got;
  178.  
  179.         want = ((adr + VSI_PageSize) & ~(VSI_PageSize - 1)) - adr;
  180.  
  181. #ifdef TRACE
  182.         printf("CALL fread %x %d %d\n", adr, 1, want);
  183. #endif
  184.  
  185.         /* Make certain area is writable */
  186.  
  187.         VSI_ENSURE_WRITE(adr);
  188.  
  189.         got = fread((void *) adr, 1, want, stream);
  190.         len += got;
  191.         if (want != got)
  192.             return len;
  193.         adr += got;
  194.     }
  195.  
  196. #ifdef TRACE
  197.     printf("CALL fread %x %d %d\n", adr, 1, top - adr + 1);
  198. #endif
  199.  
  200.     /* Make certain area is writable */
  201.  
  202.     VSI_ENSURE_WRITE(adr);
  203.  
  204.     len += fread((void *) adr, 1, top - adr + 1, stream);
  205.  
  206.     VSI_ENSURE_OFF();
  207.     VSI_Locked = NULL;
  208.  
  209. #ifdef TRACE
  210.     printf("End VSI_fread %d\n", len / size);
  211. #endif
  212.  
  213.     return len / size;
  214. }
  215.  
  216.  
  217. /*  fwrite - when called from high area shuld check whether
  218.  *  area is in high space and if so do a page at a time.
  219.  */
  220.  
  221. size_t VSI_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
  222. {
  223.     size_t rem, len;
  224.     unsigned adr, top;
  225.  
  226. #ifdef TRACE
  227.     printf("VSI_fwrite %p %d %d\n", ptr, size, nmemb);
  228. #endif
  229.  
  230.     if ((unsigned)ptr < VSI_Space || (unsigned)ptr >= VSI_Top)
  231.         return fwrite(ptr, size, nmemb, stream);
  232.  
  233.     rem = size * nmemb;
  234.  
  235.     if (rem == 0)
  236.         return fwrite(ptr, size, nmemb, stream);
  237.  
  238.     adr = (unsigned) ptr;
  239.     top = adr + (unsigned) rem - 1;
  240.     len = 0;
  241.  
  242.     while (((adr ^ top) >> VSI_Page_Ln) != 0)
  243.     {
  244.         size_t want, got;
  245.  
  246.         want = ((adr + VSI_PageSize) & ~(VSI_PageSize - 1)) - adr;
  247.  
  248. #ifdef TRACE
  249.         printf("CALL fwrite %x %d %d\n", adr, 1, want);
  250. #endif
  251.  
  252.         /* Make certain area is readable */
  253.  
  254.         VSI_ENSURE_READ(adr);
  255.  
  256.         got = fwrite((void *) adr, 1, want, stream);
  257.         len += got;
  258.         if (want != got)
  259.             return len;
  260.         adr += got;
  261.     }
  262.  
  263. #ifdef TRACE
  264.     printf("CALL fwrite %x %d %d\n", adr, 1, top - adr + 1);
  265. #endif
  266.  
  267.     /* Make certain area is readable */
  268.  
  269.     VSI_ENSURE_READ(adr);
  270.  
  271.     len += fwrite((void *) adr, 1, top - adr + 1, stream);
  272.  
  273.     VSI_ENSURE_OFF();
  274.  
  275. #ifdef TRACE
  276.     printf("End VSI_fwrite %d\n", len / size);
  277. #endif
  278.  
  279.     return len / size;
  280. }
  281.  
  282.  
  283. /*  Storage allocation in the high area
  284.  *  Taken from Kernighan and Ritchie
  285.  *
  286.  *  free and realloc revert to standard if a high area
  287.  *  or NULL not specified.
  288.  */
  289.  
  290. typedef long Align;   /* for alignment to long boundary */
  291.  
  292. union header {        /* block header: */
  293.     struct {
  294.         union header *ptr;    /* next block if on free list. */
  295.         unsigned size;        /* size of this block */
  296.     } s;
  297.     Align x;          /* force alignment of blocks */
  298. };
  299.  
  300. typedef union header Header;
  301.  
  302. static Header base;   /* empty list to get started */
  303. static Header *freep = NULL;  /* start of free list */
  304.  
  305.  
  306. /*  free - when called from high area will free space
  307.  *  if it was allocated from high space else will call
  308.  *  the low version of free.
  309.  */
  310.  
  311. void VSI_free(void *ptr)
  312. {
  313.     Header *bp, *p;
  314.  
  315. #ifdef TRACE
  316.     printf("VSI_free %p\n", ptr);
  317. #endif
  318.  
  319.     /* If original allocated by standard malloc then */
  320.     /* have to do standard free.                     */
  321.     /* Standard free deals with NULL ok.             */
  322.  
  323.     if ((unsigned) ptr < VSI_Space || (unsigned) ptr >= VSI_Top)
  324.     {
  325.         free(ptr);
  326.         return;
  327.     }
  328.  
  329.     /* free block in high space */
  330.  
  331.     bp = (Header *)ptr - 1;    /* point to block header */
  332.  
  333.     for (p = freep; !(bp > p && bp < p->s.ptr); p = p->s.ptr)
  334.     {
  335.         if (p >= p->s.ptr && (bp > p || bp < p->s.ptr))
  336.         {
  337.             /* freed block at start or end of area */
  338.  
  339.             break;
  340.         }
  341.     }
  342.  
  343.     if (bp + bp->s.size == p->s.ptr)
  344.     {
  345.         /* join to upper nbr */
  346.  
  347.         bp->s.size += p->s.ptr->s.size;
  348.         bp->s.ptr = p->s.ptr->s.ptr;
  349.     }
  350.     else
  351.     {
  352.         bp->s.ptr = p->s.ptr;
  353.     }
  354.  
  355.     if (p + p->s.size == bp)
  356.     {
  357.         /* join to lower nbr */
  358.  
  359.         p->s.size += bp->s.size;
  360.         p->s.ptr = bp->s.ptr;
  361.     }
  362.     else
  363.     {
  364.         p->s.ptr = bp;
  365.     }
  366.  
  367. #ifdef TRACE
  368.     printf("VSI_free ends\n");
  369. #endif
  370.  
  371.     freep = p;
  372. }
  373.  
  374.  
  375. /*
  376.  *  morecore - almost a dummy
  377.  */
  378.  
  379. static bool morecore_done = FALSE;
  380.  
  381. static Header *morecore(unsigned nu)
  382. {
  383.     unsigned adr, len;
  384.     Header *up;
  385.  
  386. #ifdef TRACE
  387.     printf("morecore\n");
  388. #endif
  389.  
  390.     if (morecore_done)
  391.         return NULL;
  392.     morecore_done = FALSE;
  393.  
  394.     adr = ((unsigned) VSI_ZI_Limit + 3) & -4;
  395.     len = VSI_Top - adr;
  396.  
  397.     up = (Header *) adr;
  398.     up->s.size = len / sizeof(Header);
  399.  
  400.     VSI_free((void *)(up+1));
  401.  
  402. #ifdef TRACE
  403.     printf("morecore %p %d %d\n", up, up->s.size, sizeof(Header));
  404. #endif
  405.  
  406.     return freep;
  407. }
  408.  
  409.  
  410. /*
  411.  *  malloc - when called from high area will allocate
  412.  *  pageable space.
  413.  */
  414.  
  415. void *VSI_malloc(size_t size)
  416. {
  417.     Header *p, *prevp;
  418.     unsigned nunits;
  419.  
  420. #ifdef TRACE
  421.     printf("VSI_malloc %d\n", size);
  422. #endif
  423.  
  424.     nunits = (size+sizeof(Header)-1)/sizeof(Header) + 1;
  425.  
  426.     if ((prevp = freep) == NULL)
  427.     {
  428.         /* no free list yet */
  429.  
  430.         base.s.ptr = freep = prevp = &base;
  431.         base.s.size = 0;
  432.     }
  433.  
  434.     for (p = prevp->s.ptr; ; prevp = p, p = p->s.ptr)
  435.     {
  436.         if (p->s.size >= nunits)
  437.         {
  438.             /* big enough */
  439.  
  440.             if (p->s.size == nunits)
  441.             {
  442.                 /* exactly */
  443.  
  444.                 prevp->s.ptr = p->s.ptr;
  445.             }
  446.             else
  447.             {
  448.                 /* allocate till end */
  449.  
  450.                 p->s.size -= nunits;
  451.                 p += p->s.size;
  452.  
  453.                 p->s.size = nunits;
  454.             }
  455.  
  456.             freep = prevp;
  457.  
  458. #ifdef TRACE
  459.             printf("VSI_malloc returns %p\n", (void *)(p+1));
  460. #endif
  461.  
  462.             return (void *)(p+1);
  463.         }
  464.  
  465.         if (p == freep)    /* wrapped around free list */
  466.         {
  467.             if ((p = morecore(nunits)) == NULL)
  468.             {
  469. #ifdef TRACE
  470.             printf("VSI_malloc returns NULL\n");
  471. #endif
  472.                 return NULL;    /* none left */
  473.             }
  474.         }
  475.     }
  476. }
  477.  
  478.  
  479. /*
  480.  *  calloc - when called from high area will allocate
  481.  *  pageable space.
  482.  */
  483.  
  484. extern void *VSI_calloc(size_t nmemb, size_t size)
  485. {
  486.     size_t len = nmemb * size;
  487.     void *ptr = VSI_malloc(len);
  488.  
  489. #ifdef TRACE
  490.     printf("VSI_calloc %ptr nmemb %d size %d\n", ptr, nmemb, size);
  491. #endif
  492.  
  493.     return memset(ptr, 0, len);
  494. }
  495.  
  496.  
  497. /*
  498.  *  realloc - when called from high area will allocate
  499.  *  pageable space.
  500.  */
  501.  
  502. void *VSI_realloc(void *ptr, size_t size)
  503. {
  504.     void *newptr;
  505.     unsigned len;
  506.  
  507. #ifdef TRACE
  508.     printf("VSI_realloc %p size %d\n", ptr, size);
  509. #endif
  510.  
  511.     if (ptr == NULL)
  512.         return VSI_malloc(size);
  513.  
  514.     /* If original allocated by standard malloc then */
  515.     /* have to do realloc using standard realloc.    */
  516.     /* No idea how long original is.                 */
  517.  
  518.     if ((unsigned) ptr < VSI_Space || (unsigned) ptr >= VSI_Top)
  519.         return realloc(ptr, size); 
  520.  
  521.     /* Very simple method, */
  522.     /* - just get new space and copy over. */
  523.  
  524.     len = ((Header *)ptr)[-1].s.size;
  525.     len = (len > size ? size : len);
  526.  
  527.     newptr = VSI_malloc(size);
  528.  
  529.     memcpy(newptr, ptr, len);
  530.  
  531.     VSI_free(ptr);
  532.  
  533.     return newptr;
  534. }
  535.  
  536.  
  537. /*
  538.  *  getenv
  539.  */
  540.  
  541. extern char *VSI_getenv(const char *name)
  542. {
  543.     char lname[256];
  544.  
  545. #ifdef TRACE
  546.     printf("VSI_getenv %s\n", name);
  547. #endif
  548.  
  549.     strcpy(lname, name);
  550.  
  551.     return getenv(lname);
  552. }
  553.  
  554.  
  555. /*
  556.  * system
  557.  */
  558.  
  559. extern int  VSI_system(const char *string)
  560. {
  561.     char lstring[256];
  562.     int resp;
  563.  
  564. #ifdef TRACE
  565.     printf("VSI_system %s\n", string);
  566. #endif
  567.  
  568.     strcpy(lstring, string);
  569.  
  570.     VSI_Save();
  571.  
  572.     resp = system(lstring);
  573.  
  574.     VSI_Restore();
  575.  
  576.     return resp;
  577. }
  578.