home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 1 / ARM_CLUB_CD.iso / contents / apps / program / d / gstream / c / osstream < prev    next >
Encoding:
Text File  |  1993-05-08  |  7.9 KB  |  344 lines

  1. /*************************************************************
  2. *                                                            *
  3. *    Module: osstream.c (part of gstream package)            *
  4. *                                                            *
  5. *   Version: 0.02                                            *
  6. *                                                            *
  7. *    Author: Simon Proven                                    *
  8. *                                                            *
  9. *     Owner:  Simon Proven 1993                             *
  10. *                                                            *
  11. *   Purpose: To allow gstream to access RISC OS filesystems. *
  12. *                                                            *
  13. *      Uses: gstream, flex, werr, wimpt, os, stdlib          *
  14. *                                                            *
  15. *   History:                                                 *
  16. *            0.02: added atexit() function which closes all  *
  17. *                  open osstreams                            *
  18. *                                                            *
  19. * Conditions:                                                *
  20. *             You can produce and sell executable code from  *
  21. *             this module freely.  The source code may be    *
  22. *             distributed freely, but not for profit.        *
  23. *                                                            *
  24. *             If you like these modules alot, and use them   *
  25. *             in your own programs, feel free to thank me    *
  26. *             with cash - 10 or more will get you a disc    *
  27. *             with the latest versions and new stream types. *
  28. *                                                            *
  29. * Disclaimer:                                                *
  30. *             This software is supplied in good faith, but I *
  31. *             cannot accept liability for any loss incurred  *
  32. *             through the use or inability to use any part   *
  33. *             of this software.                              *
  34. *                                                            *
  35. * How to contact me:                                         *
  36. *                                                            *
  37. * email:                      snail mail:                    *
  38. * sproven@cs.strath.ac.uk     Simon Proven,                  *
  39. *                             Castle Cottage,                *
  40. *                             Portencross,                   *
  41. *                             West Kilbride,                 *
  42. *                             KA23 9QA                       *
  43. *                             SCOTLAND                       *
  44. *                                                            *
  45. * Tel. (+44) 294 829 721                                     *
  46. *                                                            *
  47. *************************************************************/
  48.  
  49. #include "gstream.h"
  50. #include "flex.h"
  51. #include "wimpt.h"
  52. #include "os.h"
  53. #include "werr.h"
  54. #include <stdlib.h>
  55.  
  56. #define FILES_OPEN_LIMIT (16)
  57.  
  58. #define FALSE 0
  59. #define TRUE 1
  60.  
  61. static int files_open[FILES_OPEN_LIMIT];
  62. static int registered_with_atexit=FALSE;
  63.  
  64. static void atexit_func(void)
  65. {
  66.     int        count;
  67.     os_regset    regs;
  68.     os_error    *err;
  69.  
  70.     for (count=0;count<FILES_OPEN_LIMIT;count++)
  71.     {
  72.         if (files_open[count])
  73.         {
  74.             regs.r[0]=0;
  75.             regs.r[1]=files_open[count];
  76.             err=os_find(®s);
  77.             files_open[count]=0;
  78.             if (err)
  79.                 wimpt_complain(err);
  80.         }
  81.     }
  82. }
  83.  
  84. static int register_atexit_func(void)
  85. {
  86.     if (!registered_with_atexit)
  87.     {
  88.         int count;
  89.         for (count=0;count<FILES_OPEN_LIMIT;count++)
  90.             files_open[count]=0;
  91.         if (atexit(atexit_func))
  92.             return FALSE;
  93.         registered_with_atexit=TRUE;
  94.         return TRUE;
  95.     }
  96.     else
  97.         return TRUE;
  98. }
  99.  
  100. static void register_file_opened(int filehandle)
  101. {
  102.     int count;
  103.  
  104.     if (register_atexit_func())
  105.     {
  106.         for (count=0;count<FILES_OPEN_LIMIT;count++)
  107.         {
  108.             if (!files_open[count])
  109.             {
  110.                 files_open[count]=filehandle;
  111.                 return;
  112.             }
  113.         }
  114.     }    
  115. }
  116.  
  117. static void register_file_closed(int filehandle)
  118. {
  119.     int count=0;
  120.  
  121.     if (registered_with_atexit)
  122.     {
  123.         for (count=0;count<FILES_OPEN_LIMIT;count++)
  124.         {
  125.             if (files_open[count]==filehandle)
  126.             {
  127.                 files_open[count]=0;
  128.                 return;
  129.             }
  130.         }
  131.     
  132.     }
  133. }
  134.  
  135. /* this function closes an OS_READ stream.  Internal use ONLY */
  136.  
  137. static int closeosread(void *s)
  138. {
  139.     gstream        *stream=(gstream *) s;
  140.     os_regset    regs;
  141.     os_error    *err;
  142.     int        **data=(int **) &(stream->data),
  143.             filehandle;
  144.  
  145.     regs.r[0]=0;
  146.     regs.r[1]=**data;
  147.     filehandle=**data;
  148.     flex_free(&(stream->data));
  149.     err=os_find(®s);
  150.     if (err!=NULL)
  151.     {
  152.         wimpt_complain(err);
  153.         stream->error=TRUE;
  154.         return FALSE;
  155.     }
  156.     else
  157.     {
  158.         register_file_closed(filehandle);
  159.         return TRUE;
  160.     }
  161. }
  162.  
  163. /* reads some bytes into an OS_READ stream.  Internal use ONLY */
  164.  
  165. static size_t reados(void *ptr, size_t nbytes, void *s)
  166. {
  167.     gstream        *stream=(gstream *) s;
  168.     os_error    *e;
  169.     os_gbpbstr    g;
  170.     int        **data=(int **) &(stream->data);
  171.  
  172.  
  173.     g.action=4;
  174.     g.file_handle=**data;
  175.     g.data_addr=ptr;
  176.     g.number=nbytes;
  177.     e=os_gbpb(&g);
  178.  
  179.     if (e!=NULL)
  180.     {
  181.         wimpt_complain(e);
  182.         stream->error=TRUE;
  183.         return 0;
  184.     }
  185.     return(nbytes-g.number);
  186. }
  187.  
  188. /* This function opens a file for read access.  fname should be a valid
  189.  * pathname under RISC OS and stream should point to a gstream struct
  190.  */
  191.  
  192. int gsopenosr(char *fname, gstream *stream)
  193. {
  194.     os_error    *err;
  195.     os_regset    regs;
  196.     int        **data;
  197.  
  198.     stream->bufsize=gsgetbuf(&(stream->buffer),gs_BUFSIZE,0);
  199.     stream->pos=0;
  200.     stream->size=0;
  201.     stream->ungetsize=0;
  202.     stream->ungetpos=0;
  203.     stream->io.read=reados;
  204.     stream->close=closeosread;
  205.     stream->type=READ;
  206.  
  207.     if (!flex_alloc(&(stream->data),sizeof(int)))
  208.     {
  209.         if (stream->bufsize!=0)
  210.             flex_free(&(stream->buffer));
  211.         werr(FALSE,"Not enough space");
  212.         return FALSE;
  213.     }
  214.  
  215.     data=(int **) &(stream->data);
  216.  
  217.     regs.r[0]=0x4f; /* RISC OS 2.0 PRM page 881 */
  218.     regs.r[1]=(int)fname;
  219.     regs.r[2]=0;
  220.     err=os_find(®s);
  221.  
  222.     if (err!=NULL)
  223.     {
  224.         wimpt_complain(err);
  225.         flex_free(&(stream->data));
  226.         flex_free(&(stream->buffer));
  227.         return FALSE;
  228.     }
  229.     else
  230.     {
  231.         **data=regs.r[0];
  232.         register_file_opened(regs.r[0]);
  233.         stream->error=FALSE;
  234.         return TRUE;
  235.     }
  236. }
  237.  
  238. /* this function closes the write stream.  Internal use ONLY */
  239.  
  240. static int closeoswrite(void *s)
  241. {
  242.     gstream        *stream=(gstream *) s;
  243.     os_regset    regs;
  244.     os_error    *err;
  245.     int        **data=(int **) &(stream->data),
  246.             filehandle;
  247.  
  248.     regs.r[0]=0;
  249.     regs.r[1]=**data;
  250.     filehandle=**data;
  251.     err=os_find(®s);
  252.     flex_free(&(stream->data));
  253.  
  254.     if (err!=NULL)
  255.     {
  256.         wimpt_complain(err);
  257.         stream->error=TRUE;
  258.         return FALSE;
  259.     }
  260.     else
  261.     {
  262.         register_file_closed(filehandle);
  263.         return TRUE;
  264.     }
  265. }
  266.  
  267. /* writes some bytes to an OS_WRITE stream.  Internal use ONLY */
  268.  
  269. static size_t writeos(void *ptr, size_t nbytes, void *s)
  270. {
  271.     gstream        *stream=(gstream *) s;
  272.     os_error    *e;
  273.     os_gbpbstr    g;
  274.  
  275.     int **data=(int **) &(stream->data);
  276.  
  277.     g.action=2;
  278.     g.file_handle=**data;
  279.     g.data_addr=ptr;
  280.     g.number=nbytes;
  281.     e=os_gbpb(&g);
  282.     if (e!=NULL)
  283.     {
  284.         wimpt_complain(e);
  285.         stream->error=TRUE;
  286.         return 0;
  287.     }
  288.     return nbytes;
  289. }
  290.  
  291. /* opens a file for write access.  Filename can be any valid RISC OS filename
  292.  * eg SCSI::Winnie.$.Apps.!MyApp.!Choices or <MyApp$Dir>.!Choices
  293.  *
  294.  * stream will be an unopened or opened then closed gstream
  295.  */
  296.  
  297. int gsopenosw(char *fname, gstream *stream)
  298. {
  299.     os_error     *err;
  300.     os_regset    regs;
  301.  
  302.     int    **data;
  303.  
  304.     if (!flex_alloc(&(stream->data),sizeof(int)))
  305.     {
  306.         werr(FALSE,"Not enough space");
  307.         return FALSE;
  308.     }
  309.  
  310.     data=(int **) &(stream->data);
  311.  
  312.     stream->bufsize=gs_BUFSIZE;
  313.     stream->size=0;
  314.     stream->pos=0;
  315.  
  316.     stream->bufsize=gsgetbuf(&(stream->buffer),stream->bufsize,0);
  317.  
  318.     stream->type=WRITE;
  319.     stream->io.write=writeos;
  320.     stream->close=closeoswrite;
  321.  
  322.     regs.r[0]=0x8f; /* RISC OS 2.0 PRM page 881 */
  323.     regs.r[1]=(int)fname;
  324.     regs.r[2]=0;
  325.     err=os_find(®s);
  326.     if (err!=NULL)
  327.     {
  328.         wimpt_complain(err);
  329.         stream->error=TRUE;
  330.         flex_free(&(stream->data));
  331.         if (stream->bufsize!=0)
  332.             flex_free(&(stream->buffer));
  333.         return FALSE;
  334.     }
  335.     else
  336.     {
  337.         **data=regs.r[0];
  338.         register_file_opened(**data);
  339.         stream->error=FALSE;
  340.         return TRUE;
  341.     }
  342. }
  343.  
  344.