diff options
Diffstat (limited to 'unix')
41 files changed, 0 insertions, 6160 deletions
diff --git a/unix/.gitignore b/unix/.gitignore deleted file mode 100644 index 706b7732dc..0000000000 --- a/unix/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -build -build-fast -build-minimal -build-coverage -build-nanbox -build-freedos -micropython -micropython_fast -micropython_minimal -micropython_coverage -micropython_nanbox -micropython_freedos* -*.py -*.gcov diff --git a/unix/Makefile b/unix/Makefile deleted file mode 100644 index 08bd4db306..0000000000 --- a/unix/Makefile +++ /dev/null @@ -1,294 +0,0 @@ --include mpconfigport.mk -include ../py/mkenv.mk - -FROZEN_DIR = scripts -FROZEN_MPY_DIR = modules - -# define main target -PROG = micropython - -# qstr definitions (must come before including py.mk) -QSTR_DEFS = qstrdefsport.h - -# OS name, for simple autoconfig -UNAME_S := $(shell uname -s) - -# include py core make definitions -include $(TOP)/py/py.mk - -INC += -I. -INC += -I$(TOP) -INC += -I$(BUILD) - -# compiler settings -CWARN = -Wall -Werror -CWARN += -Wpointer-arith -Wuninitialized -CFLAGS = $(INC) $(CWARN) -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA) - -# Debugging/Optimization -ifdef DEBUG -CFLAGS += -g -COPT = -O0 -else -COPT = -Os -fdata-sections -ffunction-sections -DNDEBUG -# _FORTIFY_SOURCE is a feature in gcc/glibc which is intended to provide extra -# security for detecting buffer overflows. Some distros (Ubuntu at the very least) -# have it enabled by default. -# -# gcc already optimizes some printf calls to call puts and/or putchar. When -# _FORTIFY_SOURCE is enabled and compiling with -O1 or greater, then some -# printf calls will also be optimized to call __printf_chk (in glibc). Any -# printfs which get redirected to __printf_chk are then no longer synchronized -# with printfs that go through mp_printf. -# -# In MicroPython, we don't want to use the runtime library's printf but rather -# go through mp_printf, so that stdout is properly tied into streams, etc. -# This means that we either need to turn off _FORTIFY_SOURCE or provide our -# own implementation of __printf_chk. We've chosen to turn off _FORTIFY_SOURCE. -# It should also be noted that the use of printf in MicroPython is typically -# quite limited anyways (primarily for debug and some error reporting, etc -# in the unix version). -# -# Information about _FORTIFY_SOURCE seems to be rather scarce. The best I could -# find was this: https://securityblog.redhat.com/2014/03/26/fortify-and-you/ -# Original patchset was introduced by -# https://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html . -# -# Turning off _FORTIFY_SOURCE is only required when compiling with -O1 or greater -CFLAGS += -U _FORTIFY_SOURCE -endif - -# On OSX, 'gcc' is a symlink to clang unless a real gcc is installed. -# The unix port of MicroPython on OSX must be compiled with clang, -# while cross-compile ports require gcc, so we test here for OSX and -# if necessary override the value of 'CC' set in py/mkenv.mk -ifeq ($(UNAME_S),Darwin) -ifeq ($(MICROPY_FORCE_32BIT),1) -CC = clang -m32 -else -CC = clang -endif -# Use clang syntax for map file -LDFLAGS_ARCH = -Wl,-map,$@.map -Wl,-dead_strip -else -# Use gcc syntax for map file -LDFLAGS_ARCH = -Wl,-Map=$@.map,--cref -Wl,--gc-sections -endif -LDFLAGS = $(LDFLAGS_MOD) $(LDFLAGS_ARCH) -lm $(LDFLAGS_EXTRA) - -ifeq ($(MICROPY_FORCE_32BIT),1) -# Note: you may need to install i386 versions of dependency packages, -# starting with linux-libc-dev:i386 -ifeq ($(MICROPY_PY_FFI),1) -ifeq ($(UNAME_S),Linux) -CFLAGS_MOD += -I/usr/include/i686-linux-gnu -endif -endif -endif - -ifeq ($(MICROPY_USE_READLINE),1) -INC += -I$(TOP)/lib/mp-readline -CFLAGS_MOD += -DMICROPY_USE_READLINE=1 -LIB_SRC_C_EXTRA += mp-readline/readline.c -endif -ifeq ($(MICROPY_PY_TERMIOS),1) -CFLAGS_MOD += -DMICROPY_PY_TERMIOS=1 -SRC_MOD += modtermios.c -endif -ifeq ($(MICROPY_PY_SOCKET),1) -CFLAGS_MOD += -DMICROPY_PY_SOCKET=1 -SRC_MOD += modsocket.c -endif -ifeq ($(MICROPY_PY_THREAD),1) -CFLAGS_MOD += -DMICROPY_PY_THREAD=1 -DMICROPY_PY_THREAD_GIL=0 -LDFLAGS_MOD += -lpthread -endif - -ifeq ($(MICROPY_PY_FFI),1) - -ifeq ($(MICROPY_STANDALONE),1) -LIBFFI_CFLAGS_MOD := -I$(shell ls -1d $(TOP)/lib/libffi/build_dir/out/lib/libffi-*/include) - ifeq ($(MICROPY_FORCE_32BIT),1) - LIBFFI_LDFLAGS_MOD = $(TOP)/lib/libffi/build_dir/out/lib32/libffi.a - else - LIBFFI_LDFLAGS_MOD = $(TOP)/lib/libffi/build_dir/out/lib/libffi.a - endif -else -LIBFFI_CFLAGS_MOD := $(shell pkg-config --cflags libffi) -LIBFFI_LDFLAGS_MOD := $(shell pkg-config --libs libffi) -endif - -ifeq ($(UNAME_S),Linux) -LIBFFI_LDFLAGS_MOD += -ldl -endif - -CFLAGS_MOD += $(LIBFFI_CFLAGS_MOD) -DMICROPY_PY_FFI=1 -LDFLAGS_MOD += $(LIBFFI_LDFLAGS_MOD) -SRC_MOD += modffi.c -endif - -ifeq ($(MICROPY_PY_JNI),1) -# Path for 64-bit OpenJDK, should be adjusted for other JDKs -CFLAGS_MOD += -I/usr/lib/jvm/java-7-openjdk-amd64/include -DMICROPY_PY_JNI=1 -SRC_MOD += modjni.c -endif - -# source files -SRC_C = \ - main.c \ - gccollect.c \ - unix_mphal.c \ - mpthreadport.c \ - input.c \ - file.c \ - modmachine.c \ - modos.c \ - moduos_vfs.c \ - modtime.c \ - moduselect.c \ - alloc.c \ - coverage.c \ - fatfs_port.c \ - $(SRC_MOD) - -LIB_SRC_C = $(addprefix lib/,\ - $(LIB_SRC_C_EXTRA) \ - timeutils/timeutils.c \ - ) - -# FatFS VFS support -LIB_SRC_C += $(addprefix lib/,\ - oofatfs/ff.c \ - oofatfs/option/unicode.c \ - ) - -OBJ = $(PY_O) -OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) -OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o)) -OBJ += $(addprefix $(BUILD)/, $(STMHAL_SRC_C:.c=.o)) - -# List of sources for qstr extraction -SRC_QSTR += $(SRC_C) $(LIB_SRC_C) -# Append any auto-generated sources that are needed by sources listed in -# SRC_QSTR -SRC_QSTR_AUTO_DEPS += - -ifneq ($(FROZEN_MPY_DIR),) -# To use frozen bytecode, put your .py files in a subdirectory (eg frozen/) and -# then invoke make with FROZEN_MPY_DIR=frozen (be sure to build from scratch). -CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool -CFLAGS += -DMICROPY_MODULE_FROZEN_MPY -CFLAGS += -DMPZ_DIG_SIZE=16 # force 16 bits to work on both 32 and 64 bit archs -MPY_CROSS_FLAGS += -mcache-lookup-bc -endif - - -include $(TOP)/py/mkrules.mk - -.PHONY: test - -test: $(PROG) $(TOP)/tests/run-tests - $(eval DIRNAME=$(notdir $(CURDIR))) - cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(PROG) ./run-tests - -# install micropython in /usr/local/bin -TARGET = micropython -PREFIX = $(DESTDIR)/usr/local -BINDIR = $(PREFIX)/bin - -install: micropython - install -d $(BINDIR) - install $(TARGET) $(BINDIR)/$(TARGET) - -# uninstall micropython -uninstall: - -rm $(BINDIR)/$(TARGET) - -# build synthetically fast interpreter for benchmarking -fast: - $(MAKE) COPT="-O2 -DNDEBUG -fno-crossjumping" CFLAGS_EXTRA='-DMP_CONFIGFILE="<mpconfigport_fast.h>"' BUILD=build-fast PROG=micropython_fast - -# build a minimal interpreter -minimal: - $(MAKE) COPT="-Os -DNDEBUG" CFLAGS_EXTRA='-DMP_CONFIGFILE="<mpconfigport_minimal.h>"' \ - BUILD=build-minimal PROG=micropython_minimal FROZEN_DIR= FROZEN_MPY_DIR= \ - MICROPY_PY_BTREE=0 MICROPY_PY_FFI=0 MICROPY_PY_SOCKET=0 MICROPY_PY_THREAD=0 \ - MICROPY_PY_TERMIOS=0 MICROPY_PY_USSL=0 \ - MICROPY_USE_READLINE=0 - -# build interpreter with nan-boxing as object model -nanbox: - $(MAKE) \ - CFLAGS_EXTRA='-DMP_CONFIGFILE="<mpconfigport_nanbox.h>"' \ - BUILD=build-nanbox \ - PROG=micropython_nanbox \ - MICROPY_FORCE_32BIT=1 \ - MICROPY_PY_USSL=0 - -freedos: - $(MAKE) \ - CC=i586-pc-msdosdjgpp-gcc \ - STRIP=i586-pc-msdosdjgpp-strip \ - SIZE=i586-pc-msdosdjgpp-size \ - CFLAGS_EXTRA='-DMP_CONFIGFILE="<mpconfigport_freedos.h>" -DMICROPY_NLR_SETJMP -Dtgamma=gamma -DMICROPY_EMIT_X86=0 -DMICROPY_NO_ALLOCA=1 -DMICROPY_PY_USELECT_POSIX=0' \ - BUILD=build-freedos \ - PROG=micropython_freedos \ - MICROPY_PY_SOCKET=0 \ - MICROPY_PY_FFI=0 \ - MICROPY_PY_JNI=0 \ - MICROPY_PY_BTREE=0 \ - MICROPY_PY_THREAD=0 \ - MICROPY_PY_USSL=0 - -# build an interpreter for coverage testing and do the testing -coverage: - $(MAKE) \ - COPT="-O0" CFLAGS_EXTRA='-DMP_CONFIGFILE="<mpconfigport_coverage.h>" \ - -fprofile-arcs -ftest-coverage \ - -Wdouble-promotion -Wformat -Wmissing-declarations -Wmissing-prototypes -Wsign-compare \ - -Wold-style-definition -Wpointer-arith -Wshadow -Wuninitialized -Wunused-parameter \ - -DMICROPY_UNIX_COVERAGE' \ - LDFLAGS_EXTRA='-fprofile-arcs -ftest-coverage' \ - FROZEN_DIR=coverage-frzstr FROZEN_MPY_DIR=coverage-frzmpy \ - BUILD=build-coverage PROG=micropython_coverage - -coverage_test: coverage - $(eval DIRNAME=$(notdir $(CURDIR))) - cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/micropython_coverage ./run-tests - cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/micropython_coverage ./run-tests -d thread - cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/micropython_coverage ./run-tests --emit native - cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/micropython_coverage ./run-tests --via-mpy -d basics float - gcov -o build-coverage/py $(TOP)/py/*.c - gcov -o build-coverage/extmod $(TOP)/extmod/*.c - -# Value of configure's --host= option (required for cross-compilation). -# Deduce it from CROSS_COMPILE by default, but can be overridden. -ifneq ($(CROSS_COMPILE),) -CROSS_COMPILE_HOST = --host=$(patsubst %-,%,$(CROSS_COMPILE)) -else -CROSS_COMPILE_HOST = -endif - -deplibs: libffi axtls - -# install-exec-recursive & install-data-am targets are used to avoid building -# docs and depending on makeinfo -libffi: - cd $(TOP)/lib/libffi; git clean -d -x -f - cd $(TOP)/lib/libffi; ./autogen.sh - mkdir -p $(TOP)/lib/libffi/build_dir; cd $(TOP)/lib/libffi/build_dir; \ - ../configure $(CROSS_COMPILE_HOST) --prefix=$$PWD/out --disable-structs CC="$(CC)" CXX="$(CXX)" LD="$(LD)" CFLAGS="-Os -fomit-frame-pointer -fstrict-aliasing -ffast-math -fno-exceptions"; \ - $(MAKE) install-exec-recursive; $(MAKE) -C include install-data-am - -axtls: $(BUILD)/libaxtls.a - -$(BUILD)/libaxtls.a: $(TOP)/lib/axtls/README | $(OBJ_DIRS) - cd $(TOP)/lib/axtls; cp config/upyconfig config/.config - cd $(TOP)/lib/axtls; $(MAKE) oldconfig -B - cd $(TOP)/lib/axtls; $(MAKE) clean - cd $(TOP)/lib/axtls; $(MAKE) all CC="$(CC)" LD="$(LD)" - cp $(TOP)/lib/axtls/_stage/libaxtls.a $@ - -$(TOP)/lib/axtls/README: - @echo "You cloned without --recursive, fetching submodules for you." - (cd $(TOP); git submodule update --init --recursive) diff --git a/unix/alloc.c b/unix/alloc.c deleted file mode 100644 index ca12d025b6..0000000000 --- a/unix/alloc.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2014 Fabian Vogt - * - * 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 <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <sys/mman.h> - -#include "py/mpstate.h" -#include "py/gc.h" - -#if MICROPY_EMIT_NATIVE || (MICROPY_PY_FFI && MICROPY_FORCE_PLAT_ALLOC_EXEC) - -#if defined(__OpenBSD__) || defined(__MACH__) -#define MAP_ANONYMOUS MAP_ANON -#endif - -// The memory allocated here is not on the GC heap (and it may contain pointers -// that need to be GC'd) so we must somehow trace this memory. We do it by -// keeping a linked list of all mmap'd regions, and tracing them explicitly. - -typedef struct _mmap_region_t { - void *ptr; - size_t len; - struct _mmap_region_t *next; -} mmap_region_t; - -void mp_unix_alloc_exec(size_t min_size, void **ptr, size_t *size) { - // size needs to be a multiple of the page size - *size = (min_size + 0xfff) & (~0xfff); - *ptr = mmap(NULL, *size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - if (*ptr == MAP_FAILED) { - *ptr = NULL; - } - - // add new link to the list of mmap'd regions - mmap_region_t *rg = m_new_obj(mmap_region_t); - rg->ptr = *ptr; - rg->len = min_size; - rg->next = MP_STATE_VM(mmap_region_head); - MP_STATE_VM(mmap_region_head) = rg; -} - -void mp_unix_free_exec(void *ptr, size_t size) { - munmap(ptr, size); - - // unlink the mmap'd region from the list - for (mmap_region_t **rg = (mmap_region_t**)&MP_STATE_VM(mmap_region_head); *rg != NULL; *rg = (*rg)->next) { - if ((*rg)->ptr == ptr) { - mmap_region_t *next = (*rg)->next; - m_del_obj(mmap_region_t, *rg); - *rg = next; - return; - } - } -} - -void mp_unix_mark_exec(void) { - for (mmap_region_t *rg = MP_STATE_VM(mmap_region_head); rg != NULL; rg = rg->next) { - gc_collect_root(rg->ptr, rg->len / sizeof(mp_uint_t)); - } -} - -#if MICROPY_FORCE_PLAT_ALLOC_EXEC -// Provide implementation of libffi ffi_closure_* functions in terms -// of the functions above. On a normal Linux system, this save a lot -// of code size. -void *ffi_closure_alloc(size_t size, void **code); -void ffi_closure_free(void *ptr); - -void *ffi_closure_alloc(size_t size, void **code) { - size_t dummy; - mp_unix_alloc_exec(size, code, &dummy); - return *code; -} - -void ffi_closure_free(void *ptr) { - (void)ptr; - // TODO -} -#endif - -#endif // MICROPY_EMIT_NATIVE || (MICROPY_PY_FFI && MICROPY_FORCE_PLAT_ALLOC_EXEC) diff --git a/unix/coverage-frzmpy/frzmpy1.py b/unix/coverage-frzmpy/frzmpy1.py deleted file mode 100644 index 8ad0f15730..0000000000 --- a/unix/coverage-frzmpy/frzmpy1.py +++ /dev/null @@ -1 +0,0 @@ -print('frzmpy1') diff --git a/unix/coverage-frzmpy/frzmpy2.py b/unix/coverage-frzmpy/frzmpy2.py deleted file mode 100644 index 1ad930db2b..0000000000 --- a/unix/coverage-frzmpy/frzmpy2.py +++ /dev/null @@ -1 +0,0 @@ -raise ZeroDivisionError diff --git a/unix/coverage-frzmpy/frzmpy_pkg1/__init__.py b/unix/coverage-frzmpy/frzmpy_pkg1/__init__.py deleted file mode 100644 index 8c023afeba..0000000000 --- a/unix/coverage-frzmpy/frzmpy_pkg1/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# test frozen package with __init__.py -print('frzmpy_pkg1.__init__') -x = 1 diff --git a/unix/coverage-frzmpy/frzmpy_pkg2/mod.py b/unix/coverage-frzmpy/frzmpy_pkg2/mod.py deleted file mode 100644 index a66b505bf6..0000000000 --- a/unix/coverage-frzmpy/frzmpy_pkg2/mod.py +++ /dev/null @@ -1,4 +0,0 @@ -# test frozen package without __init__.py -print('frzmpy_pkg2.mod') -class Foo: - x = 1 diff --git a/unix/coverage-frzstr/frzstr1.py b/unix/coverage-frzstr/frzstr1.py deleted file mode 100644 index 6e88ac38d2..0000000000 --- a/unix/coverage-frzstr/frzstr1.py +++ /dev/null @@ -1 +0,0 @@ -print('frzstr1') diff --git a/unix/coverage-frzstr/frzstr_pkg1/__init__.py b/unix/coverage-frzstr/frzstr_pkg1/__init__.py deleted file mode 100644 index 1d1df9417e..0000000000 --- a/unix/coverage-frzstr/frzstr_pkg1/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# test frozen package with __init__.py -print('frzstr_pkg1.__init__') -x = 1 diff --git a/unix/coverage-frzstr/frzstr_pkg2/mod.py b/unix/coverage-frzstr/frzstr_pkg2/mod.py deleted file mode 100644 index bafb5978b0..0000000000 --- a/unix/coverage-frzstr/frzstr_pkg2/mod.py +++ /dev/null @@ -1,4 +0,0 @@ -# test frozen package without __init__.py -print('frzstr_pkg2.mod') -class Foo: - x = 1 diff --git a/unix/coverage.c b/unix/coverage.c deleted file mode 100644 index 4a9ab194bb..0000000000 --- a/unix/coverage.c +++ /dev/null @@ -1,340 +0,0 @@ -#include <stdio.h> -#include <string.h> - -#include "py/obj.h" -#include "py/objstr.h" -#include "py/runtime.h" -#include "py/repl.h" -#include "py/mpz.h" -#include "py/builtin.h" -#include "py/emit.h" -#include "py/formatfloat.h" -#include "py/stream.h" -#include "py/binary.h" - -#if defined(MICROPY_UNIX_COVERAGE) - -// stream testing object -typedef struct _mp_obj_streamtest_t { - mp_obj_base_t base; - uint8_t *buf; - size_t len; - size_t pos; - int error_code; -} mp_obj_streamtest_t; - -STATIC mp_obj_t stest_set_buf(mp_obj_t o_in, mp_obj_t buf_in) { - mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in); - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); - o->buf = m_new(uint8_t, bufinfo.len); - memcpy(o->buf, bufinfo.buf, bufinfo.len); - o->len = bufinfo.len; - o->pos = 0; - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(stest_set_buf_obj, stest_set_buf); - -STATIC mp_obj_t stest_set_error(mp_obj_t o_in, mp_obj_t err_in) { - mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in); - o->error_code = mp_obj_get_int(err_in); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(stest_set_error_obj, stest_set_error); - -STATIC mp_uint_t stest_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { - mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in); - if (o->pos < o->len) { - if (size > o->len - o->pos) { - size = o->len - o->pos; - } - memcpy(buf, o->buf + o->pos, size); - o->pos += size; - return size; - } else if (o->error_code == 0) { - return 0; - } else { - *errcode = o->error_code; - return MP_STREAM_ERROR; - } -} - -STATIC mp_uint_t stest_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { - mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in); - (void)buf; - (void)size; - *errcode = o->error_code; - return MP_STREAM_ERROR; -} - -STATIC mp_uint_t stest_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) { - mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in); - (void)arg; - (void)request; - (void)errcode; - if (o->error_code != 0) { - *errcode = o->error_code; - return MP_STREAM_ERROR; - } - return 0; -} - -STATIC const mp_rom_map_elem_t rawfile_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_set_buf), MP_ROM_PTR(&stest_set_buf_obj) }, - { MP_ROM_QSTR(MP_QSTR_set_error), MP_ROM_PTR(&stest_set_error_obj) }, - { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, - { MP_ROM_QSTR(MP_QSTR_read1), MP_ROM_PTR(&mp_stream_read1_obj) }, - { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, - { MP_ROM_QSTR(MP_QSTR_write1), MP_ROM_PTR(&mp_stream_write1_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_ioctl), MP_ROM_PTR(&mp_stream_ioctl_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table); - -STATIC const mp_stream_p_t fileio_stream_p = { - .read = stest_read, - .write = stest_write, - .ioctl = stest_ioctl, -}; - -STATIC const mp_obj_type_t mp_type_stest_fileio = { - { &mp_type_type }, - .protocol = &fileio_stream_p, - .locals_dict = (mp_obj_dict_t*)&rawfile_locals_dict, -}; - -// stream read returns non-blocking error -STATIC mp_uint_t stest_read2(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { - (void)o_in; - (void)buf; - (void)size; - *errcode = MP_EAGAIN; - return MP_STREAM_ERROR; -} - -STATIC const mp_rom_map_elem_t rawfile_locals_dict_table2[] = { - { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, - { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict2, rawfile_locals_dict_table2); - -STATIC const mp_stream_p_t textio_stream_p2 = { - .read = stest_read2, - .write = NULL, - .is_text = true, -}; - -STATIC const mp_obj_type_t mp_type_stest_textio2 = { - { &mp_type_type }, - .protocol = &textio_stream_p2, - .locals_dict = (mp_obj_dict_t*)&rawfile_locals_dict2, -}; - -// str/bytes objects without a valid hash -STATIC const mp_obj_str_t str_no_hash_obj = {{&mp_type_str}, 0, 10, (const byte*)"0123456789"}; -STATIC const mp_obj_str_t bytes_no_hash_obj = {{&mp_type_bytes}, 0, 10, (const byte*)"0123456789"}; - -// function to run extra tests for things that can't be checked by scripts -STATIC mp_obj_t extra_coverage(void) { - // mp_printf (used by ports that don't have a native printf) - { - mp_printf(&mp_plat_print, "# mp_printf\n"); - mp_printf(&mp_plat_print, "%d %+d % d\n", -123, 123, 123); // sign - mp_printf(&mp_plat_print, "%05d\n", -123); // negative number with zero padding - mp_printf(&mp_plat_print, "%ld\n", 123); // long - mp_printf(&mp_plat_print, "%X\n", 0x1abcdef); // capital hex - mp_printf(&mp_plat_print, "%.2s %.3s\n", "abc", "abc"); // fixed string precision - mp_printf(&mp_plat_print, "%.*s\n", -1, "abc"); // negative string precision - mp_printf(&mp_plat_print, "%b %b\n", 0, 1); // bools - mp_printf(&mp_plat_print, "%s\n", NULL); // null string - mp_printf(&mp_plat_print, "%d\n", 0x80000000); // should print signed - mp_printf(&mp_plat_print, "%u\n", 0x80000000); // should print unsigned - mp_printf(&mp_plat_print, "%x\n", 0x80000000); // should print unsigned - mp_printf(&mp_plat_print, "%X\n", 0x80000000); // should print unsigned - mp_printf(&mp_plat_print, "abc\n%"); // string ends in middle of format specifier - } - - // vstr - { - mp_printf(&mp_plat_print, "# vstr\n"); - vstr_t *vstr = vstr_new(16); - vstr_hint_size(vstr, 32); - vstr_add_str(vstr, "ts"); - vstr_ins_byte(vstr, 1, 'e'); - vstr_ins_char(vstr, 3, 't'); - vstr_ins_char(vstr, 10, 's'); - mp_printf(&mp_plat_print, "%.*s\n", (int)vstr->len, vstr->buf); - - vstr_cut_head_bytes(vstr, 2); - mp_printf(&mp_plat_print, "%.*s\n", (int)vstr->len, vstr->buf); - - vstr_cut_tail_bytes(vstr, 10); - mp_printf(&mp_plat_print, "%.*s\n", (int)vstr->len, vstr->buf); - - vstr_printf(vstr, "t%cst", 'e'); - mp_printf(&mp_plat_print, "%.*s\n", (int)vstr->len, vstr->buf); - - vstr_cut_out_bytes(vstr, 3, 10); - mp_printf(&mp_plat_print, "%.*s\n", (int)vstr->len, vstr->buf); - - VSTR_FIXED(fix, 4); - vstr_add_str(&fix, "large"); - mp_printf(&mp_plat_print, "%.*s\n", (int)fix.len, fix.buf); - } - - // repl autocomplete - { - mp_printf(&mp_plat_print, "# repl\n"); - - const char *str; - size_t len = mp_repl_autocomplete("__n", 3, &mp_plat_print, &str); - mp_printf(&mp_plat_print, "%.*s\n", (int)len, str); - - mp_store_global(MP_QSTR_sys, mp_import_name(MP_QSTR_sys, mp_const_none, MP_OBJ_NEW_SMALL_INT(0))); - mp_repl_autocomplete("sys.", 4, &mp_plat_print, &str); - len = mp_repl_autocomplete("sys.impl", 8, &mp_plat_print, &str); - mp_printf(&mp_plat_print, "%.*s\n", (int)len, str); - } - - // attrtuple - { - mp_printf(&mp_plat_print, "# attrtuple\n"); - - static const qstr fields[] = {MP_QSTR_start, MP_QSTR_stop, MP_QSTR_step}; - static const mp_obj_t items[] = {MP_OBJ_NEW_SMALL_INT(1), MP_OBJ_NEW_SMALL_INT(2), MP_OBJ_NEW_SMALL_INT(3)}; - mp_obj_print_helper(&mp_plat_print, mp_obj_new_attrtuple(fields, 3, items), PRINT_REPR); - mp_printf(&mp_plat_print, "\n"); - } - - // str - { - mp_printf(&mp_plat_print, "# str\n"); - - // intern string - mp_printf(&mp_plat_print, "%d\n", MP_OBJ_IS_QSTR(mp_obj_str_intern(mp_obj_new_str("intern me", 9, false)))); - } - - // mpz - { - mp_printf(&mp_plat_print, "# mpz\n"); - - mp_uint_t value; - mpz_t mpz; - mpz_init_zero(&mpz); - - // mpz_as_uint_checked, with success - mpz_set_from_int(&mpz, 12345678); - mp_printf(&mp_plat_print, "%d\n", mpz_as_uint_checked(&mpz, &value)); - mp_printf(&mp_plat_print, "%d\n", (int)value); - - // mpz_as_uint_checked, with negative arg - mpz_set_from_int(&mpz, -1); - mp_printf(&mp_plat_print, "%d\n", mpz_as_uint_checked(&mpz, &value)); - - // mpz_as_uint_checked, with overflowing arg - mpz_set_from_int(&mpz, 1); - mpz_shl_inpl(&mpz, &mpz, 70); - mp_printf(&mp_plat_print, "%d\n", mpz_as_uint_checked(&mpz, &value)); - } - - // runtime utils - { - mp_printf(&mp_plat_print, "# runtime utils\n"); - - // call mp_call_function_1_protected - mp_call_function_1_protected(MP_OBJ_FROM_PTR(&mp_builtin_abs_obj), MP_OBJ_NEW_SMALL_INT(1)); - // call mp_call_function_1_protected with invalid args - mp_call_function_1_protected(MP_OBJ_FROM_PTR(&mp_builtin_abs_obj), mp_obj_new_str("abc", 3, false)); - - // call mp_call_function_2_protected - mp_call_function_2_protected(MP_OBJ_FROM_PTR(&mp_builtin_divmod_obj), MP_OBJ_NEW_SMALL_INT(1), MP_OBJ_NEW_SMALL_INT(1)); - // call mp_call_function_2_protected with invalid args - mp_call_function_2_protected(MP_OBJ_FROM_PTR(&mp_builtin_divmod_obj), mp_obj_new_str("abc", 3, false), mp_obj_new_str("abc", 3, false)); - } - - // warning - { - mp_emitter_warning(MP_PASS_CODE_SIZE, "test"); - } - - // format float - { - mp_printf(&mp_plat_print, "# format float\n"); - - // format with inadequate buffer size - char buf[5]; - mp_format_float(1, buf, sizeof(buf), 'g', 0, '+'); - mp_printf(&mp_plat_print, "%s\n", buf); - - // format with just enough buffer so that precision must be - // set from 0 to 1 twice - char buf2[8]; - mp_format_float(1, buf2, sizeof(buf2), 'g', 0, '+'); - mp_printf(&mp_plat_print, "%s\n", buf2); - - // format where precision is trimmed to avoid buffer overflow - mp_format_float(1, buf2, sizeof(buf2), 'e', 0, '+'); - mp_printf(&mp_plat_print, "%s\n", buf2); - } - - // binary - { - mp_printf(&mp_plat_print, "# binary\n"); - - // call function with float and double typecodes - float far[1]; - double dar[1]; - mp_binary_set_val_array_from_int('f', far, 0, 123); - mp_printf(&mp_plat_print, "%.0f\n", (double)far[0]); - mp_binary_set_val_array_from_int('d', dar, 0, 456); - mp_printf(&mp_plat_print, "%.0lf\n", dar[0]); - } - - // scheduler - { - mp_printf(&mp_plat_print, "# scheduler\n"); - - // lock scheduler - mp_sched_lock(); - - // schedule multiple callbacks; last one should fail - for (int i = 0; i < 5; ++i) { - mp_printf(&mp_plat_print, "sched(%d)=%d\n", i, mp_sched_schedule(MP_OBJ_FROM_PTR(&mp_builtin_print_obj), MP_OBJ_NEW_SMALL_INT(i))); - } - - // test nested locking/unlocking - mp_sched_lock(); - mp_sched_unlock(); - - // shouldn't do anything while scheduler is locked - mp_handle_pending(); - - // unlock scheduler - mp_sched_unlock(); - mp_printf(&mp_plat_print, "unlocked\n"); - - // drain pending callbacks - while (mp_sched_num_pending()) { - mp_handle_pending(); - } - } - - mp_obj_streamtest_t *s = m_new_obj(mp_obj_streamtest_t); - s->base.type = &mp_type_stest_fileio; - s->buf = NULL; - s->len = 0; - s->pos = 0; - s->error_code = 0; - mp_obj_streamtest_t *s2 = m_new_obj(mp_obj_streamtest_t); - s2->base.type = &mp_type_stest_textio2; - - // return a tuple of data for testing on the Python side - mp_obj_t items[] = {(mp_obj_t)&str_no_hash_obj, (mp_obj_t)&bytes_no_hash_obj, MP_OBJ_FROM_PTR(s), MP_OBJ_FROM_PTR(s2)}; - return mp_obj_new_tuple(MP_ARRAY_SIZE(items), items); -} -MP_DEFINE_CONST_FUN_OBJ_0(extra_coverage_obj, extra_coverage); - -#endif diff --git a/unix/fatfs_port.c b/unix/fatfs_port.c deleted file mode 100644 index 30f1959f52..0000000000 --- a/unix/fatfs_port.c +++ /dev/null @@ -1,5 +0,0 @@ -#include "lib/oofatfs/ff.h" - -DWORD get_fattime(void) { - return 0; -} diff --git a/unix/fdfile.h b/unix/fdfile.h deleted file mode 100644 index 69a9b6be41..0000000000 --- a/unix/fdfile.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014 Damien P. George - * Copyright (c) 2016 Paul Sokolovsky - * - * 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. - */ -#ifndef MICROPY_INCLUDED_UNIX_FDFILE_H -#define MICROPY_INCLUDED_UNIX_FDFILE_H - -#include "py/obj.h" - -typedef struct _mp_obj_fdfile_t { - mp_obj_base_t base; - int fd; -} mp_obj_fdfile_t; - -extern const mp_obj_type_t mp_type_fileio; -extern const mp_obj_type_t mp_type_textio; - -#endif // MICROPY_INCLUDED_UNIX_FDFILE_H diff --git a/unix/file.c b/unix/file.c deleted file mode 100644 index 0d65f9ca0d..0000000000 --- a/unix/file.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * 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 <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/stat.h> -#include <sys/types.h> - -#include "py/nlr.h" -#include "py/runtime.h" -#include "py/stream.h" -#include "py/builtin.h" -#include "py/mphal.h" -#include "fdfile.h" - -#if MICROPY_PY_IO - -#ifdef _WIN32 -#define fsync _commit -#endif - -#ifdef MICROPY_CPYTHON_COMPAT -STATIC void check_fd_is_open(const mp_obj_fdfile_t *o) { - if (o->fd < 0) { - mp_raise_ValueError("I/O operation on closed file"); - } -} -#else -#define check_fd_is_open(o) -#endif - -extern const mp_obj_type_t mp_type_fileio; -extern const mp_obj_type_t mp_type_textio; - -STATIC void fdfile_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - (void)kind; - mp_obj_fdfile_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "<io.%s %d>", mp_obj_get_type_str(self_in), self->fd); -} - -STATIC mp_uint_t fdfile_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { - mp_obj_fdfile_t *o = MP_OBJ_TO_PTR(o_in); - check_fd_is_open(o); - mp_int_t r = read(o->fd, buf, size); - if (r == -1) { - *errcode = errno; - return MP_STREAM_ERROR; - } - return r; -} - -STATIC mp_uint_t fdfile_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { - mp_obj_fdfile_t *o = MP_OBJ_TO_PTR(o_in); - check_fd_is_open(o); - #if MICROPY_PY_OS_DUPTERM - if (o->fd <= STDERR_FILENO) { - mp_hal_stdout_tx_strn(buf, size); - return size; - } - #endif - mp_int_t r = write(o->fd, buf, size); - while (r == -1 && errno == EINTR) { - if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) { - mp_obj_t obj = MP_STATE_VM(mp_pending_exception); - MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; - nlr_raise(obj); - } - r = write(o->fd, buf, size); - } - if (r == -1) { - *errcode = errno; - return MP_STREAM_ERROR; - } - return r; -} - -STATIC mp_uint_t fdfile_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) { - mp_obj_fdfile_t *o = MP_OBJ_TO_PTR(o_in); - check_fd_is_open(o); - switch (request) { - case MP_STREAM_SEEK: { - struct mp_stream_seek_t *s = (struct mp_stream_seek_t*)arg; - off_t off = lseek(o->fd, s->offset, s->whence); - if (off == (off_t)-1) { - *errcode = errno; - return MP_STREAM_ERROR; - } - s->offset = off; - return 0; - } - case MP_STREAM_FLUSH: - if (fsync(o->fd) < 0) { - *errcode = errno; - return MP_STREAM_ERROR; - } - return 0; - default: - *errcode = EINVAL; - return MP_STREAM_ERROR; - } -} - -STATIC mp_obj_t fdfile_close(mp_obj_t self_in) { - mp_obj_fdfile_t *self = MP_OBJ_TO_PTR(self_in); - close(self->fd); -#ifdef MICROPY_CPYTHON_COMPAT - self->fd = -1; -#endif - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(fdfile_close_obj, fdfile_close); - -STATIC mp_obj_t fdfile___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - return fdfile_close(args[0]); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fdfile___exit___obj, 4, 4, fdfile___exit__); - -STATIC mp_obj_t fdfile_fileno(mp_obj_t self_in) { - mp_obj_fdfile_t *self = MP_OBJ_TO_PTR(self_in); - check_fd_is_open(self); - return MP_OBJ_NEW_SMALL_INT(self->fd); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(fdfile_fileno_obj, fdfile_fileno); - -// 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_buffering, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, - { MP_QSTR_encoding, MP_ARG_OBJ, {.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 fdfile_open(const mp_obj_type_t *type, mp_arg_val_t *args) { - mp_obj_fdfile_t *o = m_new_obj(mp_obj_fdfile_t); - const char *mode_s = mp_obj_str_get_str(args[1].u_obj); - - int mode_rw = 0, mode_x = 0; - while (*mode_s) { - switch (*mode_s++) { - case 'r': - mode_rw = O_RDONLY; - break; - case 'w': - mode_rw = O_WRONLY; - mode_x = O_CREAT | O_TRUNC; - break; - case 'a': - mode_rw = O_WRONLY; - mode_x = O_CREAT | O_APPEND; - break; - case '+': - mode_rw = O_RDWR; - break; - #if MICROPY_PY_IO_FILEIO - // If we don't have io.FileIO, then files are in text mode implicitly - case 'b': - type = &mp_type_fileio; - break; - case 't': - type = &mp_type_textio; - break; - #endif - } - } - - o->base.type = type; - - mp_obj_t fid = args[0].u_obj; - - if (MP_OBJ_IS_SMALL_INT(fid)) { - o->fd = MP_OBJ_SMALL_INT_VALUE(fid); - return MP_OBJ_FROM_PTR(o); - } - - const char *fname = mp_obj_str_get_str(fid); - int fd = open(fname, mode_x | mode_rw, 0644); - if (fd == -1) { - mp_raise_OSError(errno); - } - o->fd = fd; - return MP_OBJ_FROM_PTR(o); -} - -STATIC mp_obj_t fdfile_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 fdfile_open(type, arg_vals); -} - -STATIC const mp_rom_map_elem_t rawfile_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_fileno), MP_ROM_PTR(&fdfile_fileno_obj) }, - { 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_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_flush), MP_ROM_PTR(&mp_stream_flush_obj) }, - { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&fdfile_close_obj) }, - { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&fdfile___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 = fdfile_read, - .write = fdfile_write, - .ioctl = fdfile_ioctl, -}; - -const mp_obj_type_t mp_type_fileio = { - { &mp_type_type }, - .name = MP_QSTR_FileIO, - .print = fdfile_print, - .make_new = fdfile_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 = fdfile_read, - .write = fdfile_write, - .ioctl = fdfile_ioctl, - .is_text = true, -}; - -const mp_obj_type_t mp_type_textio = { - { &mp_type_type }, - .name = MP_QSTR_TextIOWrapper, - .print = fdfile_print, - .make_new = fdfile_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 fdfile_open(&mp_type_textio, arg_vals); -} -MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); - -const mp_obj_fdfile_t mp_sys_stdin_obj = { .base = {&mp_type_textio}, .fd = STDIN_FILENO }; -const mp_obj_fdfile_t mp_sys_stdout_obj = { .base = {&mp_type_textio}, .fd = STDOUT_FILENO }; -const mp_obj_fdfile_t mp_sys_stderr_obj = { .base = {&mp_type_textio}, .fd = STDERR_FILENO }; - -#endif // MICROPY_PY_IO diff --git a/unix/gccollect.c b/unix/gccollect.c deleted file mode 100644 index 02f6fc91a8..0000000000 --- a/unix/gccollect.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * 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/mpstate.h" -#include "py/gc.h" - -#if MICROPY_ENABLE_GC - -// Even if we have specific support for an architecture, it is -// possible to force use of setjmp-based implementation. -#if !MICROPY_GCREGS_SETJMP - -// We capture here callee-save registers, i.e. ones which may contain -// interesting values held there by our callers. It doesn't make sense -// to capture caller-saved registers, because they, well, put on the -// stack already by the caller. -#if defined(__x86_64__) -typedef mp_uint_t regs_t[6]; - -STATIC void gc_helper_get_regs(regs_t arr) { - register long rbx asm ("rbx"); - register long rbp asm ("rbp"); - register long r12 asm ("r12"); - register long r13 asm ("r13"); - register long r14 asm ("r14"); - register long r15 asm ("r15"); -#ifdef __clang__ - // TODO: - // This is dirty workaround for Clang. It tries to get around - // uncompliant (wrt to GCC) behavior of handling register variables. - // Application of this patch here is random, and done only to unbreak - // MacOS build. Better, cross-arch ways to deal with Clang issues should - // be found. - asm("" : "=r"(rbx)); - asm("" : "=r"(rbp)); - asm("" : "=r"(r12)); - asm("" : "=r"(r13)); - asm("" : "=r"(r14)); - asm("" : "=r"(r15)); -#endif - arr[0] = rbx; - arr[1] = rbp; - arr[2] = r12; - arr[3] = r13; - arr[4] = r14; - arr[5] = r15; -} - -#elif defined(__i386__) - -typedef mp_uint_t regs_t[4]; - -STATIC void gc_helper_get_regs(regs_t arr) { - register long ebx asm ("ebx"); - register long esi asm ("esi"); - register long edi asm ("edi"); - register long ebp asm ("ebp"); -#ifdef __clang__ - // TODO: - // This is dirty workaround for Clang. It tries to get around - // uncompliant (wrt to GCC) behavior of handling register variables. - // Application of this patch here is random, and done only to unbreak - // MacOS build. Better, cross-arch ways to deal with Clang issues should - // be found. - asm("" : "=r"(ebx)); - asm("" : "=r"(esi)); - asm("" : "=r"(edi)); - asm("" : "=r"(ebp)); -#endif - arr[0] = ebx; - arr[1] = esi; - arr[2] = edi; - arr[3] = ebp; -} - -#elif defined(__thumb2__) || defined(__thumb__) || defined(__arm__) - -typedef mp_uint_t regs_t[10]; - -STATIC void gc_helper_get_regs(regs_t arr) { - register long r4 asm ("r4"); - register long r5 asm ("r5"); - register long r6 asm ("r6"); - register long r7 asm ("r7"); - register long r8 asm ("r8"); - register long r9 asm ("r9"); - register long r10 asm ("r10"); - register long r11 asm ("r11"); - register long r12 asm ("r12"); - register long r13 asm ("r13"); - arr[0] = r4; - arr[1] = r5; - arr[2] = r6; - arr[3] = r7; - arr[4] = r8; - arr[5] = r9; - arr[6] = r10; - arr[7] = r11; - arr[8] = r12; - arr[9] = r13; -} - -#else - -// If we don't have architecture-specific optimized support, -// just fall back to setjmp-based implementation. -#undef MICROPY_GCREGS_SETJMP -#define MICROPY_GCREGS_SETJMP (1) - -#endif // Arch-specific selection -#endif // !MICROPY_GCREGS_SETJMP - -// If MICROPY_GCREGS_SETJMP was requested explicitly, or if -// we enabled it as a fallback above. -#if MICROPY_GCREGS_SETJMP -#include <setjmp.h> - -typedef jmp_buf regs_t; - -STATIC void gc_helper_get_regs(regs_t arr) { - setjmp(arr); -} - -#endif // MICROPY_GCREGS_SETJMP - -// this function is used by mpthreadport.c -void gc_collect_regs_and_stack(void); - -void gc_collect_regs_and_stack(void) { - regs_t regs; - gc_helper_get_regs(regs); - // GC stack (and regs because we captured them) - void **regs_ptr = (void**)(void*)®s; - gc_collect_root(regs_ptr, ((uintptr_t)MP_STATE_THREAD(stack_top) - (uintptr_t)®s) / sizeof(uintptr_t)); -} - -void gc_collect(void) { - //gc_dump_info(); - - gc_collect_start(); - gc_collect_regs_and_stack(); - #if MICROPY_PY_THREAD - mp_thread_gc_others(); - #endif - #if MICROPY_EMIT_NATIVE - mp_unix_mark_exec(); - #endif - gc_collect_end(); - - //printf("-----\n"); - //gc_dump_info(); -} - -#endif //MICROPY_ENABLE_GC diff --git a/unix/input.c b/unix/input.c deleted file mode 100644 index 7d60b46cc7..0000000000 --- a/unix/input.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * 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 <stdlib.h> -#include <string.h> -#include <fcntl.h> - -#include "py/mpstate.h" -#include "py/mphal.h" -#include "input.h" - -#if MICROPY_USE_READLINE == 1 -#include "lib/mp-readline/readline.h" -#endif - -#if MICROPY_USE_READLINE == 0 -char *prompt(char *p) { - // simple read string - static char buf[256]; - fputs(p, stdout); - char *s = fgets(buf, sizeof(buf), stdin); - if (!s) { - return NULL; - } - int l = strlen(buf); - if (buf[l - 1] == '\n') { - buf[l - 1] = 0; - } else { - l++; - } - char *line = malloc(l); - memcpy(line, buf, l); - return line; -} -#endif - -void prompt_read_history(void) { -#if MICROPY_USE_READLINE_HISTORY - #if MICROPY_USE_READLINE == 1 - readline_init0(); // will clear history pointers - char *home = getenv("HOME"); - if (home != NULL) { - vstr_t vstr; - vstr_init(&vstr, 50); - vstr_printf(&vstr, "%s/.micropython.history", home); - int fd = open(vstr_null_terminated_str(&vstr), O_RDONLY); - if (fd != -1) { - vstr_reset(&vstr); - for (;;) { - char c; - int sz = read(fd, &c, 1); - if (sz < 0) { - break; - } - if (sz == 0 || c == '\n') { - readline_push_history(vstr_null_terminated_str(&vstr)); - if (sz == 0) { - break; - } - vstr_reset(&vstr); - } else { - vstr_add_byte(&vstr, c); - } - } - close(fd); - } - vstr_clear(&vstr); - } - #endif -#endif -} - -void prompt_write_history(void) { -#if MICROPY_USE_READLINE_HISTORY - #if MICROPY_USE_READLINE == 1 - char *home = getenv("HOME"); - if (home != NULL) { - vstr_t vstr; - vstr_init(&vstr, 50); - vstr_printf(&vstr, "%s/.micropython.history", home); - int fd = open(vstr_null_terminated_str(&vstr), O_CREAT | O_TRUNC | O_WRONLY, 0644); - if (fd != -1) { - for (int i = MP_ARRAY_SIZE(MP_STATE_PORT(readline_hist)) - 1; i >= 0; i--) { - const char *line = MP_STATE_PORT(readline_hist)[i]; - if (line != NULL) { - int res; - res = write(fd, line, strlen(line)); - res = write(fd, "\n", 1); - (void)res; - } - } - close(fd); - } - } - #endif -#endif -} diff --git a/unix/input.h b/unix/input.h deleted file mode 100644 index a76b87e644..0000000000 --- a/unix/input.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef MICROPY_INCLUDED_UNIX_INPUT_H -#define MICROPY_INCLUDED_UNIX_INPUT_H - -char *prompt(char *p); -void prompt_read_history(void); -void prompt_write_history(void); - -#endif // MICROPY_INCLUDED_UNIX_INPUT_H diff --git a/unix/main.c b/unix/main.c deleted file mode 100644 index e861d7f112..0000000000 --- a/unix/main.c +++ /dev/null @@ -1,660 +0,0 @@ -/* - * 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 <stdint.h> -#include <stdbool.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <stdarg.h> -#include <unistd.h> -#include <ctype.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <errno.h> -#include <signal.h> - -#include "py/mpstate.h" -#include "py/nlr.h" -#include "py/compile.h" -#include "py/runtime.h" -#include "py/builtin.h" -#include "py/repl.h" -#include "py/gc.h" -#include "py/stackctrl.h" -#include "py/mphal.h" -#include "py/mpthread.h" -#include "extmod/misc.h" -#include "genhdr/mpversion.h" -#include "input.h" - -// Command line options, with their defaults -STATIC bool compile_only = false; -STATIC uint emit_opt = MP_EMIT_OPT_NONE; - -#if MICROPY_ENABLE_GC -// Heap size of GC heap (if enabled) -// Make it larger on a 64 bit machine, because pointers are larger. -long heap_size = 1024*1024 * (sizeof(mp_uint_t) / 4); -#endif - -STATIC void stderr_print_strn(void *env, const char *str, size_t len) { - (void)env; - ssize_t dummy = write(STDERR_FILENO, str, len); - mp_uos_dupterm_tx_strn(str, len); - (void)dummy; -} - -const mp_print_t mp_stderr_print = {NULL, stderr_print_strn}; - -#define FORCED_EXIT (0x100) -// If exc is SystemExit, return value where FORCED_EXIT bit set, -// and lower 8 bits are SystemExit value. For all other exceptions, -// return 1. -STATIC int handle_uncaught_exception(mp_obj_base_t *exc) { - // check for SystemExit - if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(exc->type), MP_OBJ_FROM_PTR(&mp_type_SystemExit))) { - // None is an exit value of 0; an int is its value; anything else is 1 - mp_obj_t exit_val = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(exc)); - mp_int_t val = 0; - if (exit_val != mp_const_none && !mp_obj_get_int_maybe(exit_val, &val)) { - val = 1; - } - return FORCED_EXIT | (val & 255); - } - - // Report all other exceptions - mp_obj_print_exception(&mp_stderr_print, MP_OBJ_FROM_PTR(exc)); - return 1; -} - -#define LEX_SRC_STR (1) -#define LEX_SRC_VSTR (2) -#define LEX_SRC_FILENAME (3) -#define LEX_SRC_STDIN (4) - -// Returns standard error codes: 0 for success, 1 for all other errors, -// except if FORCED_EXIT bit is set then script raised SystemExit and the -// value of the exit is in the lower 8 bits of the return value -STATIC int execute_from_lexer(int source_kind, const void *source, mp_parse_input_kind_t input_kind, bool is_repl) { - mp_hal_set_interrupt_char(CHAR_CTRL_C); - - nlr_buf_t nlr; - if (nlr_push(&nlr) == 0) { - // create lexer based on source kind - mp_lexer_t *lex; - if (source_kind == LEX_SRC_STR) { - const char *line = source; - lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, line, strlen(line), false); - } else if (source_kind == LEX_SRC_VSTR) { - const vstr_t *vstr = source; - lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr->buf, vstr->len, false); - } else if (source_kind == LEX_SRC_FILENAME) { - lex = mp_lexer_new_from_file((const char*)source); - } else { // LEX_SRC_STDIN - lex = mp_lexer_new_from_fd(MP_QSTR__lt_stdin_gt_, 0, false); - } - - qstr source_name = lex->source_name; - - #if MICROPY_PY___FILE__ - if (input_kind == MP_PARSE_FILE_INPUT) { - mp_store_global(MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name)); - } - #endif - - mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); - - #if defined(MICROPY_UNIX_COVERAGE) - // allow to print the parse tree in the coverage build - if (mp_verbose_flag >= 3) { - printf("----------------\n"); - mp_parse_node_print(parse_tree.root, 0); - printf("----------------\n"); - } - #endif - - mp_obj_t module_fun = mp_compile(&parse_tree, source_name, emit_opt, is_repl); - - if (!compile_only) { - // execute it - mp_call_function_0(module_fun); - // check for pending exception - if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) { - mp_obj_t obj = MP_STATE_VM(mp_pending_exception); - MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; - nlr_raise(obj); - } - } - - mp_hal_set_interrupt_char(-1); - nlr_pop(); - return 0; - - } else { - // uncaught exception - mp_hal_set_interrupt_char(-1); - return handle_uncaught_exception(nlr.ret_val); - } -} - -#if MICROPY_USE_READLINE == 1 -#include "lib/mp-readline/readline.h" -#else -STATIC char *strjoin(const char *s1, int sep_char, const char *s2) { - int l1 = strlen(s1); - int l2 = strlen(s2); - char *s = malloc(l1 + l2 + 2); - memcpy(s, s1, l1); - if (sep_char != 0) { - s[l1] = sep_char; - l1 += 1; - } - memcpy(s + l1, s2, l2); - s[l1 + l2] = 0; - return s; -} -#endif - -STATIC int do_repl(void) { - mp_hal_stdout_tx_str("MicroPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " - MICROPY_PY_SYS_PLATFORM " version\nUse Ctrl-D to exit, Ctrl-E for paste mode\n"); - - #if MICROPY_USE_READLINE == 1 - - // use MicroPython supplied readline - - vstr_t line; - vstr_init(&line, 16); - for (;;) { - mp_hal_stdio_mode_raw(); - - input_restart: - vstr_reset(&line); - int ret = readline(&line, ">>> "); - mp_parse_input_kind_t parse_input_kind = MP_PARSE_SINGLE_INPUT; - - if (ret == CHAR_CTRL_C) { - // cancel input - mp_hal_stdout_tx_str("\r\n"); - goto input_restart; - } else if (ret == CHAR_CTRL_D) { - // EOF - printf("\n"); - mp_hal_stdio_mode_orig(); - vstr_clear(&line); - return 0; - } else if (ret == CHAR_CTRL_E) { - // paste mode - mp_hal_stdout_tx_str("\npaste mode; Ctrl-C to cancel, Ctrl-D to finish\n=== "); - vstr_reset(&line); - for (;;) { - char c = mp_hal_stdin_rx_chr(); - if (c == CHAR_CTRL_C) { - // cancel everything - mp_hal_stdout_tx_str("\n"); - goto input_restart; - } else if (c == CHAR_CTRL_D) { - // end of input - mp_hal_stdout_tx_str("\n"); - break; - } else { - // add char to buffer and echo - vstr_add_byte(&line, c); - if (c == '\r') { - mp_hal_stdout_tx_str("\n=== "); - } else { - mp_hal_stdout_tx_strn(&c, 1); - } - } - } - parse_input_kind = MP_PARSE_FILE_INPUT; - } else if (line.len == 0) { - if (ret != 0) { - printf("\n"); - } - goto input_restart; - } else { - // got a line with non-zero length, see if it needs continuing - while (mp_repl_continue_with_input(vstr_null_terminated_str(&line))) { - vstr_add_byte(&line, '\n'); - ret = readline(&line, "... "); - if (ret == CHAR_CTRL_C) { - // cancel everything - printf("\n"); - goto input_restart; - } else if (ret == CHAR_CTRL_D) { - // stop entering compound statement - break; - } - } - } - - mp_hal_stdio_mode_orig(); - - ret = execute_from_lexer(LEX_SRC_VSTR, &line, parse_input_kind, true); - if (ret & FORCED_EXIT) { - return ret; - } - } - - #else - - // use simple readline - - for (;;) { - char *line = prompt(">>> "); - if (line == NULL) { - // EOF - return 0; - } - while (mp_repl_continue_with_input(line)) { - char *line2 = prompt("... "); - if (line2 == NULL) { - break; - } - char *line3 = strjoin(line, '\n', line2); - free(line); - free(line2); - line = line3; - } - - int ret = execute_from_lexer(LEX_SRC_STR, line, MP_PARSE_SINGLE_INPUT, true); - if (ret & FORCED_EXIT) { - return ret; - } - free(line); - } - - #endif -} - -STATIC int do_file(const char *file) { - return execute_from_lexer(LEX_SRC_FILENAME, file, MP_PARSE_FILE_INPUT, false); -} - -STATIC int do_str(const char *str) { - return execute_from_lexer(LEX_SRC_STR, str, MP_PARSE_FILE_INPUT, false); -} - -STATIC int usage(char **argv) { - printf( -"usage: %s [<opts>] [-X <implopt>] [-c <command>] [<filename>]\n" -"Options:\n" -"-v : verbose (trace various operations); can be multiple\n" -"-O[N] : apply bytecode optimizations of level N\n" -"\n" -"Implementation specific options (-X):\n", argv[0] -); - int impl_opts_cnt = 0; - printf( -" compile-only -- parse and compile only\n" -" emit={bytecode,native,viper} -- set the default code emitter\n" -); - impl_opts_cnt++; -#if MICROPY_ENABLE_GC - printf( -" heapsize=<n>[w][K|M] -- set the heap size for the GC (default %ld)\n" -, heap_size); - impl_opts_cnt++; -#endif - - if (impl_opts_cnt == 0) { - printf(" (none)\n"); - } - - return 1; -} - -// Process options which set interpreter init options -STATIC void pre_process_options(int argc, char **argv) { - for (int a = 1; a < argc; a++) { - if (argv[a][0] == '-') { - if (strcmp(argv[a], "-X") == 0) { - if (a + 1 >= argc) { - exit(usage(argv)); - } - if (0) { - } else if (strcmp(argv[a + 1], "compile-only") == 0) { - compile_only = true; - } else if (strcmp(argv[a + 1], "emit=bytecode") == 0) { - emit_opt = MP_EMIT_OPT_BYTECODE; - } else if (strcmp(argv[a + 1], "emit=native") == 0) { - emit_opt = MP_EMIT_OPT_NATIVE_PYTHON; - } else if (strcmp(argv[a + 1], "emit=viper") == 0) { - emit_opt = MP_EMIT_OPT_VIPER; -#if MICROPY_ENABLE_GC - } else if (strncmp(argv[a + 1], "heapsize=", sizeof("heapsize=") - 1) == 0) { - char *end; - heap_size = strtol(argv[a + 1] + sizeof("heapsize=") - 1, &end, 0); - // Don't bring unneeded libc dependencies like tolower() - // If there's 'w' immediately after number, adjust it for - // target word size. Note that it should be *before* size - // suffix like K or M, to avoid confusion with kilowords, - // etc. the size is still in bytes, just can be adjusted - // for word size (taking 32bit as baseline). - bool word_adjust = false; - if ((*end | 0x20) == 'w') { - word_adjust = true; - end++; - } - if ((*end | 0x20) == 'k') { - heap_size *= 1024; - } else if ((*end | 0x20) == 'm') { - heap_size *= 1024 * 1024; - } else { - // Compensate for ++ below - --end; - } - if (*++end != 0) { - goto invalid_arg; - } - if (word_adjust) { - heap_size = heap_size * BYTES_PER_WORD / 4; - } - // If requested size too small, we'll crash anyway - if (heap_size < 700) { - goto invalid_arg; - } -#endif - } else { -invalid_arg: - printf("Invalid option\n"); - exit(usage(argv)); - } - a++; - } - } - } -} - -STATIC void set_sys_argv(char *argv[], int argc, int start_arg) { - for (int i = start_arg; i < argc; i++) { - mp_obj_list_append(mp_sys_argv, MP_OBJ_NEW_QSTR(qstr_from_str(argv[i]))); - } -} - -#ifdef _WIN32 -#define PATHLIST_SEP_CHAR ';' -#else -#define PATHLIST_SEP_CHAR ':' -#endif - -MP_NOINLINE int main_(int argc, char **argv); - -int main(int argc, char **argv) { - #if MICROPY_PY_THREAD - mp_thread_init(); - #endif - // We should capture stack top ASAP after start, and it should be - // captured guaranteedly before any other stack variables are allocated. - // For this, actual main (renamed main_) should not be inlined into - // this function. main_() itself may have other functions inlined (with - // their own stack variables), that's why we need this main/main_ split. - mp_stack_ctrl_init(); - return main_(argc, argv); -} - -MP_NOINLINE int main_(int argc, char **argv) { - #ifdef SIGPIPE - // Do not raise SIGPIPE, instead return EPIPE. Otherwise, e.g. writing - // to peer-closed socket will lead to sudden termination of MicroPython - // process. SIGPIPE is particularly nasty, because unix shell doesn't - // print anything for it, so the above looks like completely sudden and - // silent termination for unknown reason. Ignoring SIGPIPE is also what - // CPython does. Note that this may lead to problems using MicroPython - // scripts as pipe filters, but again, that's what CPython does. So, - // scripts which want to follow unix shell pipe semantics (where SIGPIPE - // means "pipe was requested to terminate, it's not an error"), should - // catch EPIPE themselves. - signal(SIGPIPE, SIG_IGN); - #endif - - mp_stack_set_limit(40000 * (BYTES_PER_WORD / 4)); - - pre_process_options(argc, argv); - -#if MICROPY_ENABLE_GC - char *heap = malloc(heap_size); - gc_init(heap, heap + heap_size); -#endif - - mp_init(); - - char *home = getenv("HOME"); - char *path = getenv("MICROPYPATH"); - if (path == NULL) { - #ifdef MICROPY_PY_SYS_PATH_DEFAULT - path = MICROPY_PY_SYS_PATH_DEFAULT; - #else - path = "~/.micropython/lib:/usr/lib/micropython"; - #endif - } - size_t path_num = 1; // [0] is for current dir (or base dir of the script) - if (*path == ':') { - path_num++; - } - for (char *p = path; p != NULL; p = strchr(p, PATHLIST_SEP_CHAR)) { - path_num++; - if (p != NULL) { - p++; - } - } - mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_path), path_num); - mp_obj_t *path_items; - mp_obj_list_get(mp_sys_path, &path_num, &path_items); - path_items[0] = MP_OBJ_NEW_QSTR(MP_QSTR_); - { - char *p = path; - for (mp_uint_t i = 1; i < path_num; i++) { - char *p1 = strchr(p, PATHLIST_SEP_CHAR); - if (p1 == NULL) { - p1 = p + strlen(p); - } - if (p[0] == '~' && p[1] == '/' && home != NULL) { - // Expand standalone ~ to $HOME - int home_l = strlen(home); - vstr_t vstr; - vstr_init(&vstr, home_l + (p1 - p - 1) + 1); - vstr_add_strn(&vstr, home, home_l); - vstr_add_strn(&vstr, p + 1, p1 - p - 1); - path_items[i] = mp_obj_new_str_from_vstr(&mp_type_str, &vstr); - } else { - path_items[i] = MP_OBJ_NEW_QSTR(qstr_from_strn(p, p1 - p)); - } - p = p1 + 1; - } - } - - mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_argv), 0); - - #if defined(MICROPY_UNIX_COVERAGE) - { - MP_DECLARE_CONST_FUN_OBJ_0(extra_coverage_obj); - mp_store_global(QSTR_FROM_STR_STATIC("extra_coverage"), MP_OBJ_FROM_PTR(&extra_coverage_obj)); - } - #endif - - // Here is some example code to create a class and instance of that class. - // First is the Python, then the C code. - // - // class TestClass: - // pass - // test_obj = TestClass() - // test_obj.attr = 42 - // - // mp_obj_t test_class_type, test_class_instance; - // test_class_type = mp_obj_new_type(QSTR_FROM_STR_STATIC("TestClass"), mp_const_empty_tuple, mp_obj_new_dict(0)); - // mp_store_name(QSTR_FROM_STR_STATIC("test_obj"), test_class_instance = mp_call_function_0(test_class_type)); - // mp_store_attr(test_class_instance, QSTR_FROM_STR_STATIC("attr"), mp_obj_new_int(42)); - - /* - printf("bytes:\n"); - printf(" total %d\n", m_get_total_bytes_allocated()); - printf(" cur %d\n", m_get_current_bytes_allocated()); - printf(" peak %d\n", m_get_peak_bytes_allocated()); - */ - - const int NOTHING_EXECUTED = -2; - int ret = NOTHING_EXECUTED; - bool inspect = false; - for (int a = 1; a < argc; a++) { - if (argv[a][0] == '-') { - if (strcmp(argv[a], "-i") == 0) { - inspect = true; - } else if (strcmp(argv[a], "-c") == 0) { - if (a + 1 >= argc) { - return usage(argv); - } - ret = do_str(argv[a + 1]); - if (ret & FORCED_EXIT) { - break; - } - a += 1; - } else if (strcmp(argv[a], "-m") == 0) { - if (a + 1 >= argc) { - return usage(argv); - } - mp_obj_t import_args[4]; - import_args[0] = mp_obj_new_str(argv[a + 1], strlen(argv[a + 1]), false); - import_args[1] = import_args[2] = mp_const_none; - // Ask __import__ to handle imported module specially - set its __name__ - // to __main__, and also return this leaf module, not top-level package - // containing it. - import_args[3] = mp_const_false; - // TODO: https://docs.python.org/3/using/cmdline.html#cmdoption-m : - // "the first element of sys.argv will be the full path to - // the module file (while the module file is being located, - // the first element will be set to "-m")." - set_sys_argv(argv, argc, a + 1); - - mp_obj_t mod; - nlr_buf_t nlr; - bool subpkg_tried = false; - - reimport: - if (nlr_push(&nlr) == 0) { - mod = mp_builtin___import__(MP_ARRAY_SIZE(import_args), import_args); - nlr_pop(); - } else { - // uncaught exception - return handle_uncaught_exception(nlr.ret_val) & 0xff; - } - - if (mp_obj_is_package(mod) && !subpkg_tried) { - subpkg_tried = true; - vstr_t vstr; - int len = strlen(argv[a + 1]); - vstr_init(&vstr, len + sizeof(".__main__")); - vstr_add_strn(&vstr, argv[a + 1], len); - vstr_add_strn(&vstr, ".__main__", sizeof(".__main__") - 1); - import_args[0] = mp_obj_new_str_from_vstr(&mp_type_str, &vstr); - goto reimport; - } - - ret = 0; - break; - } else if (strcmp(argv[a], "-X") == 0) { - a += 1; - #if MICROPY_DEBUG_PRINTERS - } else if (strcmp(argv[a], "-v") == 0) { - mp_verbose_flag++; - #endif - } else if (strncmp(argv[a], "-O", 2) == 0) { - if (unichar_isdigit(argv[a][2])) { - MP_STATE_VM(mp_optimise_value) = argv[a][2] & 0xf; - } else { - MP_STATE_VM(mp_optimise_value) = 0; - for (char *p = argv[a] + 1; *p && *p == 'O'; p++, MP_STATE_VM(mp_optimise_value)++); - } - } else { - return usage(argv); - } - } else { - char *pathbuf = malloc(PATH_MAX); - char *basedir = realpath(argv[a], pathbuf); - if (basedir == NULL) { - mp_printf(&mp_stderr_print, "%s: can't open file '%s': [Errno %d] %s\n", argv[0], argv[a], errno, strerror(errno)); - // CPython exits with 2 in such case - ret = 2; - break; - } - - // Set base dir of the script as first entry in sys.path - char *p = strrchr(basedir, '/'); - path_items[0] = MP_OBJ_NEW_QSTR(qstr_from_strn(basedir, p - basedir)); - free(pathbuf); - - set_sys_argv(argv, argc, a); - ret = do_file(argv[a]); - break; - } - } - - if (ret == NOTHING_EXECUTED || inspect) { - if (isatty(0)) { - prompt_read_history(); - ret = do_repl(); - prompt_write_history(); - } else { - ret = execute_from_lexer(LEX_SRC_STDIN, NULL, MP_PARSE_FILE_INPUT, false); - } - } - - #if MICROPY_PY_MICROPYTHON_MEM_INFO - if (mp_verbose_flag) { - mp_micropython_mem_info(0, NULL); - } - #endif - - mp_deinit(); - -#if MICROPY_ENABLE_GC && !defined(NDEBUG) - // We don't really need to free memory since we are about to exit the - // process, but doing so helps to find memory leaks. - free(heap); -#endif - - //printf("total bytes = %d\n", m_get_total_bytes_allocated()); - return ret & 0xff; -} - -uint mp_import_stat(const char *path) { - struct stat st; - if (stat(path, &st) == 0) { - if (S_ISDIR(st.st_mode)) { - return MP_IMPORT_STAT_DIR; - } else if (S_ISREG(st.st_mode)) { - return MP_IMPORT_STAT_FILE; - } - } - return MP_IMPORT_STAT_NO_EXIST; -} - -void nlr_jump_fail(void *val) { - printf("FATAL: uncaught NLR %p\n", val); - exit(1); -} diff --git a/unix/modffi.c b/unix/modffi.c deleted file mode 100644 index 9b514371bc..0000000000 --- a/unix/modffi.c +++ /dev/null @@ -1,505 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014 Damien P. George - * Copyright (c) 2014 Paul Sokolovsky - * - * 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 <assert.h> -#include <string.h> -#include <errno.h> -#include <dlfcn.h> -#include <ffi.h> -#include <stdint.h> - -#include "py/nlr.h" -#include "py/runtime.h" -#include "py/binary.h" -#include "py/mperrno.h" - -/* - * modffi uses character codes to encode a value type, based on "struct" - * module type codes, with some extensions and overridings. - * - * Extra/overridden typecodes: - * v - void, can be used only as return type - * P - const void*, pointer to read-only memory - * p - void*, meaning pointer to a writable memory (note that this - * clashes with struct's "p" as "Pascal string"). - * s - as argument, the same as "p", as return value, causes string - * to be allocated and returned, instead of pointer value. - * O - mp_obj_t, passed as is (mostly useful as a callback param) - * - * TODO: - * C - callback function - * - * Note: all constraint specified by typecode can be not enforced at this time, - * but may be later. - */ - -typedef struct _mp_obj_opaque_t { - mp_obj_base_t base; - void *val; -} mp_obj_opaque_t; - -typedef struct _mp_obj_ffimod_t { - mp_obj_base_t base; - void *handle; -} mp_obj_ffimod_t; - -typedef struct _mp_obj_ffivar_t { - mp_obj_base_t base; - void *var; - char type; -// ffi_type *type; -} mp_obj_ffivar_t; - -typedef struct _mp_obj_ffifunc_t { - mp_obj_base_t base; - void *func; - char rettype; - const char *argtypes; - ffi_cif cif; - ffi_type *params[]; -} mp_obj_ffifunc_t; - -typedef struct _mp_obj_fficallback_t { - mp_obj_base_t base; - void *func; - ffi_closure *clo; - char rettype; - ffi_cif cif; - ffi_type *params[]; -} mp_obj_fficallback_t; - -//STATIC const mp_obj_type_t opaque_type; -STATIC const mp_obj_type_t ffimod_type; -STATIC const mp_obj_type_t ffifunc_type; -STATIC const mp_obj_type_t fficallback_type; -STATIC const mp_obj_type_t ffivar_type; - -STATIC ffi_type *char2ffi_type(char c) -{ - switch (c) { - case 'b': return &ffi_type_schar; - case 'B': return &ffi_type_uchar; - case 'h': return &ffi_type_sshort; - case 'H': return &ffi_type_ushort; - case 'i': return &ffi_type_sint; - case 'I': return &ffi_type_uint; - case 'l': return &ffi_type_slong; - case 'L': return &ffi_type_ulong; - #if MICROPY_PY_BUILTINS_FLOAT - case 'f': return &ffi_type_float; - case 'd': return &ffi_type_double; - #endif - case 'O': // mp_obj_t - case 'C': // (*)() - case 'P': // const void* - case 'p': // void* - case 's': return &ffi_type_pointer; - case 'v': return &ffi_type_void; - default: return NULL; - } -} - -STATIC ffi_type *get_ffi_type(mp_obj_t o_in) -{ - if (MP_OBJ_IS_STR(o_in)) { - const char *s = mp_obj_str_get_str(o_in); - ffi_type *t = char2ffi_type(*s); - if (t != NULL) { - return t; - } - } - // TODO: Support actual libffi type objects - - mp_raise_TypeError("Unknown type"); -} - -STATIC mp_obj_t return_ffi_value(ffi_arg val, char type) -{ - switch (type) { - case 's': { - const char *s = (const char *)(intptr_t)val; - if (!s) { - return mp_const_none; - } - return mp_obj_new_str(s, strlen(s), false); - } - case 'v': - return mp_const_none; - #if MICROPY_PY_BUILTINS_FLOAT - case 'f': { - union { ffi_arg ffi; float flt; } val_union = { .ffi = val }; - return mp_obj_new_float(val_union.flt); - } - case 'd': { - double *p = (double*)&val; - return mp_obj_new_float(*p); - } - #endif - case 'O': - return (mp_obj_t)(intptr_t)val; - default: - return mp_obj_new_int(val); - } -} - -// FFI module - -STATIC void ffimod_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - (void)kind; - mp_obj_ffimod_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "<ffimod %p>", self->handle); -} - -STATIC mp_obj_t ffimod_close(mp_obj_t self_in) { - mp_obj_ffimod_t *self = MP_OBJ_TO_PTR(self_in); - dlclose(self->handle); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(ffimod_close_obj, ffimod_close); - -STATIC mp_obj_t make_func(mp_obj_t rettype_in, void *func, mp_obj_t argtypes_in) { - const char *rettype = mp_obj_str_get_str(rettype_in); - const char *argtypes = mp_obj_str_get_str(argtypes_in); - - mp_int_t nparams = MP_OBJ_SMALL_INT_VALUE(mp_obj_len_maybe(argtypes_in)); - mp_obj_ffifunc_t *o = m_new_obj_var(mp_obj_ffifunc_t, ffi_type*, nparams); - o->base.type = &ffifunc_type; - - o->func = func; - o->rettype = *rettype; - o->argtypes = argtypes; - - mp_obj_iter_buf_t iter_buf; - mp_obj_t iterable = mp_getiter(argtypes_in, &iter_buf); - mp_obj_t item; - int i = 0; - while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { - o->params[i++] = get_ffi_type(item); - } - - int res = ffi_prep_cif(&o->cif, FFI_DEFAULT_ABI, nparams, char2ffi_type(*rettype), o->params); - if (res != FFI_OK) { - mp_raise_ValueError("Error in ffi_prep_cif"); - } - - return MP_OBJ_FROM_PTR(o); -} - -STATIC mp_obj_t ffimod_func(size_t n_args, const mp_obj_t *args) { - (void)n_args; // always 4 - mp_obj_ffimod_t *self = MP_OBJ_TO_PTR(args[0]); - const char *symname = mp_obj_str_get_str(args[2]); - - void *sym = dlsym(self->handle, symname); - if (sym == NULL) { - mp_raise_OSError(MP_ENOENT); - } - return make_func(args[1], sym, args[3]); -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ffimod_func_obj, 4, 4, ffimod_func); - -STATIC mp_obj_t mod_ffi_func(mp_obj_t rettype, mp_obj_t addr_in, mp_obj_t argtypes) { - void *addr = (void*)MP_OBJ_TO_PTR(mp_obj_int_get_truncated(addr_in)); - return make_func(rettype, addr, argtypes); -} -MP_DEFINE_CONST_FUN_OBJ_3(mod_ffi_func_obj, mod_ffi_func); - -STATIC void call_py_func(ffi_cif *cif, void *ret, void** args, void *func) { - mp_obj_t pyargs[cif->nargs]; - for (uint i = 0; i < cif->nargs; i++) { - pyargs[i] = mp_obj_new_int(*(mp_int_t*)args[i]); - } - mp_obj_t res = mp_call_function_n_kw(MP_OBJ_FROM_PTR(func), cif->nargs, 0, pyargs); - - if (res != mp_const_none) { - *(ffi_arg*)ret = mp_obj_int_get_truncated(res); - } -} - -STATIC mp_obj_t mod_ffi_callback(mp_obj_t rettype_in, mp_obj_t func_in, mp_obj_t paramtypes_in) { - const char *rettype = mp_obj_str_get_str(rettype_in); - - mp_int_t nparams = MP_OBJ_SMALL_INT_VALUE(mp_obj_len_maybe(paramtypes_in)); - mp_obj_fficallback_t *o = m_new_obj_var(mp_obj_fficallback_t, ffi_type*, nparams); - o->base.type = &fficallback_type; - - o->clo = ffi_closure_alloc(sizeof(ffi_closure), &o->func); - - o->rettype = *rettype; - - mp_obj_iter_buf_t iter_buf; - mp_obj_t iterable = mp_getiter(paramtypes_in, &iter_buf); - mp_obj_t item; - int i = 0; - while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { - o->params[i++] = get_ffi_type(item); - } - - int res = ffi_prep_cif(&o->cif, FFI_DEFAULT_ABI, nparams, char2ffi_type(*rettype), o->params); - if (res != FFI_OK) { - mp_raise_ValueError("Error in ffi_prep_cif"); - } - - res = ffi_prep_closure_loc(o->clo, &o->cif, call_py_func, MP_OBJ_TO_PTR(func_in), o->func); - if (res != FFI_OK) { - mp_raise_ValueError("ffi_prep_closure_loc"); - } - - return MP_OBJ_FROM_PTR(o); -} -MP_DEFINE_CONST_FUN_OBJ_3(mod_ffi_callback_obj, mod_ffi_callback); - -STATIC mp_obj_t ffimod_var(mp_obj_t self_in, mp_obj_t vartype_in, mp_obj_t symname_in) { - mp_obj_ffimod_t *self = MP_OBJ_TO_PTR(self_in); - const char *rettype = mp_obj_str_get_str(vartype_in); - const char *symname = mp_obj_str_get_str(symname_in); - - void *sym = dlsym(self->handle, symname); - if (sym == NULL) { - mp_raise_OSError(MP_ENOENT); - } - mp_obj_ffivar_t *o = m_new_obj(mp_obj_ffivar_t); - o->base.type = &ffivar_type; - - o->var = sym; - o->type = *rettype; - return MP_OBJ_FROM_PTR(o); -} -MP_DEFINE_CONST_FUN_OBJ_3(ffimod_var_obj, ffimod_var); - -STATIC mp_obj_t ffimod_addr(mp_obj_t self_in, mp_obj_t symname_in) { - mp_obj_ffimod_t *self = MP_OBJ_TO_PTR(self_in); - const char *symname = mp_obj_str_get_str(symname_in); - - void *sym = dlsym(self->handle, symname); - if (sym == NULL) { - mp_raise_OSError(MP_ENOENT); - } - return mp_obj_new_int((uintptr_t)sym); -} -MP_DEFINE_CONST_FUN_OBJ_2(ffimod_addr_obj, ffimod_addr); - -STATIC mp_obj_t ffimod_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - (void)n_args; - (void)n_kw; - - const char *fname = NULL; - if (args[0] != mp_const_none) { - fname = mp_obj_str_get_str(args[0]); - } - void *mod = dlopen(fname, RTLD_NOW | RTLD_LOCAL); - - if (mod == NULL) { - mp_raise_OSError(errno); - } - mp_obj_ffimod_t *o = m_new_obj(mp_obj_ffimod_t); - o->base.type = type; - o->handle = mod; - return MP_OBJ_FROM_PTR(o); -} - -STATIC const mp_rom_map_elem_t ffimod_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_func), MP_ROM_PTR(&ffimod_func_obj) }, - { MP_ROM_QSTR(MP_QSTR_var), MP_ROM_PTR(&ffimod_var_obj) }, - { MP_ROM_QSTR(MP_QSTR_addr), MP_ROM_PTR(&ffimod_addr_obj) }, - { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&ffimod_close_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(ffimod_locals_dict, ffimod_locals_dict_table); - -STATIC const mp_obj_type_t ffimod_type = { - { &mp_type_type }, - .name = MP_QSTR_ffimod, - .print = ffimod_print, - .make_new = ffimod_make_new, - .locals_dict = (mp_obj_dict_t*)&ffimod_locals_dict, -}; - -// FFI function - -STATIC void ffifunc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - (void)kind; - mp_obj_ffifunc_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "<ffifunc %p>", self->func); -} - -STATIC mp_obj_t ffifunc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_obj_ffifunc_t *self = MP_OBJ_TO_PTR(self_in); - assert(n_kw == 0); - assert(n_args == self->cif.nargs); - - ffi_arg values[n_args]; - void *valueptrs[n_args]; - const char *argtype = self->argtypes; - for (uint i = 0; i < n_args; i++, argtype++) { - mp_obj_t a = args[i]; - if (*argtype == 'O') { - values[i] = (ffi_arg)(intptr_t)a; - #if MICROPY_PY_BUILTINS_FLOAT - } else if (*argtype == 'f') { - float *p = (float*)&values[i]; - *p = mp_obj_get_float(a); - } else if (*argtype == 'd') { - double *p = (double*)&values[i]; - *p = mp_obj_get_float(a); - #endif - } else if (a == mp_const_none) { - values[i] = 0; - } else if (MP_OBJ_IS_INT(a)) { - values[i] = mp_obj_int_get_truncated(a); - } else if (MP_OBJ_IS_STR(a)) { - const char *s = mp_obj_str_get_str(a); - values[i] = (ffi_arg)(intptr_t)s; - } else if (((mp_obj_base_t*)MP_OBJ_TO_PTR(a))->type->buffer_p.get_buffer != NULL) { - mp_obj_base_t *o = (mp_obj_base_t*)MP_OBJ_TO_PTR(a); - mp_buffer_info_t bufinfo; - int ret = o->type->buffer_p.get_buffer(MP_OBJ_FROM_PTR(o), &bufinfo, MP_BUFFER_READ); // TODO: MP_BUFFER_READ? - if (ret != 0) { - goto error; - } - values[i] = (ffi_arg)(intptr_t)bufinfo.buf; - } else if (MP_OBJ_IS_TYPE(a, &fficallback_type)) { - mp_obj_fficallback_t *p = MP_OBJ_TO_PTR(a); - values[i] = (ffi_arg)(intptr_t)p->func; - } else { - goto error; - } - valueptrs[i] = &values[i]; - } - - // If ffi_arg is not big enough to hold a double, then we must pass along a - // pointer to a memory location of the correct size. - // TODO check if this needs to be done for other types which don't fit into - // ffi_arg. - #if MICROPY_PY_BUILTINS_FLOAT - if (sizeof(ffi_arg) == 4 && self->rettype == 'd') { - double retval; - ffi_call(&self->cif, self->func, &retval, valueptrs); - return mp_obj_new_float(retval); - } else - #endif - { - ffi_arg retval; - ffi_call(&self->cif, self->func, &retval, valueptrs); - return return_ffi_value(retval, self->rettype); - } - -error: - mp_raise_TypeError("Don't know how to pass object to native function"); -} - -STATIC const mp_obj_type_t ffifunc_type = { - { &mp_type_type }, - .name = MP_QSTR_ffifunc, - .print = ffifunc_print, - .call = ffifunc_call, -}; - -// FFI callback for Python function - -STATIC void fficallback_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - (void)kind; - mp_obj_fficallback_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "<fficallback %p>", self->func); -} - -STATIC const mp_obj_type_t fficallback_type = { - { &mp_type_type }, - .name = MP_QSTR_fficallback, - .print = fficallback_print, -}; - -// FFI variable - -STATIC void ffivar_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - (void)kind; - mp_obj_ffivar_t *self = MP_OBJ_TO_PTR(self_in); - // Variable value printed as cast to int - mp_printf(print, "<ffivar @%p: 0x%x>", self->var, *(int*)self->var); -} - -STATIC mp_obj_t ffivar_get(mp_obj_t self_in) { - mp_obj_ffivar_t *self = MP_OBJ_TO_PTR(self_in); - return mp_binary_get_val_array(self->type, self->var, 0); -} -MP_DEFINE_CONST_FUN_OBJ_1(ffivar_get_obj, ffivar_get); - -STATIC mp_obj_t ffivar_set(mp_obj_t self_in, mp_obj_t val_in) { - mp_obj_ffivar_t *self = MP_OBJ_TO_PTR(self_in); - mp_binary_set_val_array(self->type, self->var, 0, val_in); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_2(ffivar_set_obj, ffivar_set); - -STATIC const mp_rom_map_elem_t ffivar_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_get), MP_ROM_PTR(&ffivar_get_obj) }, - { MP_ROM_QSTR(MP_QSTR_set), MP_ROM_PTR(&ffivar_set_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(ffivar_locals_dict, ffivar_locals_dict_table); - -STATIC const mp_obj_type_t ffivar_type = { - { &mp_type_type }, - .name = MP_QSTR_ffivar, - .print = ffivar_print, - .locals_dict = (mp_obj_dict_t*)&ffivar_locals_dict, -}; - -// Generic opaque storage object (unused) - -/* -STATIC const mp_obj_type_t opaque_type = { - { &mp_type_type }, - .name = MP_QSTR_opaqueval, -// .print = opaque_print, -}; -*/ - -STATIC mp_obj_t mod_ffi_open(size_t n_args, const mp_obj_t *args) { - return ffimod_make_new(&ffimod_type, n_args, 0, args); -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_ffi_open_obj, 1, 2, mod_ffi_open); - -STATIC mp_obj_t mod_ffi_as_bytearray(mp_obj_t ptr, mp_obj_t size) { - return mp_obj_new_bytearray_by_ref(mp_obj_int_get_truncated(size), (void*)(uintptr_t)mp_obj_int_get_truncated(ptr)); -} -MP_DEFINE_CONST_FUN_OBJ_2(mod_ffi_as_bytearray_obj, mod_ffi_as_bytearray); - -STATIC const mp_rom_map_elem_t mp_module_ffi_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ffi) }, - { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mod_ffi_open_obj) }, - { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&mod_ffi_callback_obj) }, - { MP_ROM_QSTR(MP_QSTR_func), MP_ROM_PTR(&mod_ffi_func_obj) }, - { MP_ROM_QSTR(MP_QSTR_as_bytearray), MP_ROM_PTR(&mod_ffi_as_bytearray_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(mp_module_ffi_globals, mp_module_ffi_globals_table); - -const mp_obj_module_t mp_module_ffi = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&mp_module_ffi_globals, -}; diff --git a/unix/modjni.c b/unix/modjni.c deleted file mode 100644 index b7ac49dc85..0000000000 --- a/unix/modjni.c +++ /dev/null @@ -1,722 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Paul Sokolovsky - * - * 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 <assert.h> -#include <string.h> -#include <errno.h> -#include <dlfcn.h> -#include <ctype.h> - -#include "py/nlr.h" -#include "py/runtime0.h" -#include "py/runtime.h" -#include "py/binary.h" - -#include <jni.h> - -#define JJ(call, ...) (*env)->call(env, __VA_ARGS__) -#define JJ1(call) (*env)->call(env) -#define MATCH(s, static) (!strncmp(s, static, sizeof(static) - 1)) - -static JavaVM *jvm; -static JNIEnv *env; -static jclass Class_class; -static jclass String_class; -static jmethodID Class_getName_mid; -static jmethodID Class_getField_mid; -static jmethodID Class_getMethods_mid; -static jmethodID Class_getConstructors_mid; -static jmethodID Method_getName_mid; -static jmethodID Object_toString_mid; - -static jclass List_class; -static jmethodID List_get_mid; -static jmethodID List_set_mid; -static jmethodID List_size_mid; - -static jclass IndexException_class; - -STATIC const mp_obj_type_t jobject_type; -STATIC const mp_obj_type_t jmethod_type; - -STATIC mp_obj_t new_jobject(jobject jo); -STATIC mp_obj_t new_jclass(jclass jc); -STATIC mp_obj_t call_method(jobject obj, const char *name, jarray methods, bool is_constr, size_t n_args, const mp_obj_t *args); -STATIC bool py2jvalue(const char **jtypesig, mp_obj_t arg, jvalue *out); - -typedef struct _mp_obj_jclass_t { - mp_obj_base_t base; - jclass cls; -} mp_obj_jclass_t; - -typedef struct _mp_obj_jobject_t { - mp_obj_base_t base; - jobject obj; -} mp_obj_jobject_t; - -typedef struct _mp_obj_jmethod_t { - mp_obj_base_t base; - jobject obj; - jmethodID meth; - qstr name; - bool is_static; -} mp_obj_jmethod_t; - -// Utility functions - -STATIC bool is_object_type(const char *jtypesig) { - while (*jtypesig != ' ' && *jtypesig) { - if (*jtypesig == '.') { - return true; - } - jtypesig++; - } - return false; -} - -STATIC void check_exception(void) { - jobject exc = JJ1(ExceptionOccurred); - if (exc) { - //JJ1(ExceptionDescribe); - mp_obj_t py_e = new_jobject(exc); - JJ1(ExceptionClear); - if (JJ(IsInstanceOf, exc, IndexException_class)) { - nlr_raise(mp_obj_new_exception_arg1(&mp_type_IndexError, py_e)); - } - nlr_raise(mp_obj_new_exception_arg1(&mp_type_Exception, py_e)); - } -} - -STATIC void print_jobject(const mp_print_t *print, jobject obj) { - jobject str_o = JJ(CallObjectMethod, obj, Object_toString_mid); - const char *str = JJ(GetStringUTFChars, str_o, NULL); - mp_printf(print, str); - JJ(ReleaseStringUTFChars, str_o, str); -} - -// jclass - -STATIC void jclass_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - mp_obj_jclass_t *self = self_in; - if (kind == PRINT_REPR) { - mp_printf(print, "<jclass @%p \"", self->cls); - } - print_jobject(print, self->cls); - if (kind == PRINT_REPR) { - mp_printf(print, "\">"); - } -} - -STATIC void jclass_attr(mp_obj_t self_in, qstr attr_in, mp_obj_t *dest) { - if (dest[0] == MP_OBJ_NULL) { - // load attribute - mp_obj_jclass_t *self = self_in; - const char *attr = qstr_str(attr_in); - - jstring field_name = JJ(NewStringUTF, attr); - jobject field = JJ(CallObjectMethod, self->cls, Class_getField_mid, field_name); - if (!JJ1(ExceptionCheck)) { - jfieldID field_id = JJ(FromReflectedField, field); - jobject obj = JJ(GetStaticObjectField, self->cls, field_id); - dest[0] = new_jobject(obj); - return; - } - //JJ1(ExceptionDescribe); - JJ1(ExceptionClear); - - mp_obj_jmethod_t *o = m_new_obj(mp_obj_jmethod_t); - o->base.type = &jmethod_type; - o->name = attr_in; - o->meth = NULL; - o->obj = self->cls; - o->is_static = true; - dest[0] = o; - } -} - -STATIC mp_obj_t jclass_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { - if (n_kw != 0) { - mp_raise_TypeError("kwargs not supported"); - } - mp_obj_jclass_t *self = self_in; - - jarray methods = JJ(CallObjectMethod, self->cls, Class_getConstructors_mid); - - return call_method(self->cls, NULL, methods, true, n_args, args); -} - -STATIC const mp_rom_map_elem_t jclass_locals_dict_table[] = { -// { MP_ROM_QSTR(MP_QSTR_get), MP_ROM_PTR(&ffivar_get_obj) }, -// { MP_ROM_QSTR(MP_QSTR_set), MP_ROM_PTR(&ffivar_set_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(jclass_locals_dict, jclass_locals_dict_table); - -STATIC const mp_obj_type_t jclass_type = { - { &mp_type_type }, - .name = MP_QSTR_jclass, - .print = jclass_print, - .attr = jclass_attr, - .call = jclass_call, - .locals_dict = (mp_obj_dict_t*)&jclass_locals_dict, -}; - -STATIC mp_obj_t new_jclass(jclass jc) { - mp_obj_jclass_t *o = m_new_obj(mp_obj_jclass_t); - o->base.type = &jclass_type; - o->cls = jc; - return o; -} - -// jobject - -STATIC void jobject_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - mp_obj_jobject_t *self = self_in; - if (kind == PRINT_REPR) { - mp_printf(print, "<jobject @%p \"", self->obj); - } - print_jobject(print, self->obj); - if (kind == PRINT_REPR) { - mp_printf(print, "\">"); - } -} - -STATIC void jobject_attr(mp_obj_t self_in, qstr attr_in, mp_obj_t *dest) { - if (dest[0] == MP_OBJ_NULL) { - // load attribute - mp_obj_jobject_t *self = self_in; - - const char *attr = qstr_str(attr_in); - jclass obj_class = JJ(GetObjectClass, self->obj); - jstring field_name = JJ(NewStringUTF, attr); - jobject field = JJ(CallObjectMethod, obj_class, Class_getField_mid, field_name); - JJ(DeleteLocalRef, field_name); - JJ(DeleteLocalRef, obj_class); - if (!JJ1(ExceptionCheck)) { - jfieldID field_id = JJ(FromReflectedField, field); - JJ(DeleteLocalRef, field); - jobject obj = JJ(GetObjectField, self->obj, field_id); - dest[0] = new_jobject(obj); - return; - } - //JJ1(ExceptionDescribe); - JJ1(ExceptionClear); - - mp_obj_jmethod_t *o = m_new_obj(mp_obj_jmethod_t); - o->base.type = &jmethod_type; - o->name = attr_in; - o->meth = NULL; - o->obj = self->obj; - o->is_static = false; - dest[0] = o; - } -} - -STATIC void get_jclass_name(jobject obj, char *buf) { - jclass obj_class = JJ(GetObjectClass, obj); - jstring name = JJ(CallObjectMethod, obj_class, Class_getName_mid); - jint len = JJ(GetStringLength, name); - JJ(GetStringUTFRegion, name, 0, len, buf); - check_exception(); -} - -STATIC mp_obj_t jobject_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { - mp_obj_jobject_t *self = self_in; - mp_uint_t idx = mp_obj_get_int(index); - char class_name[64]; - get_jclass_name(self->obj, class_name); - //printf("class: %s\n", class_name); - - if (class_name[0] == '[') { - if (class_name[1] == 'L' || class_name[1] == '[') { - if (value == MP_OBJ_NULL) { - // delete - assert(0); - } else if (value == MP_OBJ_SENTINEL) { - // load - jobject el = JJ(GetObjectArrayElement, self->obj, idx); - return new_jobject(el); - } else { - // store - jvalue jval; - const char *t = class_name + 1; - py2jvalue(&t, value, &jval); - JJ(SetObjectArrayElement, self->obj, idx, jval.l); - return mp_const_none; - } - } - mp_raise_NotImplementedError(""); - } - - if (!JJ(IsInstanceOf, self->obj, List_class)) { - return MP_OBJ_NULL; - } - - - if (value == MP_OBJ_NULL) { - // delete - assert(0); - } else if (value == MP_OBJ_SENTINEL) { - // load - jobject el = JJ(CallObjectMethod, self->obj, List_get_mid, idx); - check_exception(); - return new_jobject(el); - } else { - // store - assert(0); - } - - -return MP_OBJ_NULL; -} - -STATIC mp_obj_t jobject_unary_op(mp_unary_op_t op, mp_obj_t self_in) { - mp_obj_jobject_t *self = self_in; - switch (op) { - case MP_UNARY_OP_BOOL: - case MP_UNARY_OP_LEN: { - jint len = JJ(CallIntMethod, self->obj, List_size_mid); - if (op == MP_UNARY_OP_BOOL) { - return mp_obj_new_bool(len != 0); - } - return MP_OBJ_NEW_SMALL_INT(len); - } - default: - return MP_OBJ_NULL; // op not supported - } -} - -// TODO: subscr_load_adaptor & subscr_getiter convenience functions -// should be moved to common location for reuse. -STATIC mp_obj_t subscr_load_adaptor(mp_obj_t self_in, mp_obj_t index_in) { - return mp_obj_subscr(self_in, index_in, MP_OBJ_SENTINEL); -} -MP_DEFINE_CONST_FUN_OBJ_2(subscr_load_adaptor_obj, subscr_load_adaptor); - -// .getiter special method which returns iterator which works in terms -// of object subscription. -STATIC mp_obj_t subscr_getiter(mp_obj_t self_in) { - mp_obj_t dest[2] = {(mp_obj_t)&subscr_load_adaptor_obj, self_in}; - return mp_obj_new_getitem_iter(dest); -} - -STATIC const mp_obj_type_t jobject_type = { - { &mp_type_type }, - .name = MP_QSTR_jobject, - .print = jobject_print, - .unary_op = jobject_unary_op, - .attr = jobject_attr, - .subscr = jobject_subscr, - .getiter = subscr_getiter, -// .locals_dict = (mp_obj_dict_t*)&jobject_locals_dict, -}; - -STATIC mp_obj_t new_jobject(jobject jo) { - if (jo == NULL) { - return mp_const_none; - } else if (JJ(IsInstanceOf, jo, String_class)) { - const char *s = JJ(GetStringUTFChars, jo, NULL); - mp_obj_t ret = mp_obj_new_str(s, strlen(s), false); - JJ(ReleaseStringUTFChars, jo, s); - return ret; - } else if (JJ(IsInstanceOf, jo, Class_class)) { - return new_jclass(jo); - } else { - mp_obj_jobject_t *o = m_new_obj(mp_obj_jobject_t); - o->base.type = &jobject_type; - o->obj = jo; - return o; - } - -} - - -// jmethod - -STATIC void jmethod_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - (void)kind; - mp_obj_jmethod_t *self = self_in; - // Variable value printed as cast to int - mp_printf(print, "<jmethod '%s'>", qstr_str(self->name)); -} - -#define IMATCH(s, static) ((!strncmp(s, static, sizeof(static) - 1)) && (s += sizeof(static) - 1)) - -#define CHECK_TYPE(java_type_name) \ - if (strncmp(arg_type, java_type_name, sizeof(java_type_name) - 1) != 0) { \ - return false; \ - } \ - arg_type += sizeof(java_type_name) - 1; - -STATIC const char *strprev(const char *s, char c) { - while (*s != c) { - s--; - } - return s; -} - -STATIC bool py2jvalue(const char **jtypesig, mp_obj_t arg, jvalue *out) { - const char *arg_type = *jtypesig; - mp_obj_type_t *type = mp_obj_get_type(arg); - - if (type == &mp_type_str) { - if (IMATCH(arg_type, "java.lang.String") || IMATCH(arg_type, "java.lang.Object")) { - out->l = JJ(NewStringUTF, mp_obj_str_get_str(arg)); - } else { - return false; - } - } else if (type == &mp_type_int) { - if (IMATCH(arg_type, "int") || IMATCH(arg_type, "long")) { - // TODO: Java long is 64-bit actually - out->j = mp_obj_get_int(arg); - } else { - return false; - } - } else if (type == &jobject_type) { - bool is_object = false; - const char *expected_type = arg_type; - while (1) { - if (isalpha(*arg_type)) { - } else if (*arg_type == '.') { - is_object = true; - } else { - break; - } - arg_type++; - } - if (!is_object) { - return false; - } - mp_obj_jobject_t *jo = arg; - if (!MATCH(expected_type, "java.lang.Object")) { - char class_name[64]; - get_jclass_name(jo->obj, class_name); - //printf("Arg class: %s\n", class_name); - if (strcmp(class_name, expected_type) != 0) { - return false; - } - } - out->l = jo->obj; - } else if (type == &mp_type_bool) { - if (IMATCH(arg_type, "boolean")) { - out->z = arg == mp_const_true; - } else { - return false; - } - } else if (arg == mp_const_none) { - //printf("TODO: Check java arg type!!\n"); - while (isalpha(*arg_type) || *arg_type == '.') { - arg_type++; - } - out->l = NULL; - } else { - mp_raise_TypeError("arg type not supported"); - } - - *jtypesig = arg_type; - return true; -} - -#if 0 -// jvalue is known to be union of jobject and friends. And yet from C's -// perspective, it's aggregate object which may require passing via stack -// instead of registers. Work that around by passing jobject and typecasting -// it. -STATIC mp_obj_t jvalue2py(const char *jtypesig, jobject arg) { - if (arg == NULL || MATCH(jtypesig, "void")) { - return mp_const_none; - } else if (MATCH(jtypesig, "boolean")) { - return mp_obj_new_bool((bool)arg); - } else if (MATCH(jtypesig, "int")) { - return mp_obj_new_int((mp_int_t)arg); - } else if (is_object_type(jtypesig)) { - // Non-primitive, object type - return new_jobject(arg); - } - - printf("Unknown return type: %s\n", jtypesig); - - return MP_OBJ_NULL; -} -#endif - -STATIC mp_obj_t call_method(jobject obj, const char *name, jarray methods, bool is_constr, size_t n_args, const mp_obj_t *args) { - jvalue jargs[n_args]; -// printf("methods=%p\n", methods); - jsize num_methods = JJ(GetArrayLength, methods); - for (int i = 0; i < num_methods; i++) { - jobject meth = JJ(GetObjectArrayElement, methods, i); - jobject name_o = JJ(CallObjectMethod, meth, Object_toString_mid); - const char *decl = JJ(GetStringUTFChars, name_o, NULL); - const char *arg_types = strchr(decl, '(') + 1; - //const char *arg_types_end = strchr(arg_types, ')'); -// printf("method[%d]=%p %s\n", i, meth, decl); - - const char *meth_name = NULL; - const char *ret_type = NULL; - if (!is_constr) { - meth_name = strprev(arg_types, '.') + 1; - ret_type = strprev(meth_name, ' ') - 1; - ret_type = strprev(ret_type, ' ') + 1; - - int name_len = strlen(name); - if (strncmp(name, meth_name, name_len/*arg_types - meth_name - 1*/) || meth_name[name_len] != '('/*(*/) { - goto next_method; - } - } -// printf("method[%d]=%p %s\n", i, meth, decl); -// printf("!!!%s\n", arg_types); -// printf("name=%p meth_name=%s\n", name, meth_name); - - bool found = true; - for (int i = 0; i < n_args && *arg_types != ')'; i++) { - if (!py2jvalue(&arg_types, args[i], &jargs[i])) { - goto next_method; - } - - if (*arg_types == ',') { - arg_types++; - } - } - - if (*arg_types != ')') { - goto next_method; - } - - if (found) { -// printf("found!\n"); - jmethodID method_id = JJ(FromReflectedMethod, meth); - jobject res; - mp_obj_t ret; - if (is_constr) { - JJ(ReleaseStringUTFChars, name_o, decl); - res = JJ(NewObjectA, obj, method_id, jargs); - return new_jobject(res); - } else { - if (MATCH(ret_type, "void")) { - JJ(CallVoidMethodA, obj, method_id, jargs); - check_exception(); - ret = mp_const_none; - } else if (MATCH(ret_type, "int")) { - jint res = JJ(CallIntMethodA, obj, method_id, jargs); - check_exception(); - ret = mp_obj_new_int(res); - } else if (MATCH(ret_type, "boolean")) { - jboolean res = JJ(CallBooleanMethodA, obj, method_id, jargs); - check_exception(); - ret = mp_obj_new_bool(res); - } else if (is_object_type(ret_type)) { - res = JJ(CallObjectMethodA, obj, method_id, jargs); - check_exception(); - ret = new_jobject(res); - } else { - JJ(ReleaseStringUTFChars, name_o, decl); - mp_raise_TypeError("cannot handle return type"); - } - - JJ(ReleaseStringUTFChars, name_o, decl); - JJ(DeleteLocalRef, name_o); - JJ(DeleteLocalRef, meth); - return ret; - } - } - -next_method: - JJ(ReleaseStringUTFChars, name_o, decl); - JJ(DeleteLocalRef, name_o); - JJ(DeleteLocalRef, meth); - } - - mp_raise_TypeError("method not found"); -} - - -STATIC mp_obj_t jmethod_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { - if (n_kw != 0) { - mp_raise_TypeError("kwargs not supported"); - } - mp_obj_jmethod_t *self = self_in; - - const char *name = qstr_str(self->name); -// jstring meth_name = JJ(NewStringUTF, name); - - jclass obj_class = self->obj; - if (!self->is_static) { - obj_class = JJ(GetObjectClass, self->obj); - } - jarray methods = JJ(CallObjectMethod, obj_class, Class_getMethods_mid); - - return call_method(self->obj, name, methods, false, n_args, args); -} - -STATIC const mp_obj_type_t jmethod_type = { - { &mp_type_type }, - .name = MP_QSTR_jmethod, - .print = jmethod_print, - .call = jmethod_call, -// .attr = jobject_attr, -// .locals_dict = (mp_obj_dict_t*)&jobject_locals_dict, -}; - -#ifdef __ANDROID__ -#define LIBJVM_SO "libdvm.so" -#else -#define LIBJVM_SO "libjvm.so" -#endif - -STATIC void create_jvm() { - JavaVMInitArgs args; - JavaVMOption options; - options.optionString = "-Djava.class.path=."; - args.version = JNI_VERSION_1_6; - args.nOptions = 1; - args.options = &options; - args.ignoreUnrecognized = 0; - - if (env) { - return; - } - - void *libjvm = dlopen(LIBJVM_SO, RTLD_NOW | RTLD_GLOBAL); - if (!libjvm) { - mp_raise_msg(&mp_type_OSError, "unable to load libjvm.so, use LD_LIBRARY_PATH"); - } - int (*_JNI_CreateJavaVM)(void*, void**, void*) = dlsym(libjvm, "JNI_CreateJavaVM"); - - int st = _JNI_CreateJavaVM(&jvm, (void**)&env, &args); - if (st < 0 || !env) { - mp_raise_msg(&mp_type_OSError, "unable to create JVM"); - } - - Class_class = JJ(FindClass, "java/lang/Class"); - jclass method_class = JJ(FindClass, "java/lang/reflect/Method"); - String_class = JJ(FindClass, "java/lang/String"); - - jclass Object_class = JJ(FindClass, "java/lang/Object"); - Object_toString_mid = JJ(GetMethodID, Object_class, "toString", - "()Ljava/lang/String;"); - - Class_getName_mid = (*env)->GetMethodID(env, Class_class, "getName", - "()Ljava/lang/String;"); - Class_getField_mid = (*env)->GetMethodID(env, Class_class, "getField", - "(Ljava/lang/String;)Ljava/lang/reflect/Field;"); - Class_getMethods_mid = (*env)->GetMethodID(env, Class_class, "getMethods", - "()[Ljava/lang/reflect/Method;"); - Class_getConstructors_mid = (*env)->GetMethodID(env, Class_class, "getConstructors", - "()[Ljava/lang/reflect/Constructor;"); - Method_getName_mid = (*env)->GetMethodID(env, method_class, "getName", - "()Ljava/lang/String;"); - - List_class = JJ(FindClass, "java/util/List"); - List_get_mid = JJ(GetMethodID, List_class, "get", - "(I)Ljava/lang/Object;"); - List_set_mid = JJ(GetMethodID, List_class, "set", - "(ILjava/lang/Object;)Ljava/lang/Object;"); - List_size_mid = JJ(GetMethodID, List_class, "size", - "()I"); - IndexException_class = JJ(FindClass, "java/lang/IndexOutOfBoundsException"); -} - -STATIC mp_obj_t mod_jni_cls(mp_obj_t cls_name_in) { - const char *cls_name = mp_obj_str_get_str(cls_name_in); - if (!env) { - create_jvm(); - } - jclass cls = JJ(FindClass, cls_name); - - mp_obj_jclass_t *o = m_new_obj(mp_obj_jclass_t); - o->base.type = &jclass_type; - o->cls = cls; - return o; -} -MP_DEFINE_CONST_FUN_OBJ_1(mod_jni_cls_obj, mod_jni_cls); - -STATIC mp_obj_t mod_jni_array(mp_obj_t type_in, mp_obj_t size_in) { - if (!env) { - create_jvm(); - } - mp_int_t size = mp_obj_get_int(size_in); - jobject res = NULL; - - if (MP_OBJ_IS_TYPE(type_in, &jclass_type)) { - - mp_obj_jclass_t *jcls = type_in; - res = JJ(NewObjectArray, size, jcls->cls, NULL); - - } else if (MP_OBJ_IS_STR(type_in)) { - const char *type = mp_obj_str_get_str(type_in); - switch (*type) { - case 'Z': - res = JJ(NewBooleanArray, size); - break; - case 'B': - res = JJ(NewByteArray, size); - break; - case 'C': - res = JJ(NewCharArray, size); - break; - case 'S': - res = JJ(NewShortArray, size); - break; - case 'I': - res = JJ(NewIntArray, size); - break; - case 'J': - res = JJ(NewLongArray, size); - break; - case 'F': - res = JJ(NewFloatArray, size); - break; - case 'D': - res = JJ(NewDoubleArray, size); - break; - } - - } - - return new_jobject(res); -} -MP_DEFINE_CONST_FUN_OBJ_2(mod_jni_array_obj, mod_jni_array); - - -STATIC mp_obj_t mod_jni_env() { - return mp_obj_new_int((mp_int_t)env); -} -MP_DEFINE_CONST_FUN_OBJ_0(mod_jni_env_obj, mod_jni_env); - -STATIC const mp_rom_map_elem_t mp_module_jni_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_jni) }, - { MP_ROM_QSTR(MP_QSTR_cls), MP_ROM_PTR(&mod_jni_cls_obj) }, - { MP_ROM_QSTR(MP_QSTR_array), MP_ROM_PTR(&mod_jni_array_obj) }, - { MP_ROM_QSTR(MP_QSTR_env), MP_ROM_PTR(&mod_jni_env_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(mp_module_jni_globals, mp_module_jni_globals_table); - -const mp_obj_module_t mp_module_jni = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&mp_module_jni_globals, -}; diff --git a/unix/modmachine.c b/unix/modmachine.c deleted file mode 100644 index 48dddec0ae..0000000000 --- a/unix/modmachine.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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 <stdint.h> - -#include "py/runtime.h" -#include "py/obj.h" - -#include "extmod/machine_mem.h" -#include "extmod/machine_pinbase.h" -#include "extmod/machine_signal.h" -#include "extmod/machine_pulse.h" - -#if MICROPY_PLAT_DEV_MEM -#include <errno.h> -#include <fcntl.h> -#include <sys/mman.h> -#define MICROPY_PAGE_SIZE 4096 -#define MICROPY_PAGE_MASK (MICROPY_PAGE_SIZE - 1) -#endif - -#if MICROPY_PY_MACHINE - -uintptr_t mod_machine_mem_get_addr(mp_obj_t addr_o, uint align) { - uintptr_t addr = mp_obj_int_get_truncated(addr_o); - if ((addr & (align - 1)) != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "address %08x is not aligned to %d bytes", addr, align)); - } - #if MICROPY_PLAT_DEV_MEM - { - // Not thread-safe - static int fd; - static uintptr_t last_base = (uintptr_t)-1; - static uintptr_t map_page; - if (!fd) { - fd = open("/dev/mem", O_RDWR | O_SYNC); - if (fd == -1) { - mp_raise_OSError(errno); - } - } - - uintptr_t cur_base = addr & ~MICROPY_PAGE_MASK; - if (cur_base != last_base) { - map_page = (uintptr_t)mmap(NULL, MICROPY_PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, cur_base); - last_base = cur_base; - } - addr = map_page + (addr & MICROPY_PAGE_MASK); - } - #endif - - return addr; -} - -STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) }, - - { MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) }, - { MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) }, - { MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) }, - - { MP_ROM_QSTR(MP_QSTR_PinBase), MP_ROM_PTR(&machine_pinbase_type) }, - { MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) }, - #if MICROPY_PY_MACHINE_PULSE - { MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) }, - #endif -}; - -STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); - -const mp_obj_module_t mp_module_machine = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&machine_module_globals, -}; - -#endif // MICROPY_PY_MACHINE diff --git a/unix/modos.c b/unix/modos.c deleted file mode 100644 index 5030fbb65b..0000000000 --- a/unix/modos.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014 Damien P. George - * Copyright (c) 2014 Paul Sokolovsky - * - * 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 <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#include <dirent.h> -#include "py/mpconfig.h" - -#include "py/nlr.h" -#include "py/runtime.h" -#include "py/objtuple.h" -#include "py/mphal.h" -#include "extmod/misc.h" - -#ifdef __ANDROID__ -#define USE_STATFS 1 -#endif - -STATIC mp_obj_t mod_os_stat(mp_obj_t path_in) { - struct stat sb; - const char *path = mp_obj_str_get_str(path_in); - - int res = stat(path, &sb); - RAISE_ERRNO(res, errno); - - mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL)); - t->items[0] = MP_OBJ_NEW_SMALL_INT(sb.st_mode); - t->items[1] = MP_OBJ_NEW_SMALL_INT(sb.st_ino); - t->items[2] = MP_OBJ_NEW_SMALL_INT(sb.st_dev); - t->items[3] = MP_OBJ_NEW_SMALL_INT(sb.st_nlink); - t->items[4] = MP_OBJ_NEW_SMALL_INT(sb.st_uid); - t->items[5] = MP_OBJ_NEW_SMALL_INT(sb.st_gid); - t->items[6] = mp_obj_new_int_from_uint(sb.st_size); - t->items[7] = MP_OBJ_NEW_SMALL_INT(sb.st_atime); - t->items[8] = MP_OBJ_NEW_SMALL_INT(sb.st_mtime); - t->items[9] = MP_OBJ_NEW_SMALL_INT(sb.st_ctime); - return MP_OBJ_FROM_PTR(t); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_stat_obj, mod_os_stat); - -#if MICROPY_PY_OS_STATVFS - -#if USE_STATFS -#include <sys/vfs.h> -#define STRUCT_STATVFS struct statfs -#define STATVFS statfs -#define F_FAVAIL sb.f_ffree -#define F_NAMEMAX sb.f_namelen -#define F_FLAG sb.f_flags -#else -#include <sys/statvfs.h> -#define STRUCT_STATVFS struct statvfs -#define STATVFS statvfs -#define F_FAVAIL sb.f_favail -#define F_NAMEMAX sb.f_namemax -#define F_FLAG sb.f_flag -#endif - -STATIC mp_obj_t mod_os_statvfs(mp_obj_t path_in) { - STRUCT_STATVFS sb; - const char *path = mp_obj_str_get_str(path_in); - - int res = STATVFS(path, &sb); - RAISE_ERRNO(res, errno); - - mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL)); - t->items[0] = MP_OBJ_NEW_SMALL_INT(sb.f_bsize); - t->items[1] = MP_OBJ_NEW_SMALL_INT(sb.f_frsize); - t->items[2] = MP_OBJ_NEW_SMALL_INT(sb.f_blocks); - t->items[3] = MP_OBJ_NEW_SMALL_INT(sb.f_bfree); - t->items[4] = MP_OBJ_NEW_SMALL_INT(sb.f_bavail); - t->items[5] = MP_OBJ_NEW_SMALL_INT(sb.f_files); - t->items[6] = MP_OBJ_NEW_SMALL_INT(sb.f_ffree); - t->items[7] = MP_OBJ_NEW_SMALL_INT(F_FAVAIL); - t->items[8] = MP_OBJ_NEW_SMALL_INT(F_FLAG); - t->items[9] = MP_OBJ_NEW_SMALL_INT(F_NAMEMAX); - return MP_OBJ_FROM_PTR(t); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_statvfs_obj, mod_os_statvfs); -#endif - -STATIC mp_obj_t mod_os_unlink(mp_obj_t path_in) { - const char *path = mp_obj_str_get_str(path_in); - - int r = unlink(path); - - RAISE_ERRNO(r, errno); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_unlink_obj, mod_os_unlink); - -STATIC mp_obj_t mod_os_system(mp_obj_t cmd_in) { - const char *cmd = mp_obj_str_get_str(cmd_in); - - int r = system(cmd); - - RAISE_ERRNO(r, errno); - - return MP_OBJ_NEW_SMALL_INT(r); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_system_obj, mod_os_system); - -STATIC mp_obj_t mod_os_getenv(mp_obj_t var_in) { - const char *s = getenv(mp_obj_str_get_str(var_in)); - if (s == NULL) { - return mp_const_none; - } - return mp_obj_new_str(s, strlen(s), false); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_getenv_obj, mod_os_getenv); - -STATIC mp_obj_t mod_os_mkdir(mp_obj_t path_in) { - // TODO: Accept mode param - const char *path = mp_obj_str_get_str(path_in); - #ifdef _WIN32 - int r = mkdir(path); - #else - int r = mkdir(path, 0777); - #endif - RAISE_ERRNO(r, errno); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_mkdir_obj, mod_os_mkdir); - -typedef struct _mp_obj_listdir_t { - mp_obj_base_t base; - mp_fun_1_t iternext; - DIR *dir; -} mp_obj_listdir_t; - -STATIC mp_obj_t listdir_next(mp_obj_t self_in) { - mp_obj_listdir_t *self = MP_OBJ_TO_PTR(self_in); - - if (self->dir == NULL) { - goto done; - } - struct dirent *dirent = readdir(self->dir); - if (dirent == NULL) { - closedir(self->dir); - self->dir = NULL; - done: - return MP_OBJ_STOP_ITERATION; - } - - mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL)); - t->items[0] = mp_obj_new_str(dirent->d_name, strlen(dirent->d_name), false); - #ifdef _DIRENT_HAVE_D_TYPE - t->items[1] = MP_OBJ_NEW_SMALL_INT(dirent->d_type); - #else - // DT_UNKNOWN should have 0 value on any reasonable system - t->items[1] = MP_OBJ_NEW_SMALL_INT(0); - #endif - #ifdef _DIRENT_HAVE_D_INO - t->items[2] = MP_OBJ_NEW_SMALL_INT(dirent->d_ino); - #else - t->items[2] = MP_OBJ_NEW_SMALL_INT(0); - #endif - return MP_OBJ_FROM_PTR(t); -} - -STATIC mp_obj_t mod_os_ilistdir(size_t n_args, const mp_obj_t *args) { - const char *path = "."; - if (n_args > 0) { - path = mp_obj_str_get_str(args[0]); - } - mp_obj_listdir_t *o = m_new_obj(mp_obj_listdir_t); - o->base.type = &mp_type_polymorph_iter; - o->dir = opendir(path); - o->iternext = listdir_next; - return MP_OBJ_FROM_PTR(o); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_os_ilistdir_obj, 0, 1, mod_os_ilistdir); - -STATIC mp_obj_t mod_os_errno(size_t n_args, const mp_obj_t *args) { - if (n_args == 0) { - return MP_OBJ_NEW_SMALL_INT(errno); - } - - errno = mp_obj_get_int(args[0]); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_os_errno_obj, 0, 1, mod_os_errno); - -STATIC const mp_rom_map_elem_t mp_module_os_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) }, - { MP_ROM_QSTR(MP_QSTR_errno), MP_ROM_PTR(&mod_os_errno_obj) }, - { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&mod_os_stat_obj) }, - #if MICROPY_PY_OS_STATVFS - { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&mod_os_statvfs_obj) }, - #endif - { MP_ROM_QSTR(MP_QSTR_system), MP_ROM_PTR(&mod_os_system_obj) }, - { MP_ROM_QSTR(MP_QSTR_unlink), MP_ROM_PTR(&mod_os_unlink_obj) }, - { MP_ROM_QSTR(MP_QSTR_getenv), MP_ROM_PTR(&mod_os_getenv_obj) }, - { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mod_os_mkdir_obj) }, - { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mod_os_ilistdir_obj) }, - #if MICROPY_PY_OS_DUPTERM - { MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&mp_uos_dupterm_obj) }, - #endif -}; - -STATIC MP_DEFINE_CONST_DICT(mp_module_os_globals, mp_module_os_globals_table); - -const mp_obj_module_t mp_module_os = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&mp_module_os_globals, -}; diff --git a/unix/modsocket.c b/unix/modsocket.c deleted file mode 100644 index c612f870d9..0000000000 --- a/unix/modsocket.c +++ /dev/null @@ -1,583 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014 Damien P. George - * Copyright (c) 2014 Paul Sokolovsky - * - * 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 <assert.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netdb.h> -#include <errno.h> - -#include "py/nlr.h" -#include "py/objtuple.h" -#include "py/objstr.h" -#include "py/runtime.h" -#include "py/stream.h" -#include "py/builtin.h" -#include "py/mphal.h" - -/* - The idea of this module is to implement reasonable minimum of - socket-related functions to write typical clients and servers. - The module named "usocket" on purpose, to allow to make - Python-level module more (or fully) compatible with CPython - "socket", e.g.: - ---- socket.py ---- - from usocket import * - from socket_more_funcs import * - from socket_more_funcs2 import * - ------------------- - I.e. this module should stay lean, and more functions (if needed) - should be add to separate modules (C or Python level). - */ - -#define MICROPY_SOCKET_EXTRA (0) - -// This type must "inherit" from mp_obj_fdfile_t, i.e. matching subset of -// fields should have the same layout. -typedef struct _mp_obj_socket_t { - mp_obj_base_t base; - int fd; -} mp_obj_socket_t; - -const mp_obj_type_t mp_type_socket; - -// Helper functions -static inline mp_obj_t mp_obj_from_sockaddr(const struct sockaddr *addr, socklen_t len) { - return mp_obj_new_bytes((const byte *)addr, len); -} - -STATIC mp_obj_socket_t *socket_new(int fd) { - mp_obj_socket_t *o = m_new_obj(mp_obj_socket_t); - o->base.type = &mp_type_socket; - o->fd = fd; - return o; -} - - -STATIC void socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - (void)kind; - mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "<_socket %d>", self->fd); -} - -STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { - mp_obj_socket_t *o = MP_OBJ_TO_PTR(o_in); - mp_int_t r = read(o->fd, buf, size); - if (r == -1) { - *errcode = errno; - return MP_STREAM_ERROR; - } - return r; -} - -STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { - mp_obj_socket_t *o = MP_OBJ_TO_PTR(o_in); - mp_int_t r = write(o->fd, buf, size); - if (r == -1) { - *errcode = errno; - return MP_STREAM_ERROR; - } - return r; -} - -STATIC mp_obj_t socket_close(mp_obj_t self_in) { - mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in); - // There's a POSIX drama regarding return value of close in general, - // and EINTR error in particular. See e.g. - // http://lwn.net/Articles/576478/ - // http://austingroupbugs.net/view.php?id=529 - // The rationale MicroPython follows is that close() just releases - // file descriptor. If you're interested to catch I/O errors before - // closing fd, fsync() it. - close(self->fd); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_close_obj, socket_close); - -STATIC mp_obj_t socket_fileno(mp_obj_t self_in) { - mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in); - return MP_OBJ_NEW_SMALL_INT(self->fd); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_fileno_obj, socket_fileno); - -STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) { - mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in); - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(addr_in, &bufinfo, MP_BUFFER_READ); - int r = connect(self->fd, (const struct sockaddr *)bufinfo.buf, bufinfo.len); - RAISE_ERRNO(r, errno); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect); - -STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) { - mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in); - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(addr_in, &bufinfo, MP_BUFFER_READ); - int r = bind(self->fd, (const struct sockaddr *)bufinfo.buf, bufinfo.len); - RAISE_ERRNO(r, errno); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind); - -STATIC mp_obj_t socket_listen(mp_obj_t self_in, mp_obj_t backlog_in) { - mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in); - int r = listen(self->fd, MP_OBJ_SMALL_INT_VALUE(backlog_in)); - RAISE_ERRNO(r, errno); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_listen_obj, socket_listen); - -STATIC mp_obj_t socket_accept(mp_obj_t self_in) { - mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in); - // sockaddr_storage isn't stack-friendly (129 bytes or so) - //struct sockaddr_storage addr; - byte addr[32]; - socklen_t addr_len = sizeof(addr); - int fd = accept(self->fd, (struct sockaddr*)&addr, &addr_len); - RAISE_ERRNO(fd, errno); - - mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL)); - t->items[0] = MP_OBJ_FROM_PTR(socket_new(fd)); - t->items[1] = mp_obj_new_bytearray(addr_len, &addr); - - return MP_OBJ_FROM_PTR(t); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept); - -// Note: besides flag param, this differs from read() in that -// this does not swallow blocking errors (EAGAIN, EWOULDBLOCK) - -// these would be thrown as exceptions. -STATIC mp_obj_t socket_recv(size_t n_args, const mp_obj_t *args) { - mp_obj_socket_t *self = MP_OBJ_TO_PTR(args[0]); - int sz = MP_OBJ_SMALL_INT_VALUE(args[1]); - int flags = 0; - - if (n_args > 2) { - flags = MP_OBJ_SMALL_INT_VALUE(args[2]); - } - - byte *buf = m_new(byte, sz); - int out_sz = recv(self->fd, buf, sz, flags); - RAISE_ERRNO(out_sz, errno); - - mp_obj_t ret = mp_obj_new_str_of_type(&mp_type_bytes, buf, out_sz); - m_del(char, buf, sz); - return ret; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_recv_obj, 2, 3, socket_recv); - -STATIC mp_obj_t socket_recvfrom(size_t n_args, const mp_obj_t *args) { - mp_obj_socket_t *self = MP_OBJ_TO_PTR(args[0]); - int sz = MP_OBJ_SMALL_INT_VALUE(args[1]); - int flags = 0; - - if (n_args > 2) { - flags = MP_OBJ_SMALL_INT_VALUE(args[2]); - } - - struct sockaddr_storage addr; - socklen_t addr_len = sizeof(addr); - - byte *buf = m_new(byte, sz); - int out_sz = recvfrom(self->fd, buf, sz, flags, (struct sockaddr*)&addr, &addr_len); - RAISE_ERRNO(out_sz, errno); - - mp_obj_t buf_o = mp_obj_new_str_of_type(&mp_type_bytes, buf, out_sz); - m_del(char, buf, sz); - - mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL)); - t->items[0] = buf_o; - t->items[1] = mp_obj_from_sockaddr((struct sockaddr*)&addr, addr_len); - - return MP_OBJ_FROM_PTR(t); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_recvfrom_obj, 2, 3, socket_recvfrom); - -// Note: besides flag param, this differs from write() in that -// this does not swallow blocking errors (EAGAIN, EWOULDBLOCK) - -// these would be thrown as exceptions. -STATIC mp_obj_t socket_send(size_t n_args, const mp_obj_t *args) { - mp_obj_socket_t *self = MP_OBJ_TO_PTR(args[0]); - int flags = 0; - - if (n_args > 2) { - flags = MP_OBJ_SMALL_INT_VALUE(args[2]); - } - - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); - int out_sz = send(self->fd, bufinfo.buf, bufinfo.len, flags); - RAISE_ERRNO(out_sz, errno); - - return MP_OBJ_NEW_SMALL_INT(out_sz); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_send_obj, 2, 3, socket_send); - -STATIC mp_obj_t socket_sendto(size_t n_args, const mp_obj_t *args) { - mp_obj_socket_t *self = MP_OBJ_TO_PTR(args[0]); - int flags = 0; - - mp_obj_t dst_addr = args[2]; - if (n_args > 3) { - flags = MP_OBJ_SMALL_INT_VALUE(args[2]); - dst_addr = args[3]; - } - - mp_buffer_info_t bufinfo, addr_bi; - mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); - mp_get_buffer_raise(dst_addr, &addr_bi, MP_BUFFER_READ); - int out_sz = sendto(self->fd, bufinfo.buf, bufinfo.len, flags, - (struct sockaddr *)addr_bi.buf, addr_bi.len); - RAISE_ERRNO(out_sz, errno); - - return MP_OBJ_NEW_SMALL_INT(out_sz); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_sendto_obj, 3, 4, socket_sendto); - -STATIC mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) { - (void)n_args; // always 4 - mp_obj_socket_t *self = MP_OBJ_TO_PTR(args[0]); - int level = MP_OBJ_SMALL_INT_VALUE(args[1]); - int option = mp_obj_get_int(args[2]); - - const void *optval; - socklen_t optlen; - int val; - if (MP_OBJ_IS_INT(args[3])) { - val = mp_obj_int_get_truncated(args[3]); - optval = &val; - optlen = sizeof(val); - } else { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ); - optval = bufinfo.buf; - optlen = bufinfo.len; - } - int r = setsockopt(self->fd, level, option, optval, optlen); - RAISE_ERRNO(r, errno); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_setsockopt); - -STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) { - mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in); - int val = mp_obj_is_true(flag_in); - int flags = fcntl(self->fd, F_GETFL, 0); - RAISE_ERRNO(flags, errno); - if (val) { - flags &= ~O_NONBLOCK; - } else { - flags |= O_NONBLOCK; - } - flags = fcntl(self->fd, F_SETFL, flags); - RAISE_ERRNO(flags, errno); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking); - -STATIC mp_obj_t socket_makefile(size_t n_args, const mp_obj_t *args) { - // TODO: CPython explicitly says that closing returned object doesn't close - // the original socket (Python2 at all says that fd is dup()ed). But we - // save on the bloat. - mp_obj_socket_t *self = MP_OBJ_TO_PTR(args[0]); - mp_obj_t *new_args = alloca(n_args * sizeof(mp_obj_t)); - memcpy(new_args + 1, args + 1, (n_args - 1) * sizeof(mp_obj_t)); - new_args[0] = MP_OBJ_NEW_SMALL_INT(self->fd); - return mp_builtin_open(n_args, new_args, (mp_map_t*)&mp_const_empty_map); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_makefile_obj, 1, 3, socket_makefile); - -STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { - (void)type_in; - (void)n_kw; - - int family = AF_INET; - int type = SOCK_STREAM; - int proto = 0; - - if (n_args > 0) { - assert(MP_OBJ_IS_SMALL_INT(args[0])); - family = MP_OBJ_SMALL_INT_VALUE(args[0]); - if (n_args > 1) { - assert(MP_OBJ_IS_SMALL_INT(args[1])); - type = MP_OBJ_SMALL_INT_VALUE(args[1]); - if (n_args > 2) { - assert(MP_OBJ_IS_SMALL_INT(args[2])); - proto = MP_OBJ_SMALL_INT_VALUE(args[2]); - } - } - } - - int fd = socket(family, type, proto); - RAISE_ERRNO(fd, errno); - return MP_OBJ_FROM_PTR(socket_new(fd)); -} - -STATIC const mp_rom_map_elem_t usocket_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_fileno), MP_ROM_PTR(&socket_fileno_obj) }, - { MP_ROM_QSTR(MP_QSTR_makefile), MP_ROM_PTR(&socket_makefile_obj) }, - { 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_write), MP_ROM_PTR(&mp_stream_write_obj) }, - { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&socket_connect_obj) }, - { MP_ROM_QSTR(MP_QSTR_bind), MP_ROM_PTR(&socket_bind_obj) }, - { MP_ROM_QSTR(MP_QSTR_listen), MP_ROM_PTR(&socket_listen_obj) }, - { MP_ROM_QSTR(MP_QSTR_accept), MP_ROM_PTR(&socket_accept_obj) }, - { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&socket_recv_obj) }, - { MP_ROM_QSTR(MP_QSTR_recvfrom), MP_ROM_PTR(&socket_recvfrom_obj) }, - { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&socket_send_obj) }, - { MP_ROM_QSTR(MP_QSTR_sendto), MP_ROM_PTR(&socket_sendto_obj) }, - { MP_ROM_QSTR(MP_QSTR_setsockopt), MP_ROM_PTR(&socket_setsockopt_obj) }, - { MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) }, - { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&socket_close_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(usocket_locals_dict, usocket_locals_dict_table); - -STATIC const mp_stream_p_t usocket_stream_p = { - .read = socket_read, - .write = socket_write, -}; - -const mp_obj_type_t mp_type_socket = { - { &mp_type_type }, - .name = MP_QSTR_socket, - .print = socket_print, - .make_new = socket_make_new, - .getiter = NULL, - .iternext = NULL, - .protocol = &usocket_stream_p, - .locals_dict = (mp_obj_dict_t*)&usocket_locals_dict, -}; - -#if MICROPY_SOCKET_EXTRA -STATIC mp_obj_t mod_socket_htons(mp_obj_t arg) { - return MP_OBJ_NEW_SMALL_INT(htons(MP_OBJ_SMALL_INT_VALUE(arg))); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_socket_htons_obj, mod_socket_htons); - - -STATIC mp_obj_t mod_socket_gethostbyname(mp_obj_t arg) { - const char *s = mp_obj_str_get_str(arg); - struct hostent *h = gethostbyname(s); - if (h == NULL) { - // CPython: socket.herror - mp_raise_OSError(h_errno); - } - assert(h->h_length == 4); - return mp_obj_new_int(*(int*)*h->h_addr_list); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_socket_gethostbyname_obj, mod_socket_gethostbyname); -#endif // MICROPY_SOCKET_EXTRA - -#define BINADDR_MAX_LEN sizeof(struct in6_addr) -STATIC mp_obj_t mod_socket_inet_pton(mp_obj_t family_in, mp_obj_t addr_in) { - int family = mp_obj_get_int(family_in); - byte binaddr[BINADDR_MAX_LEN]; - int r = inet_pton(family, mp_obj_str_get_str(addr_in), binaddr); - RAISE_ERRNO(r, errno); - if (r == 0) { - mp_raise_OSError(MP_EINVAL); - } - int binaddr_len = 0; - switch (family) { - case AF_INET: - binaddr_len = sizeof(struct in_addr); - break; - case AF_INET6: - binaddr_len = sizeof(struct in6_addr); - break; - } - return mp_obj_new_bytes(binaddr, binaddr_len); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_socket_inet_pton_obj, mod_socket_inet_pton); - -STATIC mp_obj_t mod_socket_inet_ntop(mp_obj_t family_in, mp_obj_t binaddr_in) { - int family = mp_obj_get_int(family_in); - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(binaddr_in, &bufinfo, MP_BUFFER_READ); - vstr_t vstr; - vstr_init_len(&vstr, family == AF_INET ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN); - if (inet_ntop(family, bufinfo.buf, vstr.buf, vstr.len) == NULL) { - mp_raise_OSError(errno); - } - vstr.len = strlen(vstr.buf); - return mp_obj_new_str_from_vstr(&mp_type_str, &vstr); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_socket_inet_ntop_obj, mod_socket_inet_ntop); - -STATIC mp_obj_t mod_socket_getaddrinfo(size_t n_args, const mp_obj_t *args) { - // TODO: Implement 5th and 6th args - - const char *host = mp_obj_str_get_str(args[0]); - const char *serv = NULL; - struct addrinfo hints; - char buf[6]; - memset(&hints, 0, sizeof(hints)); - // getaddrinfo accepts port in string notation, so however - // it may seem stupid, we need to convert int to str - if (MP_OBJ_IS_SMALL_INT(args[1])) { - unsigned port = (unsigned short)MP_OBJ_SMALL_INT_VALUE(args[1]); - snprintf(buf, sizeof(buf), "%u", port); - serv = buf; - hints.ai_flags = AI_NUMERICSERV; -#ifdef __UCLIBC_MAJOR__ -#if __UCLIBC_MAJOR__ == 0 && (__UCLIBC_MINOR__ < 9 || (__UCLIBC_MINOR__ == 9 && __UCLIBC_SUBLEVEL__ <= 32)) -// "warning" requires -Wno-cpp which is a relatively new gcc option, so we choose not to use it. -//#warning Working around uClibc bug with numeric service name - // Older versions og uClibc have bugs when numeric ports in service - // arg require also hints.ai_socktype (or hints.ai_protocol) != 0 - // This actually was fixed in 0.9.32.1, but uClibc doesn't allow to - // test for that. - // http://git.uclibc.org/uClibc/commit/libc/inet/getaddrinfo.c?id=bc3be18145e4d5 - // Note that this is crude workaround, precluding UDP socket addresses - // to be returned. TODO: set only if not set by Python args. - hints.ai_socktype = SOCK_STREAM; -#endif -#endif - } else { - serv = mp_obj_str_get_str(args[1]); - } - - if (n_args > 2) { - hints.ai_family = MP_OBJ_SMALL_INT_VALUE(args[2]); - if (n_args > 3) { - hints.ai_socktype = MP_OBJ_SMALL_INT_VALUE(args[3]); - } - } - - struct addrinfo *addr_list; - int res = getaddrinfo(host, serv, &hints, &addr_list); - - if (res != 0) { - // CPython: socket.gaierror - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[addrinfo error %d]", res)); - } - assert(addr_list); - - mp_obj_t list = mp_obj_new_list(0, NULL); - for (struct addrinfo *addr = addr_list; addr; addr = addr->ai_next) { - mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(5, NULL)); - t->items[0] = MP_OBJ_NEW_SMALL_INT(addr->ai_family); - t->items[1] = MP_OBJ_NEW_SMALL_INT(addr->ai_socktype); - t->items[2] = MP_OBJ_NEW_SMALL_INT(addr->ai_protocol); - // "canonname will be a string representing the canonical name of the host - // if AI_CANONNAME is part of the flags argument; else canonname will be empty." ?? - if (addr->ai_canonname) { - t->items[3] = MP_OBJ_NEW_QSTR(qstr_from_str(addr->ai_canonname)); - } else { - t->items[3] = mp_const_none; - } - t->items[4] = mp_obj_new_bytearray(addr->ai_addrlen, addr->ai_addr); - mp_obj_list_append(list, MP_OBJ_FROM_PTR(t)); - } - freeaddrinfo(addr_list); - return list; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_socket_getaddrinfo_obj, 2, 4, mod_socket_getaddrinfo); - -STATIC mp_obj_t mod_socket_sockaddr(mp_obj_t sockaddr_in) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(sockaddr_in, &bufinfo, MP_BUFFER_READ); - switch (((struct sockaddr*)bufinfo.buf)->sa_family) { - case AF_INET: { - struct sockaddr_in *sa = (struct sockaddr_in*)bufinfo.buf; - mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL)); - t->items[0] = MP_OBJ_NEW_SMALL_INT(AF_INET); - t->items[1] = mp_obj_new_bytes((byte*)&sa->sin_addr, sizeof(sa->sin_addr)); - t->items[2] = MP_OBJ_NEW_SMALL_INT(ntohs(sa->sin_port)); - return MP_OBJ_FROM_PTR(t); - } - case AF_INET6: { - struct sockaddr_in6 *sa = (struct sockaddr_in6*)bufinfo.buf; - mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(5, NULL)); - t->items[0] = MP_OBJ_NEW_SMALL_INT(AF_INET6); - t->items[1] = mp_obj_new_bytes((byte*)&sa->sin6_addr, sizeof(sa->sin6_addr)); - t->items[2] = MP_OBJ_NEW_SMALL_INT(ntohs(sa->sin6_port)); - t->items[3] = MP_OBJ_NEW_SMALL_INT(ntohl(sa->sin6_flowinfo)); - t->items[4] = MP_OBJ_NEW_SMALL_INT(ntohl(sa->sin6_scope_id)); - return MP_OBJ_FROM_PTR(t); - } - default: { - struct sockaddr *sa = (struct sockaddr*)bufinfo.buf; - mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL)); - t->items[0] = MP_OBJ_NEW_SMALL_INT(sa->sa_family); - t->items[1] = mp_obj_new_bytes((byte*)sa->sa_data, bufinfo.len - offsetof(struct sockaddr, sa_data)); - return MP_OBJ_FROM_PTR(t); - } - } - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_socket_sockaddr_obj, mod_socket_sockaddr); - -STATIC const mp_rom_map_elem_t mp_module_socket_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usocket) }, - { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&mp_type_socket) }, - { MP_ROM_QSTR(MP_QSTR_getaddrinfo), MP_ROM_PTR(&mod_socket_getaddrinfo_obj) }, - { MP_ROM_QSTR(MP_QSTR_inet_pton), MP_ROM_PTR(&mod_socket_inet_pton_obj) }, - { MP_ROM_QSTR(MP_QSTR_inet_ntop), MP_ROM_PTR(&mod_socket_inet_ntop_obj) }, - { MP_ROM_QSTR(MP_QSTR_sockaddr), MP_ROM_PTR(&mod_socket_sockaddr_obj) }, -#if MICROPY_SOCKET_EXTRA - { MP_ROM_QSTR(MP_QSTR_htons), MP_ROM_PTR(&mod_socket_htons_obj) }, - { MP_ROM_QSTR(MP_QSTR_gethostbyname), MP_ROM_PTR(&mod_socket_gethostbyname_obj) }, -#endif - -#define C(name) { MP_ROM_QSTR(MP_QSTR_ ## name), MP_ROM_INT(name) } - C(AF_UNIX), - C(AF_INET), - C(AF_INET6), - C(SOCK_STREAM), - C(SOCK_DGRAM), - C(SOCK_RAW), - - C(MSG_DONTROUTE), - C(MSG_DONTWAIT), - - C(SOL_SOCKET), - C(SO_BROADCAST), - C(SO_ERROR), - C(SO_KEEPALIVE), - C(SO_LINGER), - C(SO_REUSEADDR), -#undef C -}; - -STATIC MP_DEFINE_CONST_DICT(mp_module_socket_globals, mp_module_socket_globals_table); - -const mp_obj_module_t mp_module_socket = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&mp_module_socket_globals, -}; diff --git a/unix/modtermios.c b/unix/modtermios.c deleted file mode 100644 index fe19aac83c..0000000000 --- a/unix/modtermios.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2014 Paul Sokolovsky - * - * 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 <sys/types.h> -#include <termios.h> -#include <unistd.h> -#include <errno.h> - -#include "py/objlist.h" -#include "py/runtime.h" -#include "py/mphal.h" - -STATIC mp_obj_t mod_termios_tcgetattr(mp_obj_t fd_in) { - struct termios term; - int fd = mp_obj_get_int(fd_in); - - int res = tcgetattr(fd, &term); - RAISE_ERRNO(res, errno); - - mp_obj_list_t *r = MP_OBJ_TO_PTR(mp_obj_new_list(7, NULL)); - r->items[0] = MP_OBJ_NEW_SMALL_INT(term.c_iflag); - r->items[1] = MP_OBJ_NEW_SMALL_INT(term.c_oflag); - r->items[2] = MP_OBJ_NEW_SMALL_INT(term.c_cflag); - r->items[3] = MP_OBJ_NEW_SMALL_INT(term.c_lflag); - r->items[4] = MP_OBJ_NEW_SMALL_INT(cfgetispeed(&term)); - r->items[5] = MP_OBJ_NEW_SMALL_INT(cfgetospeed(&term)); - - mp_obj_list_t *cc = MP_OBJ_TO_PTR(mp_obj_new_list(NCCS, NULL)); - r->items[6] = MP_OBJ_FROM_PTR(cc); - for (int i = 0; i < NCCS; i++) { - if (i == VMIN || i == VTIME) { - cc->items[i] = MP_OBJ_NEW_SMALL_INT(term.c_cc[i]); - } else { - // https://docs.python.org/3/library/termios.html says value is *string*, - // but no way unicode chars could be there, if c_cc is defined to be a - // a "char". But it's type is actually cc_t, which can be anything. - // TODO: For now, we still deal with it like that. - cc->items[i] = mp_obj_new_bytes((byte*)&term.c_cc[i], 1); - } - } - return MP_OBJ_FROM_PTR(r); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_termios_tcgetattr_obj, mod_termios_tcgetattr); - -STATIC mp_obj_t mod_termios_tcsetattr(mp_obj_t fd_in, mp_obj_t when_in, mp_obj_t attrs_in) { - struct termios term; - int fd = mp_obj_get_int(fd_in); - int when = mp_obj_get_int(when_in); - if (when == 0) { - // We don't export TCSANOW and friends to save on code space. Then - // common lazy sense says that passing 0 should be godo enough, and - // it is e.g. for glibc. But for other libc's it's not, so set just - // treat 0 as defauling to TCSANOW. - when = TCSANOW; - } - - assert(MP_OBJ_IS_TYPE(attrs_in, &mp_type_list)); - mp_obj_list_t *attrs = MP_OBJ_TO_PTR(attrs_in); - - term.c_iflag = mp_obj_get_int(attrs->items[0]); - term.c_oflag = mp_obj_get_int(attrs->items[1]); - term.c_cflag = mp_obj_get_int(attrs->items[2]); - term.c_lflag = mp_obj_get_int(attrs->items[3]); - - mp_obj_list_t *cc = MP_OBJ_TO_PTR(attrs->items[6]); - for (int i = 0; i < NCCS; i++) { - if (i == VMIN || i == VTIME) { - term.c_cc[i] = mp_obj_get_int(cc->items[i]); - } else { - term.c_cc[i] = *mp_obj_str_get_str(cc->items[i]); - } - } - - int res = cfsetispeed(&term, mp_obj_get_int(attrs->items[4])); - RAISE_ERRNO(res, errno); - res = cfsetispeed(&term, mp_obj_get_int(attrs->items[5])); - RAISE_ERRNO(res, errno); - - res = tcsetattr(fd, when, &term); - RAISE_ERRNO(res, errno); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_termios_tcsetattr_obj, mod_termios_tcsetattr); - -STATIC mp_obj_t mod_termios_setraw(mp_obj_t fd_in) { - struct termios term; - int fd = mp_obj_get_int(fd_in); - int res = tcgetattr(fd, &term); - RAISE_ERRNO(res, errno); - - term.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); - term.c_oflag = 0; - term.c_cflag = (term.c_cflag & ~(CSIZE | PARENB)) | CS8; - term.c_lflag = 0; - term.c_cc[VMIN] = 1; - term.c_cc[VTIME] = 0; - res = tcsetattr(fd, TCSAFLUSH, &term); - RAISE_ERRNO(res, errno); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_termios_setraw_obj, mod_termios_setraw); - -STATIC const mp_rom_map_elem_t mp_module_termios_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_termios) }, - { MP_ROM_QSTR(MP_QSTR_tcgetattr), MP_ROM_PTR(&mod_termios_tcgetattr_obj) }, - { MP_ROM_QSTR(MP_QSTR_tcsetattr), MP_ROM_PTR(&mod_termios_tcsetattr_obj) }, - { MP_ROM_QSTR(MP_QSTR_setraw), MP_ROM_PTR(&mod_termios_setraw_obj) }, - -#define C(name) { MP_ROM_QSTR(MP_QSTR_ ## name), MP_ROM_INT(name) } - C(TCSANOW), - - C(B9600), - #ifdef B57600 - C(B57600), - #endif - #ifdef B115200 - C(B115200), - #endif -#undef C -}; - -STATIC MP_DEFINE_CONST_DICT(mp_module_termios_globals, mp_module_termios_globals_table); - -const mp_obj_module_t mp_module_termios = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&mp_module_termios_globals, -}; diff --git a/unix/modtime.c b/unix/modtime.c deleted file mode 100644 index a74b81f374..0000000000 --- a/unix/modtime.c +++ /dev/null @@ -1,185 +0,0 @@ -/* - * 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 "py/mpconfig.h" -#if MICROPY_PY_UTIME - -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <time.h> -#include <sys/time.h> -#include <math.h> - -#include "py/runtime.h" -#include "py/smallint.h" -#include "py/mphal.h" -#include "extmod/utime_mphal.h" - -#ifdef _WIN32 -static inline int msec_sleep_tv(struct timeval *tv) { - msec_sleep(tv->tv_sec * 1000.0 + tv->tv_usec / 1000.0); - return 0; -} -#define sleep_select(a,b,c,d,e) msec_sleep_tv((e)) -#else -#define sleep_select select -#endif - -// mingw32 defines CLOCKS_PER_SEC as ((clock_t)<somevalue>) but preprocessor does not handle casts -#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) -#define MP_REMOVE_BRACKETSA(x) -#define MP_REMOVE_BRACKETSB(x) MP_REMOVE_BRACKETSA x -#define MP_REMOVE_BRACKETSC(x) MP_REMOVE_BRACKETSB x -#define MP_CLOCKS_PER_SEC MP_REMOVE_BRACKETSC(CLOCKS_PER_SEC) -#else -#define MP_CLOCKS_PER_SEC CLOCKS_PER_SEC -#endif - -#if defined(MP_CLOCKS_PER_SEC) -#define CLOCK_DIV (MP_CLOCKS_PER_SEC / 1000.0F) -#else -#error Unsupported clock() implementation -#endif - -STATIC mp_obj_t mod_time_time(void) { -#if MICROPY_PY_BUILTINS_FLOAT - struct timeval tv; - gettimeofday(&tv, NULL); - mp_float_t val = tv.tv_sec + (mp_float_t)tv.tv_usec / 1000000; - return mp_obj_new_float(val); -#else - return mp_obj_new_int((mp_int_t)time(NULL)); -#endif -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_time_time_obj, mod_time_time); - -// Note: this is deprecated since CPy3.3, but pystone still uses it. -STATIC mp_obj_t mod_time_clock(void) { -#if MICROPY_PY_BUILTINS_FLOAT - // float cannot represent full range of int32 precisely, so we pre-divide - // int to reduce resolution, and then actually do float division hoping - // to preserve integer part resolution. - return mp_obj_new_float((float)(clock() / 1000) / CLOCK_DIV); -#else - return mp_obj_new_int((mp_int_t)clock()); -#endif -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_time_clock_obj, mod_time_clock); - -STATIC mp_obj_t mod_time_sleep(mp_obj_t arg) { -#if MICROPY_PY_BUILTINS_FLOAT - struct timeval tv; - mp_float_t val = mp_obj_get_float(arg); - double ipart; - tv.tv_usec = round(modf(val, &ipart) * 1000000); - tv.tv_sec = ipart; - int res; - while (1) { - MP_THREAD_GIL_EXIT(); - res = sleep_select(0, NULL, NULL, NULL, &tv); - MP_THREAD_GIL_ENTER(); - #if MICROPY_SELECT_REMAINING_TIME - // TODO: This assumes Linux behavior of modifying tv to the remaining - // time. - if (res != -1 || errno != EINTR) { - break; - } - mp_handle_pending(); - //printf("select: EINTR: %ld:%ld\n", tv.tv_sec, tv.tv_usec); - #else - break; - #endif - } - RAISE_ERRNO(res, errno); -#else - // TODO: Handle EINTR - MP_THREAD_GIL_EXIT(); - sleep(mp_obj_get_int(arg)); - MP_THREAD_GIL_ENTER(); -#endif - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_time_sleep_obj, mod_time_sleep); - -STATIC mp_obj_t mod_time_localtime(size_t n_args, const mp_obj_t *args) { - time_t t; - if (n_args == 0) { - t = time(NULL); - } else { - #if MICROPY_PY_BUILTINS_FLOAT - mp_float_t val = mp_obj_get_float(args[0]); - t = (time_t)MICROPY_FLOAT_C_FUN(trunc)(val); - #else - t = mp_obj_get_int(args[0]); - #endif - } - struct tm *tm = localtime(&t); - - mp_obj_t ret = mp_obj_new_tuple(9, NULL); - - mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(ret); - tuple->items[0] = MP_OBJ_NEW_SMALL_INT(tm->tm_year + 1900); - tuple->items[1] = MP_OBJ_NEW_SMALL_INT(tm->tm_mon + 1); - tuple->items[2] = MP_OBJ_NEW_SMALL_INT(tm->tm_mday); - tuple->items[3] = MP_OBJ_NEW_SMALL_INT(tm->tm_hour); - tuple->items[4] = MP_OBJ_NEW_SMALL_INT(tm->tm_min); - tuple->items[5] = MP_OBJ_NEW_SMALL_INT(tm->tm_sec); - int wday = tm->tm_wday - 1; - if (wday < 0) { - wday = 6; - } - tuple->items[6] = MP_OBJ_NEW_SMALL_INT(wday); - tuple->items[7] = MP_OBJ_NEW_SMALL_INT(tm->tm_yday + 1); - tuple->items[8] = MP_OBJ_NEW_SMALL_INT(tm->tm_isdst); - - return ret; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_time_localtime_obj, 0, 1, mod_time_localtime); - -STATIC const mp_rom_map_elem_t mp_module_time_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime) }, - { MP_ROM_QSTR(MP_QSTR_clock), MP_ROM_PTR(&mod_time_clock_obj) }, - { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&mod_time_sleep_obj) }, - { MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mp_utime_sleep_ms_obj) }, - { MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mp_utime_sleep_us_obj) }, - { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&mod_time_time_obj) }, - { MP_ROM_QSTR(MP_QSTR_ticks_ms), MP_ROM_PTR(&mp_utime_ticks_ms_obj) }, - { MP_ROM_QSTR(MP_QSTR_ticks_us), MP_ROM_PTR(&mp_utime_ticks_us_obj) }, - { MP_ROM_QSTR(MP_QSTR_ticks_cpu), MP_ROM_PTR(&mp_utime_ticks_cpu_obj) }, - { MP_ROM_QSTR(MP_QSTR_ticks_add), MP_ROM_PTR(&mp_utime_ticks_add_obj) }, - { MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mp_utime_ticks_diff_obj) }, - { MP_ROM_QSTR(MP_QSTR_localtime), MP_ROM_PTR(&mod_time_localtime_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(mp_module_time_globals, mp_module_time_globals_table); - -const mp_obj_module_t mp_module_time = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&mp_module_time_globals, -}; - -#endif // MICROPY_PY_UTIME diff --git a/unix/modules/upip.py b/unix/modules/upip.py deleted file mode 120000 index 20d52a4ab7..0000000000 --- a/unix/modules/upip.py +++ /dev/null @@ -1 +0,0 @@ -../../tools/upip.py
\ No newline at end of file diff --git a/unix/modules/upip_utarfile.py b/unix/modules/upip_utarfile.py deleted file mode 120000 index 1498862916..0000000000 --- a/unix/modules/upip_utarfile.py +++ /dev/null @@ -1 +0,0 @@ -../../tools/upip_utarfile.py
\ No newline at end of file diff --git a/unix/moduos_vfs.c b/unix/moduos_vfs.c deleted file mode 100644 index 96defa5544..0000000000 --- a/unix/moduos_vfs.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 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 <stdint.h> -#include <string.h> - -#include "extmod/vfs.h" -#include "extmod/vfs_fat.h" - -#if MICROPY_VFS - -STATIC const mp_rom_map_elem_t uos_vfs_module_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos_vfs) }, - { MP_ROM_QSTR(MP_QSTR_sep), MP_ROM_QSTR(MP_QSTR__slash_) }, - - { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) }, - { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&mp_vfs_umount_obj) }, - { MP_ROM_QSTR(MP_QSTR_vfs_open), MP_ROM_PTR(&mp_vfs_open_obj) }, - - { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) }, - { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_vfs_getcwd_obj) }, - { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mp_vfs_ilistdir_obj) }, - { MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) }, - { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mp_vfs_mkdir_obj) }, - { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mp_vfs_remove_obj) }, - { MP_ROM_QSTR(MP_QSTR_rename),MP_ROM_PTR(&mp_vfs_rename_obj) }, - { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&mp_vfs_rmdir_obj) }, - { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&mp_vfs_stat_obj) }, - { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&mp_vfs_statvfs_obj) }, - { MP_ROM_QSTR(MP_QSTR_unlink), MP_ROM_PTR(&mp_vfs_remove_obj) }, // unlink aliases to remove - - #if MICROPY_VFS_FAT - { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) }, - #endif -}; - -STATIC MP_DEFINE_CONST_DICT(uos_vfs_module_globals, uos_vfs_module_globals_table); - -const mp_obj_module_t mp_module_uos_vfs = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&uos_vfs_module_globals, -}; - -#endif // MICROPY_VFS diff --git a/unix/moduselect.c b/unix/moduselect.c deleted file mode 100644 index ba1c195ef4..0000000000 --- a/unix/moduselect.c +++ /dev/null @@ -1,330 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2014 Damien P. George - * Copyright (c) 2015-2017 Paul Sokolovsky - * - * 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 "py/mpconfig.h" - -#if MICROPY_PY_USELECT_POSIX - -#include <stdio.h> -#include <errno.h> -#include <poll.h> - -#include "py/runtime.h" -#include "py/obj.h" -#include "py/objlist.h" -#include "py/objtuple.h" -#include "py/mphal.h" -#include "fdfile.h" - -#if MICROPY_PY_SOCKET -extern const mp_obj_type_t mp_type_socket; -#endif - -// Flags for poll() -#define FLAG_ONESHOT (1) - -/// \class Poll - poll class - -typedef struct _mp_obj_poll_t { - mp_obj_base_t base; - unsigned short alloc; - unsigned short len; - struct pollfd *entries; - mp_obj_t *obj_map; - short iter_cnt; - short iter_idx; - int flags; - // callee-owned tuple - mp_obj_t ret_tuple; -} mp_obj_poll_t; - -STATIC int get_fd(mp_obj_t fdlike) { - int fd; - // Shortcut for fdfile compatible types - if (MP_OBJ_IS_TYPE(fdlike, &mp_type_fileio) - #if MICROPY_PY_SOCKET - || MP_OBJ_IS_TYPE(fdlike, &mp_type_socket) - #endif - ) { - mp_obj_fdfile_t *fdfile = MP_OBJ_TO_PTR(fdlike); - fd = fdfile->fd; - } else { - fd = mp_obj_get_int(fdlike); - } - return fd; -} - -/// \method register(obj[, eventmask]) -STATIC mp_obj_t poll_register(size_t n_args, const mp_obj_t *args) { - mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]); - bool is_fd = MP_OBJ_IS_INT(args[1]); - int fd = get_fd(args[1]); - - mp_uint_t flags; - if (n_args == 3) { - flags = mp_obj_get_int(args[2]); - } else { - flags = POLLIN | POLLOUT; - } - - struct pollfd *free_slot = NULL; - - struct pollfd *entry = self->entries; - for (int i = 0; i < self->len; i++, entry++) { - int entry_fd = entry->fd; - if (entry_fd == fd) { - entry->events = flags; - return mp_const_false; - } - if (entry_fd == -1) { - free_slot = entry; - } - } - - if (free_slot == NULL) { - if (self->len >= self->alloc) { - self->entries = m_renew(struct pollfd, self->entries, self->alloc, self->alloc + 4); - if (self->obj_map) { - self->obj_map = m_renew(mp_obj_t, self->obj_map, self->alloc, self->alloc + 4); - } - self->alloc += 4; - } - free_slot = &self->entries[self->len++]; - } - - if (!is_fd) { - if (self->obj_map == NULL) { - self->obj_map = m_new0(mp_obj_t, self->alloc); - } - self->obj_map[free_slot - self->entries] = args[1]; - } - - free_slot->fd = fd; - free_slot->events = flags; - free_slot->revents = 0; - return mp_const_true; -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_register_obj, 2, 3, poll_register); - -/// \method unregister(obj) -STATIC mp_obj_t poll_unregister(mp_obj_t self_in, mp_obj_t obj_in) { - mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in); - struct pollfd *entries = self->entries; - int fd = get_fd(obj_in); - for (int i = self->len - 1; i >= 0; i--) { - if (entries->fd == fd) { - entries->fd = -1; - if (self->obj_map) { - self->obj_map[entries - self->entries] = MP_OBJ_NULL; - } - break; - } - entries++; - } - - // TODO raise KeyError if obj didn't exist in map - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_2(poll_unregister_obj, poll_unregister); - -/// \method modify(obj, eventmask) -STATIC mp_obj_t poll_modify(mp_obj_t self_in, mp_obj_t obj_in, mp_obj_t eventmask_in) { - mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in); - struct pollfd *entries = self->entries; - int fd = get_fd(obj_in); - for (int i = self->len - 1; i >= 0; i--) { - if (entries->fd == fd) { - entries->events = mp_obj_get_int(eventmask_in); - break; - } - entries++; - } - - // TODO raise KeyError if obj didn't exist in map - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_3(poll_modify_obj, poll_modify); - -STATIC int poll_poll_internal(size_t n_args, const mp_obj_t *args) { - mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]); - - // work out timeout (it's given already in ms) - int timeout = -1; - int flags = 0; - if (n_args >= 2) { - if (args[1] != mp_const_none) { - mp_int_t timeout_i = mp_obj_get_int(args[1]); - if (timeout_i >= 0) { - timeout = timeout_i; - } - } - if (n_args >= 3) { - flags = mp_obj_get_int(args[2]); - } - } - - self->flags = flags; - - int n_ready = poll(self->entries, self->len, timeout); - RAISE_ERRNO(n_ready, errno); - return n_ready; -} - -/// \method poll([timeout]) -/// Timeout is in milliseconds. -STATIC mp_obj_t poll_poll(size_t n_args, const mp_obj_t *args) { - int n_ready = poll_poll_internal(n_args, args); - - if (n_ready == 0) { - return mp_const_empty_tuple; - } - - mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]); - - mp_obj_list_t *ret_list = MP_OBJ_TO_PTR(mp_obj_new_list(n_ready, NULL)); - int ret_i = 0; - struct pollfd *entries = self->entries; - for (int i = 0; i < self->len; i++, entries++) { - if (entries->revents != 0) { - mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL)); - // If there's an object stored, return it, otherwise raw fd - if (self->obj_map && self->obj_map[i] != MP_OBJ_NULL) { - t->items[0] = self->obj_map[i]; - } else { - t->items[0] = MP_OBJ_NEW_SMALL_INT(entries->fd); - } - t->items[1] = MP_OBJ_NEW_SMALL_INT(entries->revents); - ret_list->items[ret_i++] = MP_OBJ_FROM_PTR(t); - if (self->flags & FLAG_ONESHOT) { - entries->events = 0; - } - } - } - - return MP_OBJ_FROM_PTR(ret_list); -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_poll_obj, 1, 3, poll_poll); - -STATIC mp_obj_t poll_ipoll(size_t n_args, const mp_obj_t *args) { - mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]); - - if (self->ret_tuple == MP_OBJ_NULL) { - self->ret_tuple = mp_obj_new_tuple(2, NULL); - } - - int n_ready = poll_poll_internal(n_args, args); - self->iter_cnt = n_ready; - self->iter_idx = 0; - - return args[0]; -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_ipoll_obj, 1, 3, poll_ipoll); - -STATIC mp_obj_t poll_iternext(mp_obj_t self_in) { - mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in); - - if (self->iter_cnt == 0) { - return MP_OBJ_STOP_ITERATION; - } - - self->iter_cnt--; - - struct pollfd *entries = self->entries + self->iter_idx; - for (int i = self->iter_idx; i < self->len; i++, entries++) { - self->iter_idx++; - if (entries->revents != 0) { - mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->ret_tuple); - // If there's an object stored, return it, otherwise raw fd - if (self->obj_map && self->obj_map[i] != MP_OBJ_NULL) { - t->items[0] = self->obj_map[i]; - } else { - t->items[0] = MP_OBJ_NEW_SMALL_INT(entries->fd); - } - t->items[1] = MP_OBJ_NEW_SMALL_INT(entries->revents); - if (self->flags & FLAG_ONESHOT) { - entries->events = 0; - } - return MP_OBJ_FROM_PTR(t); - } - } - - assert(!"inconsistent number of poll active entries"); - self->iter_cnt = 0; - return MP_OBJ_STOP_ITERATION; -} - -STATIC const mp_rom_map_elem_t poll_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_register), MP_ROM_PTR(&poll_register_obj) }, - { MP_ROM_QSTR(MP_QSTR_unregister), MP_ROM_PTR(&poll_unregister_obj) }, - { MP_ROM_QSTR(MP_QSTR_modify), MP_ROM_PTR(&poll_modify_obj) }, - { MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&poll_poll_obj) }, - { MP_ROM_QSTR(MP_QSTR_ipoll), MP_ROM_PTR(&poll_ipoll_obj) }, -}; -STATIC MP_DEFINE_CONST_DICT(poll_locals_dict, poll_locals_dict_table); - -STATIC const mp_obj_type_t mp_type_poll = { - { &mp_type_type }, - .name = MP_QSTR_poll, - .getiter = mp_identity_getiter, - .iternext = poll_iternext, - .locals_dict = (void*)&poll_locals_dict, -}; - -STATIC mp_obj_t select_poll(size_t n_args, const mp_obj_t *args) { - int alloc = 4; - if (n_args > 0) { - alloc = mp_obj_get_int(args[0]); - } - mp_obj_poll_t *poll = m_new_obj(mp_obj_poll_t); - poll->base.type = &mp_type_poll; - poll->entries = m_new(struct pollfd, alloc); - poll->alloc = alloc; - poll->len = 0; - poll->obj_map = NULL; - poll->iter_cnt = 0; - poll->ret_tuple = MP_OBJ_NULL; - return MP_OBJ_FROM_PTR(poll); -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_select_poll_obj, 0, 1, select_poll); - -STATIC const mp_rom_map_elem_t mp_module_select_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uselect) }, - { MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&mp_select_poll_obj) }, - { MP_ROM_QSTR(MP_QSTR_POLLIN), MP_ROM_INT(POLLIN) }, - { MP_ROM_QSTR(MP_QSTR_POLLOUT), MP_ROM_INT(POLLOUT) }, - { MP_ROM_QSTR(MP_QSTR_POLLERR), MP_ROM_INT(POLLERR) }, - { MP_ROM_QSTR(MP_QSTR_POLLHUP), MP_ROM_INT(POLLHUP) }, -}; - -STATIC MP_DEFINE_CONST_DICT(mp_module_select_globals, mp_module_select_globals_table); - -const mp_obj_module_t mp_module_uselect = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&mp_module_select_globals, -}; - -#endif // MICROPY_PY_USELECT_POSIX diff --git a/unix/mpconfigport.h b/unix/mpconfigport.h deleted file mode 100644 index b557f3d448..0000000000 --- a/unix/mpconfigport.h +++ /dev/null @@ -1,318 +0,0 @@ -/* - * 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. - */ - -// options to control how MicroPython is built - -#define MICROPY_ALLOC_PATH_MAX (PATH_MAX) -#define MICROPY_PERSISTENT_CODE_LOAD (1) -#if !defined(MICROPY_EMIT_X64) && defined(__x86_64__) - #define MICROPY_EMIT_X64 (1) -#endif -#if !defined(MICROPY_EMIT_X86) && defined(__i386__) - #define MICROPY_EMIT_X86 (1) -#endif -#if !defined(MICROPY_EMIT_THUMB) && defined(__thumb2__) - #define MICROPY_EMIT_THUMB (1) - #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1)) -#endif -// Some compilers define __thumb2__ and __arm__ at the same time, let -// autodetected thumb2 emitter have priority. -#if !defined(MICROPY_EMIT_ARM) && defined(__arm__) && !defined(__thumb2__) - #define MICROPY_EMIT_ARM (1) -#endif -#define MICROPY_COMP_MODULE_CONST (1) -#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1) -#define MICROPY_COMP_RETURN_IF_EXPR (1) -#define MICROPY_ENABLE_GC (1) -#define MICROPY_ENABLE_FINALISER (1) -#define MICROPY_STACK_CHECK (1) -#define MICROPY_MALLOC_USES_ALLOCATED_SIZE (1) -#define MICROPY_MEM_STATS (1) -#define MICROPY_DEBUG_PRINTERS (1) -// Printing debug to stderr may give tests which -// check stdout a chance to pass, etc. -#define MICROPY_DEBUG_PRINTER_DEST mp_stderr_print -#define MICROPY_READER_POSIX (1) -#define MICROPY_USE_READLINE_HISTORY (1) -#define MICROPY_HELPER_REPL (1) -#define MICROPY_REPL_EMACS_KEYS (1) -#define MICROPY_REPL_AUTO_INDENT (1) -#define MICROPY_HELPER_LEXER_UNIX (1) -#define MICROPY_ENABLE_SOURCE_LINE (1) -#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) -#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) -#define MICROPY_STREAMS_NON_BLOCK (1) -#define MICROPY_STREAMS_POSIX_API (1) -#define MICROPY_OPT_COMPUTED_GOTO (1) -#ifndef MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE -#define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (1) -#endif -#define MICROPY_CAN_OVERRIDE_BUILTINS (1) -#define MICROPY_PY_FUNCTION_ATTRS (1) -#define MICROPY_PY_DESCRIPTORS (1) -#define MICROPY_PY_BUILTINS_STR_UNICODE (1) -#define MICROPY_PY_BUILTINS_STR_CENTER (1) -#define MICROPY_PY_BUILTINS_STR_PARTITION (1) -#define MICROPY_PY_BUILTINS_STR_SPLITLINES (1) -#define MICROPY_PY_BUILTINS_MEMORYVIEW (1) -#define MICROPY_PY_BUILTINS_FROZENSET (1) -#define MICROPY_PY_BUILTINS_COMPILE (1) -#define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (1) -#define MICROPY_PY_BUILTINS_INPUT (1) -#define MICROPY_PY_BUILTINS_POW3 (1) -#define MICROPY_PY_MICROPYTHON_MEM_INFO (1) -#define MICROPY_PY_ALL_SPECIAL_METHODS (1) -#define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) -#define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) -#define MICROPY_PY_SYS_EXIT (1) -#if defined(__APPLE__) && defined(__MACH__) - #define MICROPY_PY_SYS_PLATFORM "darwin" -#else - #define MICROPY_PY_SYS_PLATFORM "linux" -#endif -#define MICROPY_PY_SYS_MAXSIZE (1) -#define MICROPY_PY_SYS_STDFILES (1) -#define MICROPY_PY_SYS_EXC_INFO (1) -#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1) -#ifndef MICROPY_PY_MATH_SPECIAL_FUNCTIONS -#define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (1) -#endif -#define MICROPY_PY_CMATH (1) -#define MICROPY_PY_IO_FILEIO (1) -#define MICROPY_PY_IO_RESOURCE_STREAM (1) -#define MICROPY_PY_GC_COLLECT_RETVAL (1) -#define MICROPY_MODULE_FROZEN_STR (1) - -#define MICROPY_STACKLESS (0) -#define MICROPY_STACKLESS_STRICT (0) - -#define MICROPY_PY_OS_STATVFS (1) -#define MICROPY_PY_UTIME (1) -#define MICROPY_PY_UTIME_MP_HAL (1) -#define MICROPY_PY_UERRNO (1) -#define MICROPY_PY_UCTYPES (1) -#define MICROPY_PY_UZLIB (1) -#define MICROPY_PY_UJSON (1) -#define MICROPY_PY_URE (1) -#define MICROPY_PY_UHEAPQ (1) -#define MICROPY_PY_UTIMEQ (1) -#define MICROPY_PY_UHASHLIB (1) -#if MICROPY_PY_USSL && MICROPY_SSL_AXTLS -#define MICROPY_PY_UHASHLIB_SHA1 (1) -#endif -#define MICROPY_PY_UBINASCII (1) -#define MICROPY_PY_UBINASCII_CRC32 (1) -#define MICROPY_PY_URANDOM (1) -#ifndef MICROPY_PY_USELECT_POSIX -#define MICROPY_PY_USELECT_POSIX (1) -#endif -#define MICROPY_PY_WEBSOCKET (1) -#define MICROPY_PY_MACHINE (1) -#define MICROPY_PY_MACHINE_PULSE (1) -#define MICROPY_MACHINE_MEM_GET_READ_ADDR mod_machine_mem_get_addr -#define MICROPY_MACHINE_MEM_GET_WRITE_ADDR mod_machine_mem_get_addr - -#define MICROPY_FATFS_ENABLE_LFN (1) -#define MICROPY_FATFS_RPATH (2) -#define MICROPY_FATFS_MAX_SS (4096) -#define MICROPY_FATFS_LFN_CODE_PAGE (437) /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ -#define MICROPY_VFS_FAT (0) - -// Define to MICROPY_ERROR_REPORTING_DETAILED to get function, etc. -// names in exception messages (may require more RAM). -#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_DETAILED) -#define MICROPY_WARNINGS (1) -#define MICROPY_PY_STR_BYTES_CMP_WARN (1) - -// Define to 1 to use undertested inefficient GC helper implementation -// (if more efficient arch-specific one is not available). -#ifndef MICROPY_GCREGS_SETJMP - #ifdef __mips__ - #define MICROPY_GCREGS_SETJMP (1) - #else - #define MICROPY_GCREGS_SETJMP (0) - #endif -#endif - -#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) -#define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (256) -#define MICROPY_KBD_EXCEPTION (1) -#define MICROPY_ASYNC_KBD_INTR (1) - -extern const struct _mp_obj_module_t mp_module_machine; -extern const struct _mp_obj_module_t mp_module_os; -extern const struct _mp_obj_module_t mp_module_uos_vfs; -extern const struct _mp_obj_module_t mp_module_uselect; -extern const struct _mp_obj_module_t mp_module_time; -extern const struct _mp_obj_module_t mp_module_termios; -extern const struct _mp_obj_module_t mp_module_socket; -extern const struct _mp_obj_module_t mp_module_ffi; -extern const struct _mp_obj_module_t mp_module_jni; - -#if MICROPY_PY_UOS_VFS -#define MICROPY_PY_UOS_VFS_DEF { MP_ROM_QSTR(MP_QSTR_uos_vfs), MP_ROM_PTR(&mp_module_uos_vfs) }, -#else -#define MICROPY_PY_UOS_VFS_DEF -#endif -#if MICROPY_PY_FFI -#define MICROPY_PY_FFI_DEF { MP_ROM_QSTR(MP_QSTR_ffi), MP_ROM_PTR(&mp_module_ffi) }, -#else -#define MICROPY_PY_FFI_DEF -#endif -#if MICROPY_PY_JNI -#define MICROPY_PY_JNI_DEF { MP_ROM_QSTR(MP_QSTR_jni), MP_ROM_PTR(&mp_module_jni) }, -#else -#define MICROPY_PY_JNI_DEF -#endif -#if MICROPY_PY_UTIME -#define MICROPY_PY_UTIME_DEF { MP_ROM_QSTR(MP_QSTR_utime), MP_ROM_PTR(&mp_module_time) }, -#else -#define MICROPY_PY_UTIME_DEF -#endif -#if MICROPY_PY_TERMIOS -#define MICROPY_PY_TERMIOS_DEF { MP_ROM_QSTR(MP_QSTR_termios), MP_ROM_PTR(&mp_module_termios) }, -#else -#define MICROPY_PY_TERMIOS_DEF -#endif -#if MICROPY_PY_SOCKET -#define MICROPY_PY_SOCKET_DEF { MP_ROM_QSTR(MP_QSTR_usocket), MP_ROM_PTR(&mp_module_socket) }, -#else -#define MICROPY_PY_SOCKET_DEF -#endif -#if MICROPY_PY_USELECT_POSIX -#define MICROPY_PY_USELECT_DEF { MP_ROM_QSTR(MP_QSTR_uselect), MP_ROM_PTR(&mp_module_uselect) }, -#else -#define MICROPY_PY_USELECT_DEF -#endif - -#define MICROPY_PORT_BUILTIN_MODULES \ - MICROPY_PY_FFI_DEF \ - MICROPY_PY_JNI_DEF \ - MICROPY_PY_UTIME_DEF \ - MICROPY_PY_SOCKET_DEF \ - { MP_ROM_QSTR(MP_QSTR_umachine), MP_ROM_PTR(&mp_module_machine) }, \ - { MP_ROM_QSTR(MP_QSTR_uos), MP_ROM_PTR(&mp_module_os) }, \ - MICROPY_PY_UOS_VFS_DEF \ - MICROPY_PY_USELECT_DEF \ - MICROPY_PY_TERMIOS_DEF \ - -// type definitions for the specific machine - -// For size_t and ssize_t -#include <unistd.h> - -// assume that if we already defined the obj repr then we also defined types -#ifndef MICROPY_OBJ_REPR -#ifdef __LP64__ -typedef long mp_int_t; // must be pointer size -typedef unsigned long mp_uint_t; // must be pointer size -#else -// These are definitions for machines where sizeof(int) == sizeof(void*), -// regardless of actual size. -typedef int mp_int_t; // must be pointer size -typedef unsigned int mp_uint_t; // must be pointer size -#endif -#endif - -// Cannot include <sys/types.h>, as it may lead to symbol name clashes -#if _FILE_OFFSET_BITS == 64 && !defined(__LP64__) -typedef long long mp_off_t; -#else -typedef long mp_off_t; -#endif - -void mp_unix_alloc_exec(size_t min_size, void** ptr, size_t *size); -void mp_unix_free_exec(void *ptr, size_t size); -void mp_unix_mark_exec(void); -#define MP_PLAT_ALLOC_EXEC(min_size, ptr, size) mp_unix_alloc_exec(min_size, ptr, size) -#define MP_PLAT_FREE_EXEC(ptr, size) mp_unix_free_exec(ptr, size) -#ifndef MICROPY_FORCE_PLAT_ALLOC_EXEC -// Use MP_PLAT_ALLOC_EXEC for any executable memory allocation, including for FFI -// (overriding libffi own implementation) -#define MICROPY_FORCE_PLAT_ALLOC_EXEC (1) -#endif - -#if MICROPY_PY_OS_DUPTERM -#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) -#else -#define MP_PLAT_PRINT_STRN(str, len) do { ssize_t ret = write(1, str, len); (void)ret; } while (0) -#endif - -#ifdef __linux__ -// Can access physical memory using /dev/mem -#define MICROPY_PLAT_DEV_MEM (1) -#endif - -// Assume that select() call, interrupted with a signal, and erroring -// with EINTR, updates remaining timeout value. -#define MICROPY_SELECT_REMAINING_TIME (1) - -#ifdef __ANDROID__ -#include <android/api-level.h> -#if __ANDROID_API__ < 4 -// Bionic libc in Android 1.5 misses these 2 functions -#define MP_NEED_LOG2 (1) -#define nan(x) NAN -#endif -#endif - -#define MICROPY_PORT_BUILTINS \ - { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mp_builtin_open_obj) }, - -#define MP_STATE_PORT MP_STATE_VM - -#define MICROPY_PORT_ROOT_POINTERS \ - const char *readline_hist[50]; \ - void *mmap_region_head; \ - -// We need to provide a declaration/definition of alloca() -// unless support for it is disabled. -#if !defined(MICROPY_NO_ALLOCA) || MICROPY_NO_ALLOCA == 0 -#ifdef __FreeBSD__ -#include <stdlib.h> -#else -#include <alloca.h> -#endif -#endif - -// From "man readdir": "Under glibc, programs can check for the availability -// of the fields [in struct dirent] not defined in POSIX.1 by testing whether -// the macros [...], _DIRENT_HAVE_D_TYPE are defined." -// Other libc's don't define it, but proactively assume that dirent->d_type -// is available on a modern *nix system. -#ifndef _DIRENT_HAVE_D_TYPE -#define _DIRENT_HAVE_D_TYPE (1) -#endif -// This macro is not provided by glibc but we need it so ports that don't have -// dirent->d_ino can disable the use of this field. -#ifndef _DIRENT_HAVE_D_INO -#define _DIRENT_HAVE_D_INO (1) -#endif - -#ifndef __APPLE__ -// For debugging purposes, make printf() available to any source file. -#include <stdio.h> -#endif diff --git a/unix/mpconfigport.mk b/unix/mpconfigport.mk deleted file mode 100644 index f0aa955c0c..0000000000 --- a/unix/mpconfigport.mk +++ /dev/null @@ -1,42 +0,0 @@ -# Enable/disable modules and 3rd-party libs to be included in interpreter - -# Build 32-bit binaries on a 64-bit host -MICROPY_FORCE_32BIT = 0 - -# This variable can take the following values: -# 0 - no readline, just simple stdin input -# 1 - use MicroPython version of readline -MICROPY_USE_READLINE = 1 - -# btree module using Berkeley DB 1.xx -MICROPY_PY_BTREE = 1 - -# _thread module using pthreads -MICROPY_PY_THREAD = 1 - -# Subset of CPython termios module -MICROPY_PY_TERMIOS = 1 - -# Subset of CPython socket module -MICROPY_PY_SOCKET = 1 - -# ffi module requires libffi (libffi-dev Debian package) -MICROPY_PY_FFI = 1 - -# ussl module requires one of the TLS libraries below -MICROPY_PY_USSL = 1 -# axTLS has minimal size and fully integrated with MicroPython, but -# implements only a subset of modern TLS functionality, so may have -# problems with some servers. -MICROPY_SSL_AXTLS = 1 -# mbedTLS is more up to date and complete implementation, but also -# more bloated. Configuring and building of mbedTLS should be done -# outside of MicroPython, it can just link with mbedTLS library. -MICROPY_SSL_MBEDTLS = 0 - -# jni module requires JVM/JNI -MICROPY_PY_JNI = 0 - -# Avoid using system libraries, use copies bundled with MicroPython -# as submodules (currently affects only libffi). -MICROPY_STANDALONE = 0 diff --git a/unix/mpconfigport_coverage.h b/unix/mpconfigport_coverage.h deleted file mode 100644 index a9e0a38fa0..0000000000 --- a/unix/mpconfigport_coverage.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013-2016 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. - */ - -// Default unix config while intended to be comprehensive, may still not enable -// all the features, this config should enable more (testable) options. - -#define MICROPY_VFS (1) -#define MICROPY_PY_UOS_VFS (1) - -#include <mpconfigport.h> - -#define MICROPY_FLOAT_HIGH_QUALITY_HASH (1) -#define MICROPY_ENABLE_SCHEDULER (1) -#define MICROPY_PY_DELATTR_SETATTR (1) -#define MICROPY_PY_BUILTINS_HELP (1) -#define MICROPY_PY_BUILTINS_HELP_MODULES (1) -#define MICROPY_PY_SYS_GETSIZEOF (1) -#define MICROPY_PY_URANDOM_EXTRA_FUNCS (1) -#define MICROPY_PY_IO_BUFFEREDWRITER (1) -#undef MICROPY_VFS_FAT -#define MICROPY_VFS_FAT (1) -#define MICROPY_PY_FRAMEBUF (1) diff --git a/unix/mpconfigport_fast.h b/unix/mpconfigport_fast.h deleted file mode 100644 index 442159eb4f..0000000000 --- a/unix/mpconfigport_fast.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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. - */ - -// This config file is intended to configure artificially fast uPy build for -// synthetic benchmarking, at the expense of features supported and memory -// usage. This config is not intended to be used in production. - -#include <mpconfigport.h> -#define MICROPY_PY___FILE__ (0) -// 91 is a magic number proposed by @dpgeorge, which make pystone run ~ at tie -// with CPython 3.4. -#define MICROPY_MODULE_DICT_SIZE (91) - -// Don't include builtin upip, as this build is again intended just for -// synthetic benchmarking -#undef MICROPY_MODULE_FROZEN_STR -#define MICROPY_MODULE_FROZEN_STR (0) diff --git a/unix/mpconfigport_freedos.h b/unix/mpconfigport_freedos.h deleted file mode 100644 index 09c85ab1e3..0000000000 --- a/unix/mpconfigport_freedos.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2015 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. - */ - -// options to control how MicroPython is built - -#include <mpconfigport.h> - -#undef MICROPY_STREAMS_NON_BLOCK -#define MICROPY_STREAMS_NON_BLOCK (0) - -#undef MICROPY_PY_SYS_PLATFORM -#define MICROPY_PY_SYS_PLATFORM "freedos" - -// djgpp dirent struct does not have d_ino field -#undef _DIRENT_HAVE_D_INO - -#define MICROPY_USE_INTERNAL_ERRNO (1) diff --git a/unix/mpconfigport_minimal.h b/unix/mpconfigport_minimal.h deleted file mode 100644 index ef7a1a09a0..0000000000 --- a/unix/mpconfigport_minimal.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2015 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. - */ - -// options to control how MicroPython is built - -#define MICROPY_ALLOC_QSTR_CHUNK_INIT (64) -#define MICROPY_ALLOC_PARSE_RULE_INIT (8) -#define MICROPY_ALLOC_PARSE_RULE_INC (8) -#define MICROPY_ALLOC_PARSE_RESULT_INIT (8) -#define MICROPY_ALLOC_PARSE_RESULT_INC (8) -#define MICROPY_ALLOC_PARSE_CHUNK_INIT (64) -#define MICROPY_ALLOC_PATH_MAX (PATH_MAX) -#define MICROPY_ENABLE_GC (1) -#define MICROPY_GC_ALLOC_THRESHOLD (0) -#define MICROPY_ENABLE_FINALISER (0) -#define MICROPY_STACK_CHECK (0) -#define MICROPY_COMP_CONST (0) -#define MICROPY_MEM_STATS (0) -#define MICROPY_DEBUG_PRINTERS (0) -#define MICROPY_READER_POSIX (1) -#define MICROPY_HELPER_REPL (1) -#define MICROPY_HELPER_LEXER_UNIX (1) -#define MICROPY_ENABLE_SOURCE_LINE (0) -#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) -#define MICROPY_WARNINGS (0) -#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (0) -#define MICROPY_KBD_EXCEPTION (1) -#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE) -#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE) -#define MICROPY_STREAMS_NON_BLOCK (0) -#define MICROPY_OPT_COMPUTED_GOTO (0) -#define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (0) -#define MICROPY_CAN_OVERRIDE_BUILTINS (0) -#define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (0) -#define MICROPY_CPYTHON_COMPAT (0) -#define MICROPY_PY_BUILTINS_BYTEARRAY (0) -#define MICROPY_PY_BUILTINS_MEMORYVIEW (0) -#define MICROPY_PY_BUILTINS_COMPILE (0) -#define MICROPY_PY_BUILTINS_ENUMERATE (0) -#define MICROPY_PY_BUILTINS_FILTER (0) -#define MICROPY_PY_BUILTINS_FROZENSET (0) -#define MICROPY_PY_BUILTINS_REVERSED (0) -#define MICROPY_PY_BUILTINS_SET (0) -#define MICROPY_PY_BUILTINS_SLICE (0) -#define MICROPY_PY_BUILTINS_STR_UNICODE (0) -#define MICROPY_PY_BUILTINS_PROPERTY (0) -#define MICROPY_PY_BUILTINS_MIN_MAX (0) -#define MICROPY_PY___FILE__ (0) -#define MICROPY_PY_MICROPYTHON_MEM_INFO (0) -#define MICROPY_PY_GC (0) -#define MICROPY_PY_GC_COLLECT_RETVAL (0) -#define MICROPY_PY_ARRAY (0) -#define MICROPY_PY_COLLECTIONS (0) -#define MICROPY_PY_MATH (0) -#define MICROPY_PY_CMATH (0) -#define MICROPY_PY_IO (0) -#define MICROPY_PY_IO_FILEIO (0) -#define MICROPY_PY_STRUCT (0) -#define MICROPY_PY_SYS (1) -#define MICROPY_PY_SYS_EXIT (0) -#define MICROPY_PY_SYS_PLATFORM "linux" -#define MICROPY_PY_SYS_MAXSIZE (0) -#define MICROPY_PY_SYS_STDFILES (0) -#define MICROPY_PY_CMATH (0) -#define MICROPY_PY_UCTYPES (0) -#define MICROPY_PY_UTIME (0) -#define MICROPY_PY_UZLIB (0) -#define MICROPY_PY_UJSON (0) -#define MICROPY_PY_URE (0) -#define MICROPY_PY_UHEAPQ (0) -#define MICROPY_PY_UHASHLIB (0) -#define MICROPY_PY_UBINASCII (0) - -extern const struct _mp_obj_module_t mp_module_os; - -#define MICROPY_PORT_BUILTIN_MODULES \ - { MP_ROM_QSTR(MP_QSTR_uos), MP_ROM_PTR(&mp_module_os) }, \ - -#define MICROPY_PORT_ROOT_POINTERS \ - -////////////////////////////////////////// -// Do not change anything beyond this line -////////////////////////////////////////// - -// Define to 1 to use undertested inefficient GC helper implementation -// (if more efficient arch-specific one is not available). -#ifndef MICROPY_GCREGS_SETJMP - #ifdef __mips__ - #define MICROPY_GCREGS_SETJMP (1) - #else - #define MICROPY_GCREGS_SETJMP (0) - #endif -#endif - -// type definitions for the specific machine - -#ifdef __LP64__ -typedef long mp_int_t; // must be pointer size -typedef unsigned long mp_uint_t; // must be pointer size -#else -// These are definitions for machines where sizeof(int) == sizeof(void*), -// regardless for actual size. -typedef int mp_int_t; // must be pointer size -typedef unsigned int mp_uint_t; // must be pointer size -#endif - -// Cannot include <sys/types.h>, as it may lead to symbol name clashes -#if _FILE_OFFSET_BITS == 64 && !defined(__LP64__) -typedef long long mp_off_t; -#else -typedef long mp_off_t; -#endif - -// We need to provide a declaration/definition of alloca() -#ifdef __FreeBSD__ -#include <stdlib.h> -#else -#include <alloca.h> -#endif diff --git a/unix/mpconfigport_nanbox.h b/unix/mpconfigport_nanbox.h deleted file mode 100644 index 7da2cf7b80..0000000000 --- a/unix/mpconfigport_nanbox.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016 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. - */ - -// select nan-boxing object model -#define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_D) - -// native emitters don't work with nan-boxing -#define MICROPY_EMIT_X86 (0) -#define MICROPY_EMIT_X64 (0) -#define MICROPY_EMIT_THUMB (0) -#define MICROPY_EMIT_ARM (0) - -#include <stdint.h> - -typedef int64_t mp_int_t; -typedef uint64_t mp_uint_t; -#define UINT_FMT "%llu" -#define INT_FMT "%lld" - -#include <mpconfigport.h> diff --git a/unix/mphalport.h b/unix/mphalport.h deleted file mode 100644 index ff7a51567c..0000000000 --- a/unix/mphalport.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2015 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 <unistd.h> - -#ifndef CHAR_CTRL_C -#define CHAR_CTRL_C (3) -#endif - -void mp_hal_set_interrupt_char(char c); - -void mp_hal_stdio_mode_raw(void); -void mp_hal_stdio_mode_orig(void); - -#if MICROPY_USE_READLINE == 1 && MICROPY_PY_BUILTINS_INPUT -#include "py/misc.h" -#include "lib/mp-readline/readline.h" -// For built-in input() we need to wrap the standard readline() to enable raw mode -#define mp_hal_readline mp_hal_readline -static inline int mp_hal_readline(vstr_t *vstr, const char *p) { - mp_hal_stdio_mode_raw(); - int ret = readline(vstr, p); - mp_hal_stdio_mode_orig(); - return ret; -} -#endif - -// TODO: POSIX et al. define usleep() as guaranteedly capable only of 1s sleep: -// "The useconds argument shall be less than one million." -static inline void mp_hal_delay_ms(mp_uint_t ms) { usleep((ms) * 1000); } -static inline void mp_hal_delay_us(mp_uint_t us) { usleep(us); } -#define mp_hal_ticks_cpu() 0 - -#define RAISE_ERRNO(err_flag, error_val) \ - { if (err_flag == -1) \ - { mp_raise_OSError(error_val); } } diff --git a/unix/mpthreadport.c b/unix/mpthreadport.c deleted file mode 100644 index 09f5702e38..0000000000 --- a/unix/mpthreadport.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd - * - * 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 <stdlib.h> -#include <errno.h> - -#include "py/mpstate.h" -#include "py/runtime.h" -#include "py/mpthread.h" -#include "py/gc.h" - -#if MICROPY_PY_THREAD - -#include <signal.h> -#include <sched.h> - -// this structure forms a linked list, one node per active thread -typedef struct _thread_t { - pthread_t id; // system id of thread - int ready; // whether the thread is ready and running - void *arg; // thread Python args, a GC root pointer - struct _thread_t *next; -} thread_t; - -STATIC pthread_key_t tls_key; - -// the mutex controls access to the linked list -STATIC pthread_mutex_t thread_mutex = PTHREAD_MUTEX_INITIALIZER; -STATIC thread_t *thread; - -// this is used to synchronise the signal handler of the thread -// it's needed because we can't use any pthread calls in a signal handler -STATIC volatile int thread_signal_done; - -// this signal handler is used to scan the regs and stack of a thread -STATIC void mp_thread_gc(int signo, siginfo_t *info, void *context) { - (void)info; // unused - (void)context; // unused - if (signo == SIGUSR1) { - void gc_collect_regs_and_stack(void); - gc_collect_regs_and_stack(); - // We have access to the context (regs, stack) of the thread but it seems - // that we don't need the extra information, enough is captured by the - // gc_collect_regs_and_stack function above - //gc_collect_root((void**)context, sizeof(ucontext_t) / sizeof(uintptr_t)); - thread_signal_done = 1; - } -} - -void mp_thread_init(void) { - pthread_key_create(&tls_key, NULL); - pthread_setspecific(tls_key, &mp_state_ctx.thread); - - // create first entry in linked list of all threads - thread = malloc(sizeof(thread_t)); - thread->id = pthread_self(); - thread->ready = 1; - thread->arg = NULL; - thread->next = NULL; - - // enable signal handler for garbage collection - struct sigaction sa; - sa.sa_flags = SA_SIGINFO; - sa.sa_sigaction = mp_thread_gc; - sigemptyset(&sa.sa_mask); - sigaction(SIGUSR1, &sa, NULL); -} - -// This function scans all pointers that are external to the current thread. -// It does this by signalling all other threads and getting them to scan their -// own registers and stack. Note that there may still be some edge cases left -// with race conditions and root-pointer scanning: a given thread may manipulate -// the global root pointers (in mp_state_ctx) while another thread is doing a -// garbage collection and tracing these pointers. -void mp_thread_gc_others(void) { - pthread_mutex_lock(&thread_mutex); - for (thread_t *th = thread; th != NULL; th = th->next) { - gc_collect_root(&th->arg, 1); - if (th->id == pthread_self()) { - continue; - } - if (!th->ready) { - continue; - } - thread_signal_done = 0; - pthread_kill(th->id, SIGUSR1); - while (thread_signal_done == 0) { - sched_yield(); - } - } - pthread_mutex_unlock(&thread_mutex); -} - -mp_state_thread_t *mp_thread_get_state(void) { - return (mp_state_thread_t*)pthread_getspecific(tls_key); -} - -void mp_thread_set_state(void *state) { - pthread_setspecific(tls_key, state); -} - -void mp_thread_start(void) { - pthread_mutex_lock(&thread_mutex); - for (thread_t *th = thread; th != NULL; th = th->next) { - if (th->id == pthread_self()) { - th->ready = 1; - break; - } - } - pthread_mutex_unlock(&thread_mutex); -} - -void mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size) { - // default stack size is 8k machine-words - if (*stack_size == 0) { - *stack_size = 8192 * BYTES_PER_WORD; - } - - // minimum stack size is set by pthreads - if (*stack_size < PTHREAD_STACK_MIN) { - *stack_size = PTHREAD_STACK_MIN; - } - - // set thread attributes - pthread_attr_t attr; - int ret = pthread_attr_init(&attr); - if (ret != 0) { - goto er; - } - ret = pthread_attr_setstacksize(&attr, *stack_size); - if (ret != 0) { - goto er; - } - - pthread_mutex_lock(&thread_mutex); - - // create thread - pthread_t id; - ret = pthread_create(&id, &attr, entry, arg); - if (ret != 0) { - pthread_mutex_unlock(&thread_mutex); - goto er; - } - - // adjust stack_size to provide room to recover from hitting the limit - // this value seems to be about right for both 32-bit and 64-bit builds - *stack_size -= 8192; - - // add thread to linked list of all threads - thread_t *th = malloc(sizeof(thread_t)); - th->id = id; - th->ready = 0; - th->arg = arg; - th->next = thread; - thread = th; - - pthread_mutex_unlock(&thread_mutex); - - return; - -er: - mp_raise_OSError(ret); -} - -void mp_thread_finish(void) { - pthread_mutex_lock(&thread_mutex); - // TODO unlink from list - for (thread_t *th = thread; th != NULL; th = th->next) { - if (th->id == pthread_self()) { - th->ready = 0; - break; - } - } - pthread_mutex_unlock(&thread_mutex); -} - -void mp_thread_mutex_init(mp_thread_mutex_t *mutex) { - pthread_mutex_init(mutex, NULL); -} - -int mp_thread_mutex_lock(mp_thread_mutex_t *mutex, int wait) { - int ret; - if (wait) { - ret = pthread_mutex_lock(mutex); - if (ret == 0) { - return 1; - } - } else { - ret = pthread_mutex_trylock(mutex); - if (ret == 0) { - return 1; - } else if (ret == EBUSY) { - return 0; - } - } - return -ret; -} - -void mp_thread_mutex_unlock(mp_thread_mutex_t *mutex) { - pthread_mutex_unlock(mutex); - // TODO check return value -} - -#endif // MICROPY_PY_THREAD diff --git a/unix/mpthreadport.h b/unix/mpthreadport.h deleted file mode 100644 index b158ed5bcc..0000000000 --- a/unix/mpthreadport.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd - * - * 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 <pthread.h> - -typedef pthread_mutex_t mp_thread_mutex_t; - -void mp_thread_init(void); -void mp_thread_gc_others(void); diff --git a/unix/qstrdefsport.h b/unix/qstrdefsport.h deleted file mode 100644 index ebfaa6ccab..0000000000 --- a/unix/qstrdefsport.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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. - */ diff --git a/unix/unix_mphal.c b/unix/unix_mphal.c deleted file mode 100644 index 02cdbea11f..0000000000 --- a/unix/unix_mphal.c +++ /dev/null @@ -1,199 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2015 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 <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <sys/time.h> - -#include "py/mpstate.h" -#include "py/mphal.h" -#include "py/runtime.h" -#include "extmod/misc.h" - -#ifndef _WIN32 -#include <signal.h> - -STATIC void sighandler(int signum) { - if (signum == SIGINT) { - #if MICROPY_ASYNC_KBD_INTR - mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))); - sigset_t mask; - sigemptyset(&mask); - // On entry to handler, its signal is blocked, and unblocked on - // normal exit. As we instead perform longjmp, unblock it manually. - sigprocmask(SIG_SETMASK, &mask, NULL); - nlr_raise(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))); - #else - if (MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))) { - // this is the second time we are called, so die straight away - exit(1); - } - mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))); - MP_STATE_VM(mp_pending_exception) = MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)); - #endif - } -} -#endif - -void mp_hal_set_interrupt_char(char c) { - // configure terminal settings to (not) let ctrl-C through - if (c == CHAR_CTRL_C) { - #ifndef _WIN32 - // enable signal handler - struct sigaction sa; - sa.sa_flags = 0; - sa.sa_handler = sighandler; - sigemptyset(&sa.sa_mask); - sigaction(SIGINT, &sa, NULL); - #endif - } else { - #ifndef _WIN32 - // disable signal handler - struct sigaction sa; - sa.sa_flags = 0; - sa.sa_handler = SIG_DFL; - sigemptyset(&sa.sa_mask); - sigaction(SIGINT, &sa, NULL); - #endif - } -} - -#if MICROPY_USE_READLINE == 1 - -#include <termios.h> - -static struct termios orig_termios; - -void mp_hal_stdio_mode_raw(void) { - // save and set terminal settings - tcgetattr(0, &orig_termios); - static struct termios termios; - termios = orig_termios; - termios.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); - termios.c_cflag = (termios.c_cflag & ~(CSIZE | PARENB)) | CS8; - termios.c_lflag = 0; - termios.c_cc[VMIN] = 1; - termios.c_cc[VTIME] = 0; - tcsetattr(0, TCSAFLUSH, &termios); -} - -void mp_hal_stdio_mode_orig(void) { - // restore terminal settings - tcsetattr(0, TCSAFLUSH, &orig_termios); -} - -#endif - -#if MICROPY_PY_OS_DUPTERM -static int call_dupterm_read(void) { - nlr_buf_t nlr; - if (nlr_push(&nlr) == 0) { - mp_obj_t read_m[3]; - mp_load_method(MP_STATE_PORT(term_obj), MP_QSTR_read, read_m); - read_m[2] = MP_OBJ_NEW_SMALL_INT(1); - mp_obj_t res = mp_call_method_n_kw(1, 0, read_m); - if (res == mp_const_none) { - return -2; - } - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(res, &bufinfo, MP_BUFFER_READ); - if (bufinfo.len == 0) { - mp_printf(&mp_plat_print, "dupterm: EOF received, deactivating\n"); - MP_STATE_PORT(term_obj) = NULL; - return -1; - } - nlr_pop(); - return *(byte*)bufinfo.buf; - } else { - // Temporarily disable dupterm to avoid infinite recursion - mp_obj_t save_term = MP_STATE_PORT(term_obj); - MP_STATE_PORT(term_obj) = NULL; - mp_printf(&mp_plat_print, "dupterm: "); - mp_obj_print_exception(&mp_plat_print, nlr.ret_val); - MP_STATE_PORT(term_obj) = save_term; - } - - return -1; -} -#endif - -int mp_hal_stdin_rx_chr(void) { - unsigned char c; -#if MICROPY_PY_OS_DUPTERM - if (MP_STATE_PORT(term_obj) != MP_OBJ_NULL) { - int c; - do { - c = call_dupterm_read(); - } while (c == -2); - if (c == -1) { - goto main_term; - } - if (c == '\n') { - c = '\r'; - } - return c; - } else { - main_term:; -#endif - int ret = read(0, &c, 1); - if (ret == 0) { - c = 4; // EOF, ctrl-D - } else if (c == '\n') { - c = '\r'; - } - return c; -#if MICROPY_PY_OS_DUPTERM - } -#endif -} - -void mp_hal_stdout_tx_strn(const char *str, size_t len) { - int ret = write(1, str, len); - mp_uos_dupterm_tx_strn(str, len); - (void)ret; // to suppress compiler warning -} - -// cooked is same as uncooked because the terminal does some postprocessing -void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) { - mp_hal_stdout_tx_strn(str, len); -} - -void mp_hal_stdout_tx_str(const char *str) { - mp_hal_stdout_tx_strn(str, strlen(str)); -} - -mp_uint_t mp_hal_ticks_ms(void) { - struct timeval tv; - gettimeofday(&tv, NULL); - return tv.tv_sec * 1000 + tv.tv_usec / 1000; -} - -mp_uint_t mp_hal_ticks_us(void) { - struct timeval tv; - gettimeofday(&tv, NULL); - return tv.tv_sec * 1000000 + tv.tv_usec; -} |