Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. #include <string.h>
  2. #include "tp.h"
  3.  
  4. extern tp_obj tp_fnc(TP,tp_obj v(TP));
  5. extern tp_obj tp_method(TP,tp_obj self,tp_obj v(TP));
  6. extern tp_obj tp_number(tp_num v);
  7. extern tp_obj tp_string(char const *v);
  8. extern tp_obj tp_list(TP);
  9. extern tp_obj tp_dict(TP);
  10. extern void _tp_raise(TP,tp_obj);
  11. #define _cdecl __attribute__((cdecl))
  12. extern int (* _cdecl con_printf)(const char* format,...);
  13.  
  14. #define call70(par, st) asm volatile ("int   $0x40":"=a"(st):"a"(70), "b"(par))
  15. #define call70_rw(par, st, cnt) asm volatile ("int   $0x40":"=a"(st), "=b"(cnt):"a"(70), "b"(par))
  16. typedef unsigned int uint32_t;
  17. typedef unsigned char uint8_t;
  18.  
  19. typedef struct {
  20.         uint32_t subfnc;
  21.         uint32_t res1;
  22.         uint32_t res2;
  23.         uint32_t res3;
  24.         uint8_t *data;
  25.         uint8_t  res4;
  26.         char    *fn;
  27.     }__attribute__((__packed__))  info_params_t;
  28.  
  29. typedef struct {
  30.         uint32_t subfnc;
  31.         uint32_t pos;
  32.         uint32_t res1;
  33.         uint32_t cnt;
  34.         char*    data;
  35.         uint8_t res2;
  36.         char*    fn;
  37.     } __attribute__((__packed__)) rw_params_t;
  38.  
  39. static tp_obj kolibri_close(TP)
  40. {
  41.     tp_obj self = TP_TYPE(TP_DICT);
  42.     uint32_t size = tp_get(tp, self, tp_string("size")).number.val;
  43.     char *mode = (char *)tp_get(tp, self, tp_string("mode")).string.val;
  44.     tp_set(tp, self, tp_string("closed"), tp_True);
  45.     return tp_None;
  46. }
  47.  
  48. static tp_obj kolibri_read(TP)
  49. {
  50.     uint32_t status, num;
  51.     tp_obj self = TP_TYPE(TP_DICT);
  52.     uint32_t pos = tp_get(tp, self, tp_string("pos")).number.val;
  53.     uint32_t size = tp_get(tp, self, tp_string("size")).number.val;
  54.     uint32_t cnt;
  55.     char *buf = (char *)malloc(size - pos);
  56.     rw_params_t params = {0, pos, 0, size - pos, buf, 0,
  57.                 (char *)tp_get(tp, self, tp_string("name")).string.val};
  58.     char *mode = (char *)tp_get(tp, self, tp_string("mode")).string.val;
  59.  
  60.     if (*mode != 'r')
  61.         tp_raise(tp_None, "IOError: file not open for reading", tp_None);
  62.  
  63.     if (!buf)
  64.         return tp_None;
  65.     call70_rw((&params), status, cnt);
  66.     buf[cnt] = '\0';
  67.     return tp_string(buf);
  68. }
  69.  
  70. #if 0
  71. static tp_obj kolibri_readline(TP)
  72. {
  73.     return tp_string("Line");
  74. }
  75.  
  76. static tp_obj kolibri_readlines(TP)
  77. {
  78.     tp_obj result = tp_list(tp);
  79.     int i;
  80.  
  81.     for(i=0; i < 5; i++)
  82.         tp_add(result, tp_string("Line"));
  83.     return result;
  84. }
  85. #endif
  86.  
  87. /* Write object to file.
  88.  *
  89.  * tp   TinyPy virtual machine structure.
  90.  *
  91.  * returns tp_True
  92.  */
  93. static tp_obj kolibri_write(TP)
  94. {
  95.     tp_obj self = TP_TYPE(TP_DICT);
  96.     tp_obj obj = TP_OBJ(); /* What to write. */
  97.     char *mode = (char *)tp_get(tp, self, tp_string("mode")).string.val;
  98.     uint32_t pos = (uint32_t)tp_get(tp, self, tp_string("pos")).number.val;
  99.     uint32_t size = (uint32_t)tp_get(tp, self, tp_string("size")).number.val;
  100.  
  101.     if (*mode != 'w' && *mode != 'a')
  102.     {
  103.         tp_raise(tp_None, "IOError: file not open for writing", tp_None);
  104.     }
  105.     else
  106.     {
  107.         char *data = (char *)TP_CSTR(obj);
  108.         rw_params_t params = {3, pos, 0, strlen(data), data, 0,
  109.                              (char *)tp_get(tp, self, tp_string("name")).string.val};
  110.         uint32_t status;
  111.         uint32_t cnt;
  112.         call70_rw((&params), status, cnt);
  113.         if (status)
  114.         {
  115.             tp_raise(tp_None, "IOError: writing failed with status %d", status);
  116.         }
  117.         pos += cnt;
  118.         tp_set(tp, self, tp_string("pos"), tp_number(pos));
  119.         if (pos > size)
  120.         {
  121.             /* If writing has come beyond the file, increase its size. */
  122.             tp_set(tp, self, tp_string("size"), tp_number(pos));
  123.         }
  124.         return tp_True;
  125.     }
  126. }
  127.  
  128. /* Write line list into file.
  129.  *
  130.  * tp   TinyPy virtual machine structure.
  131.  *
  132.  * returns tp_None.
  133.  */
  134. static tp_obj kolibri_writelines(TP)
  135. {
  136.     tp_obj result = tp_None;
  137.     tp_obj self = TP_TYPE(TP_DICT);
  138.     tp_obj list = TP_TYPE(TP_LIST); /* What to write. */
  139.     char *mode = (char *)tp_get(tp, self, tp_string("mode")).string.val;
  140.     long pos = (long)tp_get(tp, self, tp_string("pos")).number.val;
  141.     uint32_t size = (uint32_t)tp_get(tp, self, tp_string("size")).number.val;
  142.  
  143.     if (*mode != 'w' && *mode != 'a')
  144.     {
  145.         tp_raise(tp_None, "IOError: file not open for writing", tp_None);
  146.     }
  147.     else
  148.     {
  149.         int i;
  150.         char *fn = (char *)tp_get(tp, self, tp_string("name")).string.val;
  151.         rw_params_t params = {3, 0, 0, 0, NULL, 0, fn};
  152.  
  153.         for (i = 0; i < list.list.val->len; i++)
  154.         {
  155.             char *data = (char *)TP_CSTR(list.list.val->items[i]);
  156.             uint32_t status;
  157.             uint32_t cnt;
  158.  
  159.             params.data = data;
  160.             params.cnt = strlen(data);
  161.             params.pos = pos;
  162.  
  163.             call70_rw((&params), status, cnt);
  164.             if (status)
  165.                 tp_raise(tp_None, "IOError: writing failed with status %d", status);
  166.             pos += cnt;
  167.         }
  168.         tp_set(tp, self, tp_string("pos"), tp_number(pos));
  169.         if (pos > size)
  170.         {
  171.             /* If writing has come beyond the file, increase its size. */
  172.             tp_set(tp, self, tp_string("size"), tp_number(pos));
  173.         }
  174.         return tp_True;
  175.     }
  176. }
  177.  
  178. /* Get file size.
  179.  *
  180.  * fn   ASCIIZ absolute file path.
  181.  */
  182. long long int kolibri_filesize(const char *fn)
  183. {
  184.     uint8_t data[40];
  185.     uint32_t status;
  186.     long long int result;
  187.     info_params_t params = {5, 0, 0, 0, data, 0, (char *)fn};
  188.  
  189.     call70((&params), status);
  190.     /* File size is at offset 32. */
  191.     if (status == 0)
  192.         result = *(long long*)(&data[32]);
  193.     else
  194.         result = -status;
  195.     return result;
  196. }
  197.  
  198.  
  199. /* Open file.
  200.  *
  201.  * tp   TinyPy virtual machine structure.
  202.  *
  203.  * returns file object.
  204.  */
  205. tp_obj kolibri_open(TP) {
  206.     tp_obj obj;
  207.     char *fn = (char *)(TP_TYPE(TP_STRING).string.val);
  208.     tp_obj mode_obj = TP_OBJ();
  209.     long long int size;
  210.     long long int pos = 0;
  211.     uint32_t status;
  212.     info_params_t params = {2, 0, 0, 0, NULL, 0, fn};
  213.  
  214.     if (mode_obj.type == TP_NONE)
  215.         mode_obj = tp_string("r");
  216.     else if (mode_obj.type != TP_STRING)
  217.         tp_raise(tp_None, "ValueError: bad file access mode %s", TP_CSTR(mode_obj));
  218.     switch(mode_obj.string.val[0])
  219.     {
  220.         case 'w':
  221.             call70((&params), status);
  222.             if (status)
  223.                 tp_raise(tp_None, "IOError: cannot open file for writing", tp_None);
  224.             size = 0;
  225.             break;
  226.         case 'a':
  227.             pos = size;
  228.             break;
  229.         case 'r':
  230.             break;
  231.         default:
  232.             tp_raise(tp_None, "ValueError: mode string must begin with 'r', 'w', or 'a'", tp_None);
  233.     }
  234.     if ((size = kolibri_filesize(fn)) < 0)
  235.         tp_raise(tp_None, "IOError: filesize returned %d", tp_number(size));
  236.     obj = tp_dict(tp);
  237.     tp_set(tp, obj, tp_string("name"), tp_string(fn));
  238.     tp_set(tp, obj, tp_string("size"), tp_number(size));
  239.     tp_set(tp, obj, tp_string("pos"), tp_number(pos));
  240.     tp_set(tp, obj, tp_string("mode"), mode_obj);
  241. #if 0
  242.     tp_set(tp, obj, tp_string("__doc__"),
  243.            tp_string("File object.\nAttributes:\n  name: file name\n"
  244.                      "  closed: boolean indicating whether file was closed\n"
  245.                      "Methods:\n  read: read the entire file into string\n"
  246.                      "  readlines: get list of lines\n"
  247.                      "  close: close the file\n"
  248.                      ));
  249. #endif
  250.     tp_set(tp, obj, tp_string("closed"), tp_False);
  251.     tp_set(tp, obj, tp_string("close"), tp_method(tp, obj, kolibri_close));
  252.     tp_set(tp, obj, tp_string("read"), tp_method(tp, obj, kolibri_read));
  253.     tp_set(tp, obj, tp_string("write"), tp_method(tp, obj, kolibri_write));
  254.     tp_set(tp, obj, tp_string("writelines"), tp_method(tp, obj, kolibri_writelines));
  255.     return obj;
  256. }
  257.  
  258.  
  259.