diff --git a/epicardium/epicardium.h b/epicardium/epicardium.h index 470a41853895ef3fbaec66ebea29cb2a8e68490c..9c4a770dd2ca448d94c011b76cc3801404e9194f 100644 --- a/epicardium/epicardium.h +++ b/epicardium/epicardium.h @@ -48,6 +48,15 @@ typedef unsigned int size_t; #define API_DISP_RECT 0x16 #define API_DISP_CIRC 0x17 #define API_DISP_PIXEL 0x18 + +#define API_FILE_OPEN 0x30 +#define API_FILE_CLOSE 0x31 +#define API_FILE_READ 0x32 +#define API_FILE_WRITE 0x34 +#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; @@ -439,4 +448,68 @@ API(API_LIGHT_SENSOR_GET, int epic_light_sensor_get(uint16_t* value)); */ API(API_LIGHT_SENSOR_STOP, int epic_light_sensor_stop()); +/** + * File + * ==== + * Except for :c:func:`epic_file_open`, which models C stdio's ``fopen`` + * function, ``close``, ``read`` and ``write`` model `close(2)`_, `read(2)`_ and + * `write(2)`_. All file-related functions return >= ``0`` on success and + * ``-Exyz`` on failure, with error codes from errno.h (``EIO``, ``EINVAL`` + * etc.) + * + * .. _close(2): http://man7.org/linux/man-pages/man2/close.2.html + * .. _read(2): http://man7.org/linux/man-pages/man2/read.2.html + * .. _write(2): http://man7.org/linux/man-pages/man2/write.2.html + */ + +/** */ +API( + API_FILE_OPEN, + int epic_file_open(const char* filename, const char* modeString) +); + +/** */ +API(API_FILE_CLOSE, int epic_file_close(int fd)); + +/** */ +API(API_FILE_READ, int epic_file_read(int fd, void* buf, size_t nbytes)); + +/** */ +API( + API_FILE_WRITE, + int epic_file_write(int fd, const void* buf, size_t nbytes) +); + +/** */ +API(API_FILE_FLUSH, int epic_file_flush(int 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 + */ +API(API_FILE_STAT, int epic_file_stat(const char* path, epic_stat_t* stat)); + #endif /* _EPICARDIUM_H */ diff --git a/epicardium/modules/fatfs.c b/epicardium/modules/fatfs.c index fc76bb5532640d8a2e3a2484e7880f20e15c49ef..649ba730374bbf2901c42373aa8f8b8575d903f8 100644 --- a/epicardium/modules/fatfs.c +++ b/epicardium/modules/fatfs.c @@ -2,24 +2,74 @@ * support routines for FatFs */ -#include <stddef.h> //NULL +#include <errno.h> +#include <stddef.h> #include <stdio.h> #include <stdbool.h> +#include <stdlib.h> + #include <ff.h> #include <FreeRTOS.h> #include <semphr.h> +#include "modules.h" +#include "epicardium.h" + +#ifndef EPIC_FAT_STATIC_SEMAPHORE +#define EPIC_FAT_STATIC_SEMAPHORE 0 +#endif + static const TCHAR *rcstrings = _T("OK\0DISK_ERR\0INT_ERR\0NOT_READY\0NO_FILE\0NO_PATH\0INVALID_NAME\0") _T("DENIED\0EXIST\0INVALID_OBJECT\0WRITE_PROTECTED\0INVALID_DRIVE\0") _T("NOT_ENABLED\0NO_FILESYSTEM\0MKFS_ABORTED\0TIMEOUT\0LOCKED\0") _T("NOT_ENOUGH_CORE\0TOO_MANY_OPEN_FILES\0INVALID_PARAMETER\0"); +// this table converts from FRESULT to POSIX errno +const int fresult_to_errno_table[20] = { + [FR_OK] = 0, + [FR_DISK_ERR] = EIO, + [FR_INT_ERR] = EIO, + [FR_NOT_READY] = EBUSY, + [FR_NO_FILE] = ENOENT, + [FR_NO_PATH] = ENOENT, + [FR_INVALID_NAME] = EINVAL, + [FR_DENIED] = EACCES, + [FR_EXIST] = EEXIST, + [FR_INVALID_OBJECT] = EINVAL, + [FR_WRITE_PROTECTED] = EROFS, + [FR_INVALID_DRIVE] = ENODEV, + [FR_NOT_ENABLED] = ENODEV, + [FR_NO_FILESYSTEM] = ENODEV, + [FR_MKFS_ABORTED] = EIO, + [FR_TIMEOUT] = EIO, + [FR_LOCKED] = EIO, + [FR_NOT_ENOUGH_CORE] = ENOMEM, + [FR_TOO_MANY_OPEN_FILES] = EMFILE, + [FR_INVALID_PARAMETER] = EINVAL, +}; + +enum FatObjectType { FO_Nil, FO_File, FO_Dir }; +struct FatObject { + enum FatObjectType type; + union { + FIL file; + DIR dir; + }; +}; + static bool mount(void); +static int +get_fat_object(int i, enum FatObjectType expected, struct FatObject **res); DIR dir; FATFS FatFs; +static struct FatObject s_openedObjects[EPIC_FAT_MAX_OPENED]; + +#if (EPIC_FAT_STATIC_SEMAPHORE == 1) +StaticSemaphore_t xSemaphoreBuffer; +#endif static volatile struct { bool initiaized; @@ -64,6 +114,7 @@ static bool mount() return true; } + /*------------------------------------------------------------------------*/ /* Create a Synchronization Object */ /*------------------------------------------------------------------------*/ @@ -79,7 +130,12 @@ static bool mount() */ int ff_cre_syncobj(BYTE vol, FF_SYNC_t *sobj) { +#if (EPIC_FAT_STATIC_SEMAPHORE == 1) + *sobj = xSemaphoreCreateMutexStatic(&xSemaphoreBuffer); +#else *sobj = xSemaphoreCreateMutex(); +#endif //EPIC_FAT_STATIC_SEMAPHORE + return (int)(*sobj != NULL); } @@ -98,7 +154,6 @@ int ff_cre_syncobj(BYTE vol, FF_SYNC_t *sobj) */ int ff_del_syncobj(FF_SYNC_t sobj) { - printf("%s\n", __PRETTY_FUNCTION__); /* FreeRTOS */ vSemaphoreDelete(sobj); return 1; @@ -133,3 +188,158 @@ void ff_rel_grant(FF_SYNC_t sobj) /* FreeRTOS */ xSemaphoreGive(sobj); } + +int get_fat_object(int i, enum FatObjectType expected, struct FatObject **res) +{ + if (i < 0 || i >= EPIC_FAT_MAX_OPENED) { + *res = NULL; + return EBADF; + } + if (s_openedObjects[i].type != expected) { + *res = NULL; + return EBADF; + } + *res = &s_openedObjects[i]; + return 0; +} + +int epic_file_open(const char *filename, const char *modeString) +{ + struct FatObject *o = NULL; + const char *mode_s = modeString; + int i; + int mode = 0; + + //find free object to use + for (i = 0; i < EPIC_FAT_MAX_OPENED; ++i) { + if (s_openedObjects[i].type == FO_Nil) { + break; + } + } + if (i == EPIC_FAT_MAX_OPENED) { + return -fresult_to_errno_table[FR_TOO_MANY_OPEN_FILES]; + } + o = &s_openedObjects[i]; + + while (*mode_s) { + switch (*mode_s++) { + case 'r': + mode |= FA_READ; + break; + case 'w': + mode |= FA_WRITE | FA_CREATE_ALWAYS; + break; + case 'x': + mode |= FA_WRITE | FA_CREATE_NEW; + break; + case 'a': + mode |= FA_WRITE | FA_OPEN_ALWAYS; + break; + case '+': + mode |= FA_READ | FA_WRITE; + break; + } + } + + int res = f_open(&o->file, filename, mode); + if (res != FR_OK) { + return -fresult_to_errno_table[res]; + } + o->type = FO_File; + + // for 'a' mode, we must begin at the end of the file + if ((mode & FA_OPEN_ALWAYS) != 0) { + f_lseek(&o->file, f_size(&o->file)); + } + + return i; +} + +int epic_file_close(int fd) +{ + int res; + struct FatObject *o; + res = get_fat_object(fd, FO_File, &o); + if (res) { + return -res; + } + + res = f_close(&o->file); + if (res != FR_OK) { + return -fresult_to_errno_table[res]; + } + + o->type = FO_Nil; + return 0; +} + +int epic_file_read(int fd, void *buf, size_t nbytes) +{ + unsigned int nread = 0; + + int res; + struct FatObject *o; + res = get_fat_object(fd, FO_File, &o); + if (res) { + return -res; + } + + res = f_read(&o->file, buf, nbytes, &nread); + if (res != FR_OK) { + return -fresult_to_errno_table[res]; + } + + return nread; +} + +int epic_file_write(int fd, const void *buf, size_t nbytes) +{ + unsigned int nwritten = 0; + + int res; + struct FatObject *o; + res = get_fat_object(fd, FO_File, &o); + if (res) { + return -res; + } + res = f_write(&o->file, buf, nbytes, &nwritten); + if (res != FR_OK) { + return -fresult_to_errno_table[res]; + } + + return nwritten; +} + +int epic_file_flush(int fd) +{ + int res; + struct FatObject *o; + res = get_fat_object(fd, FO_File, &o); + if (res) { + return -res; + } + res = f_sync(&o->file); + if (res != FR_OK) { + return -fresult_to_errno_table[res]; + } + + return 0; +} + +int epic_file_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/epicardium/modules/modules.h b/epicardium/modules/modules.h index 214545f6029e5201db4f3518a1224bc8ad6f12bd..f02298e36b2e538237fc75bfe0710517c11e33ab 100644 --- a/epicardium/modules/modules.h +++ b/epicardium/modules/modules.h @@ -1,7 +1,10 @@ #ifndef MODULES_H #define MODULES_H -/* FatFS */ +/* ---------- FAT fs ------------------------------------------------------ */ +/* max no. of descriptors (file & directory) that can be open at a time */ +#define EPIC_FAT_MAX_OPENED 16 +#define EPIC_FAT_STATIC_SEMAPHORE 1 void fatfs_init(void); /* ---------- Serial ------------------------------------------------------- */ diff --git a/pycardium/meson.build b/pycardium/meson.build index 2a1f08939c5f69273186d28050f44fe1bbe3b8b1..cf5f5ba57ecdbdb4d321cd5d6bc08dfc151024ff 100644 --- a/pycardium/meson.build +++ b/pycardium/meson.build @@ -6,7 +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 new file mode 100644 index 0000000000000000000000000000000000000000..e1d42f3efcc33c16f1425d23e061767d1eb6d5ad --- /dev/null +++ b/pycardium/modules/fat_file.c @@ -0,0 +1,274 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <stdio.h> + +#include "py/mpconfig.h" +#include "py/runtime.h" +#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; +#if MICROPY_PY_IO_FILEIO +extern const mp_obj_type_t mp_type_fat_fileio; +#endif + +typedef struct _pyb_file_obj_t { + mp_obj_base_t base; + int fd; +} pyb_file_obj_t; + +STATIC void +file_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) +{ + (void)kind; + mp_printf( + print, + "<io.%s %p>", + mp_obj_get_type_str(self_in), + MP_OBJ_TO_PTR(self_in) + ); +} + +STATIC mp_uint_t +file_obj_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) +{ + pyb_file_obj_t *self = MP_OBJ_TO_PTR(self_in); + int res = epic_file_read(self->fd, buf, size); + if (res < 0) { + *errcode = -res; + return MP_STREAM_ERROR; + } + return res; +} + +STATIC mp_uint_t +file_obj_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) +{ + pyb_file_obj_t *self = MP_OBJ_TO_PTR(self_in); + int res = epic_file_write(self->fd, buf, size); + if (res < 0) { + *errcode = -res; + return MP_STREAM_ERROR; + } + return res; +} + +STATIC mp_obj_t file_obj___exit__(size_t n_args, const mp_obj_t *args) +{ + (void)n_args; + return mp_stream_close(args[0]); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + file_obj___exit___obj, 4, 4, file_obj___exit__ +); + +STATIC mp_uint_t +file_obj_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) +{ + pyb_file_obj_t *self = MP_OBJ_TO_PTR(o_in); + int res; + switch (request) { + case MP_STREAM_FLUSH: + res = epic_file_flush(self->fd); + if (res < 0) { + *errcode = -res; + return MP_STREAM_ERROR; + } + return 0; + case MP_STREAM_CLOSE: + res = epic_file_close(self->fd); + if (res < 0) { + *errcode = -res; + return MP_STREAM_ERROR; + } + return 0; + } + //every valid case returns either success or error, so this is EINVAL land: + *errcode = MP_EINVAL; + return MP_STREAM_ERROR; + // if (request == MP_STREAM_SEEK) { + // struct mp_stream_seek_t *s = (struct mp_stream_seek_t*)(uintptr_t)arg; + + // switch (s->whence) { + // case 0: // SEEK_SET + // f_lseek(&self->fp, s->offset); + // break; + + // case 1: // SEEK_CUR + // f_lseek(&self->fp, f_tell(&self->fp) + s->offset); + // break; + + // case 2: // SEEK_END + // f_lseek(&self->fp, f_size(&self->fp) + s->offset); + // break; + // } + + // s->offset = f_tell(&self->fp); + // return 0; +} + +// Note: encoding is ignored for now; it's also not a valid kwarg for CPython's FileIO, +// but by adding it here we can use one single mp_arg_t array for open() and FileIO's constructor +STATIC const mp_arg_t file_open_args[] = { + { MP_QSTR_file, + MP_ARG_OBJ | MP_ARG_REQUIRED, + { .u_rom_obj = MP_ROM_PTR(&mp_const_none_obj) } }, + { MP_QSTR_mode, MP_ARG_OBJ, { .u_obj = MP_OBJ_NEW_QSTR(MP_QSTR_r) } }, + { MP_QSTR_encoding, + MP_ARG_OBJ | MP_ARG_KW_ONLY, + { .u_rom_obj = MP_ROM_PTR(&mp_const_none_obj) } }, +}; +#define FILE_OPEN_NUM_ARGS MP_ARRAY_SIZE(file_open_args) + +STATIC mp_obj_t file_open(const mp_obj_type_t *type, mp_arg_val_t *args) +{ + const char *modeString = mp_obj_str_get_str(args[1].u_obj); + const char *mode_s = modeString; + // modes r w x a + are handled on epicardium side, binary / text + // is relevant for python type so look for these here + while (*mode_s) { + switch (*mode_s++) { +#if MICROPY_PY_IO_FILEIO + case 'b': + type = &mp_type_fat_fileio; + break; +#endif + case 't': + type = &mp_type_fat_textio; + break; + } + } + + pyb_file_obj_t *o = m_new_obj_with_finaliser(pyb_file_obj_t); + o->base.type = type; + + const char *fname = mp_obj_str_get_str(args[0].u_obj); + int res = epic_file_open(fname, modeString); + if (res < 0) { + m_del_obj(pyb_file_obj_t, o); + mp_raise_OSError(-res); + } + o->fd = res; + + return MP_OBJ_FROM_PTR(o); +} + +STATIC mp_obj_t file_obj_make_new( + const mp_obj_type_t *type, + size_t n_args, + size_t n_kw, + const mp_obj_t *args +) { + mp_arg_val_t arg_vals[FILE_OPEN_NUM_ARGS]; + mp_arg_parse_all_kw_array( + n_args, + n_kw, + args, + FILE_OPEN_NUM_ARGS, + file_open_args, + arg_vals + ); + return file_open(type, arg_vals); +} + +// TODO gc hook to close the file if not already closed + +STATIC const mp_rom_map_elem_t rawfile_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_readline), + MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, + { MP_ROM_QSTR(MP_QSTR_readlines), + MP_ROM_PTR(&mp_stream_unbuffered_readlines_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) }, + { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, + { MP_ROM_QSTR(MP_QSTR_seek), MP_ROM_PTR(&mp_stream_seek_obj) }, + { MP_ROM_QSTR(MP_QSTR_tell), MP_ROM_PTR(&mp_stream_tell_obj) }, + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&file_obj___exit___obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table); + +#if MICROPY_PY_IO_FILEIO +STATIC const mp_stream_p_t fileio_stream_p = { + .read = file_obj_read, + .write = file_obj_write, + .ioctl = file_obj_ioctl, +}; + +const mp_obj_type_t mp_type_fat_fileio = { + { &mp_type_type }, + .name = MP_QSTR_FileIO, + .print = file_obj_print, + .make_new = file_obj_make_new, + .getiter = mp_identity_getiter, + .iternext = mp_stream_unbuffered_iter, + .protocol = &fileio_stream_p, + .locals_dict = (mp_obj_dict_t *)&rawfile_locals_dict, +}; +#endif + +STATIC const mp_stream_p_t textio_stream_p = { + .read = file_obj_read, + .write = file_obj_write, + .ioctl = file_obj_ioctl, + .is_text = true, +}; + +const mp_obj_type_t mp_type_fat_textio = { + { &mp_type_type }, + .name = MP_QSTR_TextIOWrapper, + .print = file_obj_print, + .make_new = file_obj_make_new, + .getiter = mp_identity_getiter, + .iternext = mp_stream_unbuffered_iter, + .protocol = &textio_stream_p, + .locals_dict = (mp_obj_dict_t *)&rawfile_locals_dict, +}; + +// Factory function for I/O stream classes +mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) +{ + // TODO: analyze buffering args and instantiate appropriate type + mp_arg_val_t arg_vals[FILE_OPEN_NUM_ARGS]; + mp_arg_parse_all( + n_args, + args, + kwargs, + FILE_OPEN_NUM_ARGS, + file_open_args, + arg_vals + ); + 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 0000000000000000000000000000000000000000..bb35aec22ff8cd66c11c02924b8ce3eeb944b430 --- /dev/null +++ b/pycardium/modules/fat_reader_import.c @@ -0,0 +1,83 @@ +#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_file_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_file_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_file_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_file_read(rp->fd, rp->buf, sizeof(rp->buf)); + if (n < 0) { + epic_file_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_file_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/modules/qstrdefs.h b/pycardium/modules/qstrdefs.h index 3dda54d667557f66d39978788fbde813f8e39390..e8ac9dac50a12c6a1566c07626050358940587fc 100644 --- a/pycardium/modules/qstrdefs.h +++ b/pycardium/modules/qstrdefs.h @@ -46,3 +46,24 @@ Q(light_sensor) Q(start) Q(get_reading) Q(stop) + +/* file */ +Q(__del__) +Q(__enter__) +Q(__exit__) +Q(close) +Q(encoding) +Q(file) +Q(FileIO) +Q(flush) +Q(mode) +Q(r) +Q(read) +Q(readinto) +Q(readline) +Q(readlines) +Q(seek) +Q(tell) +Q(TextIOWrapper) +Q(write) + diff --git a/pycardium/mpconfigport.h b/pycardium/mpconfigport.h index 6bfb2c6717fcddb0bfcd585fb13c401b5df86bb9..9bed1f600fd79535f4f53d6792f0ded869cf99d0 100644 --- a/pycardium/mpconfigport.h +++ b/pycardium/mpconfigport.h @@ -76,3 +76,4 @@ typedef long mp_off_t; /* For some reason, we need to define readline history manually */ #define MICROPY_PORT_ROOT_POINTERS \ const char *readline_hist[16]; + diff --git a/pycardium/mphalport.c b/pycardium/mphalport.c index 9e0402779651f13808726eef4b62a1d6d97ed064..b97c1dd4130734ce2e3145dead584764f7d921f4 100644 --- a/pycardium/mphalport.c +++ b/pycardium/mphalport.c @@ -135,26 +135,3 @@ void NORETURN nlr_jump_fail(void *val) Reset_Handler(); } - -/****************************************************************************** - * 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; -} - -mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) -{ - /* TODO: Once fs is implemented, get this working as well */ - mp_raise_NotImplementedError("FS is not yet implemented"); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open);