From 69a12a838195eaca325e2dc8047095dc1a1bdbdd Mon Sep 17 00:00:00 2001
From: swym <0xfd000000@gmail.com>
Date: Wed, 24 Jul 2019 22:47:19 +0200
Subject: [PATCH] implement necessary functionality for making import in
 micropython work

---
 epicardium/epicardium.h               | 26 +++++++++
 epicardium/modules/fatfs.c            | 19 +++++++
 pycardium/meson.build                 |  3 +-
 pycardium/modules/fat_file.c          |  2 +
 pycardium/modules/fat_reader_import.c | 79 +++++++++++++++++++++++++++
 pycardium/mphalport.c                 | 11 ----
 6 files changed, 128 insertions(+), 12 deletions(-)
 create mode 100644 pycardium/modules/fat_reader_import.c

diff --git a/epicardium/epicardium.h b/epicardium/epicardium.h
index 4456a0bb..e7638d94 100644
--- a/epicardium/epicardium.h
+++ b/epicardium/epicardium.h
@@ -56,6 +56,7 @@ typedef unsigned int size_t;
 #define API_FILE_FLUSH         0x35
 #define API_FILE_SEEK          0x36 //NYI
 #define API_FILE_TELL          0x37 //NYI
+#define API_FILE_STAT          0x38
 /* clang-format on */
 
 typedef uint32_t api_int_id_t;
@@ -463,4 +464,29 @@ API(API_FILE_READ,  int32_t epic_read(int32_t fd, void* buf, uint32_t nbytes));
 API(API_FILE_WRITE, int32_t epic_write(int32_t fd, const void* buf, uint32_t nbytes));
 API(API_FILE_FLUSH, int32_t epic_flush(int32_t fd));
 
+enum epic_stat_type {
+    EPICSTAT_FILE,
+    EPICSTAT_DIR,
+};
+
+typedef struct epic_stat_t {
+    enum epic_stat_type type;
+} epic_stat_t;
+
+/**
+ * stat path
+ *
+ * This does not follow posix convention, but rather takes
+ * a path as parameter. This aligns more with libff's API and
+ * also this has been implemented for python import support, which
+ * passes the filename as well.
+ *
+ * :param const char* filename: path to stat
+ * :param epic_stat_t* stat: pointer to result
+ *
+ * :return: `0` on success, negative on error
+ *      if an error occured.
+ */
+API(API_FILE_STAT,  int32_t epic_stat(const char* path, epic_stat_t* stat));
+
 #endif /* _EPICARDIUM_H */
diff --git a/epicardium/modules/fatfs.c b/epicardium/modules/fatfs.c
index 84622d26..254f9a0a 100644
--- a/epicardium/modules/fatfs.c
+++ b/epicardium/modules/fatfs.c
@@ -14,6 +14,7 @@
 #include <semphr.h>
 
 #include "modules.h"
+#include "epicardium.h"
 
 #ifndef EPIC_FAT_STATIC_SEMAPHORE
 #define EPIC_FAT_STATIC_SEMAPHORE 0
@@ -326,3 +327,21 @@ int32_t epic_flush(int32_t fd) {
     return 0;
 }
 
+int32_t epic_stat(const char* filename, epic_stat_t* stat) {
+
+    int res;
+    FILINFO finfo;
+    res = f_stat(filename, &finfo);
+    if (res != FR_OK) {
+        return -fresult_to_errno_table[res];
+    }
+
+    if(finfo.fattrib & AM_DIR) {
+        stat->type = EPICSTAT_DIR;
+    } else {
+        stat->type = EPICSTAT_FILE;
+    }
+
+    return 0;
+}
+
diff --git a/pycardium/meson.build b/pycardium/meson.build
index 453fc752..42fa849d 100644
--- a/pycardium/meson.build
+++ b/pycardium/meson.build
@@ -6,8 +6,9 @@ modsrc = files(
   'modules/sys_display.c',
   'modules/utime.c',
   'modules/vibra.c',
-  'modules/light_sensor.c'
+  'modules/light_sensor.c',
   'modules/fat_file.c',
+  'modules/fat_reader_import.c',
 )
 
 #################################
diff --git a/pycardium/modules/fat_file.c b/pycardium/modules/fat_file.c
index 711217b4..70f01995 100644
--- a/pycardium/modules/fat_file.c
+++ b/pycardium/modules/fat_file.c
@@ -31,6 +31,7 @@
 #include "py/builtin.h"
 #include "py/stream.h"
 #include "py/mperrno.h"
+
 #include "epicardium.h"
 
 extern const mp_obj_type_t mp_type_fat_textio;
@@ -271,3 +272,4 @@ mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs)
 	return file_open(&mp_type_fat_textio, arg_vals);
 }
 MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open);
+
diff --git a/pycardium/modules/fat_reader_import.c b/pycardium/modules/fat_reader_import.c
new file mode 100644
index 00000000..a035754e
--- /dev/null
+++ b/pycardium/modules/fat_reader_import.c
@@ -0,0 +1,79 @@
+#include "epicardium.h"
+
+#include <py/runtime.h>
+#include <py/reader.h>
+#include <py/lexer.h>
+
+/** ported from picropython's posic implementation */
+
+typedef struct _mp_reader_epicfat_t {
+    bool close_fd;
+    int fd;
+    size_t len;
+    size_t pos;
+    byte buf[20];
+} mp_reader_epicfat_t;
+
+STATIC mp_uint_t mp_reader_epicfat_readbyte(void *data) {
+    mp_reader_epicfat_t *reader = (mp_reader_epicfat_t*)data;
+    if (reader->pos >= reader->len) {
+        if (reader->len == 0) {
+            return MP_READER_EOF;
+        } else {
+            int n = epic_read(reader->fd, reader->buf, sizeof(reader->buf));
+            if (n <= 0) {
+                reader->len = 0;
+                return MP_READER_EOF;
+            }
+            reader->len = n;
+            reader->pos = 0;
+        }
+    }
+    return reader->buf[reader->pos++];
+}
+
+STATIC void mp_reader_epicfat_close(void *data) {
+    mp_reader_epicfat_t *reader = (mp_reader_epicfat_t*)data;
+    epic_close(reader->fd);
+    m_del_obj(mp_reader_epicfat_t, reader);
+}
+
+void mp_reader_new_file(mp_reader_t* reader, const char *filename)
+{
+    int fd = epic_open(filename, "r");
+    if (fd < 0) {
+        mp_raise_OSError(-fd);
+    }
+    mp_reader_epicfat_t *rp = m_new_obj(mp_reader_epicfat_t);
+    rp->fd = fd;
+    int n = epic_read(rp->fd, rp->buf, sizeof(rp->buf));
+    if (n < 0) {
+        epic_close(fd);
+    }
+    rp->len = n;
+    rp->pos = 0;
+    reader->data = rp;
+    reader->readbyte = mp_reader_epicfat_readbyte;
+    reader->close = mp_reader_epicfat_close;
+}
+
+mp_lexer_t *mp_lexer_new_from_file(const char *filename)
+{
+    mp_reader_t reader;
+    mp_reader_new_file(&reader, filename);
+    return mp_lexer_new(qstr_from_str(filename), reader);
+}
+
+mp_import_stat_t mp_import_stat(const char *path)
+{
+    struct epic_stat_t stat;
+
+    if(epic_stat(path, &stat) == 0) {
+        if (stat.type == EPICSTAT_FILE) {
+            return MP_IMPORT_STAT_FILE;
+        } else {
+            return MP_IMPORT_STAT_DIR;
+        }
+    }
+	return MP_IMPORT_STAT_NO_EXIST;
+}
diff --git a/pycardium/mphalport.c b/pycardium/mphalport.c
index 7c14df44..29784be5 100644
--- a/pycardium/mphalport.c
+++ b/pycardium/mphalport.c
@@ -121,14 +121,3 @@ void NORETURN nlr_jump_fail(void *val)
  * Stubs
  */
 
-mp_lexer_t *mp_lexer_new_from_file(const char *filename)
-{
-	/* TODO: Do we need an implementation for this? */
-	mp_raise_OSError(MP_ENOENT);
-}
-
-mp_import_stat_t mp_import_stat(const char *path)
-{
-	return MP_IMPORT_STAT_NO_EXIST;
-}
-
-- 
GitLab