Subversion Repositories Kolibri OS

Rev

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

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