diff options
Diffstat (limited to 'unix')
-rw-r--r-- | unix/Makefile | 27 | ||||
-rw-r--r-- | unix/file.c | 73 | ||||
-rw-r--r-- | unix/gccollect.c | 6 | ||||
-rw-r--r-- | unix/main.c | 59 | ||||
-rw-r--r-- | unix/modffi.c | 1 | ||||
-rw-r--r-- | unix/modos.c | 87 | ||||
-rw-r--r-- | unix/modsocket.c | 21 | ||||
-rw-r--r-- | unix/modtime.c | 32 | ||||
-rw-r--r-- | unix/mpconfigport.h | 37 | ||||
-rw-r--r-- | unix/mpconfigport.mk | 4 | ||||
-rw-r--r-- | unix/qstrdefsport.h | 3 | ||||
-rw-r--r-- | unix/seg_helpers.c | 38 |
12 files changed, 320 insertions, 68 deletions
diff --git a/unix/Makefile b/unix/Makefile index 05cdfb5b39..ffc3391a14 100644 --- a/unix/Makefile +++ b/unix/Makefile @@ -19,15 +19,15 @@ CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) UNAME_S := $(shell uname -s) ifeq ($(UNAME_S),Darwin) - LDFLAGS = $(LDFLAGS_MOD) -lm -Wl,-map,$@.map -else + LDFLAGS = $(LDFLAGS_MOD) -lm -Wl,-map,$@.map,-order_file,$(BUILD)/order.def + else LDFLAGS = $(LDFLAGS_MOD) -lm -Wl,-Map=$@.map,--cref endif ifeq ($(MICROPY_FORCE_32BIT),1) CFLAGS += -m32 LDFLAGS += -m32 -ifeq ($(MICROPY_MOD_FFI),1) +ifeq ($(MICROPY_PY_FFI),1) ifeq ($(UNAME_S),Linux) CFLAGS_MOD += -I/usr/include/i686-linux-gnu endif @@ -40,14 +40,14 @@ LDFLAGS_MOD += -lreadline # the following is needed for BSD #LDFLAGS_MOD += -ltermcap endif -ifeq ($(MICROPY_MOD_TIME),1) -CFLAGS_MOD += -DMICROPY_MOD_TIME=1 +ifeq ($(MICROPY_PY_TIME),1) +CFLAGS_MOD += -DMICROPY_PY_TIME=1 SRC_MOD += modtime.c endif -ifeq ($(MICROPY_MOD_FFI),1) +ifeq ($(MICROPY_PY_FFI),1) LIBFFI_LDFLAGS_MOD := $(shell pkg-config --libs libffi) LIBFFI_CFLAGS_MOD := $(shell pkg-config --cflags libffi) -CFLAGS_MOD += $(LIBFFI_CFLAGS_MOD) -DMICROPY_MOD_FFI=1 +CFLAGS_MOD += $(LIBFFI_CFLAGS_MOD) -DMICROPY_PY_FFI=1 LDFLAGS_MOD += -ldl $(LIBFFI_LDFLAGS_MOD) SRC_MOD += modffi.c endif @@ -68,8 +68,21 @@ SRC_C = \ input.c \ file.c \ modsocket.c \ + modos.c \ $(SRC_MOD) +ifeq ($(UNAME_S),Darwin) +# Must be the last file in list of sources +SRC_C += seg_helpers.c + +# making seg_helpers.c rely on order.def will force order.def to be created +seg_helpers.c: $(BUILD)/order.def + +# create order.def in build directory +$(BUILD)/order.def: + $(Q)echo "seg_helpers.o: ___bss_start" > $@ +endif + OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) include ../py/mkrules.mk diff --git a/unix/file.c b/unix/file.c index ada841ea2c..386f018bdd 100644 --- a/unix/file.c +++ b/unix/file.c @@ -54,11 +54,12 @@ void check_fd_is_open(const mp_obj_fdfile_t *o) { #define check_fd_is_open(o) #endif -STATIC const mp_obj_type_t rawfile_type; +extern const mp_obj_type_t mp_type_fileio; +extern const mp_obj_type_t mp_type_textio; STATIC void fdfile_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { mp_obj_fdfile_t *self = self_in; - print(env, "<io.FileIO %d>", self->fd); + print(env, "<io.%s %d>", mp_obj_get_type_str(self), self->fd); } STATIC machine_int_t fdfile_read(mp_obj_t o_in, void *buf, machine_uint_t size, int *errcode) { @@ -103,23 +104,10 @@ STATIC mp_obj_t fdfile_fileno(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(fdfile_fileno_obj, fdfile_fileno); -STATIC mp_obj_fdfile_t *fdfile_new(int fd) { - mp_obj_fdfile_t *o = m_new_obj(mp_obj_fdfile_t); - o->base.type = &rawfile_type; - o->fd = fd; - return o; -} - STATIC mp_obj_t fdfile_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { mp_obj_fdfile_t *o = m_new_obj(mp_obj_fdfile_t); - o->base.type = type_in; - - if (MP_OBJ_IS_SMALL_INT(args[0])) { - o->fd = MP_OBJ_SMALL_INT_VALUE(args[0]); - return o; - } + mp_const_obj_t type = type_in; - const char *fname = mp_obj_str_get_str(args[0]); const char *mode_s; if (n_args > 1) { mode_s = mp_obj_str_get_str(args[1]); @@ -143,14 +131,32 @@ STATIC mp_obj_t fdfile_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const case '+': mode |= 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; + + if (MP_OBJ_IS_SMALL_INT(args[0])) { + o->fd = MP_OBJ_SMALL_INT_VALUE(args[0]); + return o; + } + + const char *fname = mp_obj_str_get_str(args[0]); int fd = open(fname, mode, 0644); if (fd == -1) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT((machine_int_t)errno))); } - return fdfile_new(fd); + o->fd = fd; + return o; } STATIC const mp_map_elem_t rawfile_locals_dict_table[] = { @@ -167,29 +173,48 @@ STATIC const mp_map_elem_t rawfile_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table); -STATIC const mp_stream_p_t rawfile_stream_p = { +#if MICROPY_PY_IO_FILEIO +STATIC const mp_stream_p_t fileio_stream_p = { .read = fdfile_read, .write = fdfile_write, + .is_bytes = true, }; -STATIC const mp_obj_type_t rawfile_type = { +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, .iternext = mp_stream_unbuffered_iter, - .stream_p = &rawfile_stream_p, + .stream_p = &fileio_stream_p, + .locals_dict = (mp_obj_t)&rawfile_locals_dict, +}; +#endif + +STATIC const mp_stream_p_t textio_stream_p = { + .read = fdfile_read, + .write = fdfile_write, +}; + +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, + .iternext = mp_stream_unbuffered_iter, + .stream_p = &textio_stream_p, .locals_dict = (mp_obj_t)&rawfile_locals_dict, }; // Factory function for I/O stream classes mp_obj_t mp_builtin_open(uint n_args, const mp_obj_t *args) { // TODO: analyze mode and buffering args and instantiate appropriate type - return fdfile_make_new((mp_obj_t)&rawfile_type, n_args, 0, args); + return fdfile_make_new((mp_obj_t)&mp_type_textio, n_args, 0, args); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_open_obj, 1, 2, mp_builtin_open); -const mp_obj_fdfile_t mp_sys_stdin_obj = { .base = {&rawfile_type}, .fd = STDIN_FILENO }; -const mp_obj_fdfile_t mp_sys_stdout_obj = { .base = {&rawfile_type}, .fd = STDOUT_FILENO }; -const mp_obj_fdfile_t mp_sys_stderr_obj = { .base = {&rawfile_type}, .fd = STDERR_FILENO }; +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 }; diff --git a/unix/gccollect.c b/unix/gccollect.c index 647a1214de..1b5a38ffc6 100644 --- a/unix/gccollect.c +++ b/unix/gccollect.c @@ -43,11 +43,17 @@ typedef machine_uint_t regs_t[6]; void gc_helper_get_regs(regs_t arr) { register long rbx asm ("rbx"); + asm("" : "=r"(rbx)); register long rbp asm ("rbp"); + asm("" : "=r"(rbp)); register long r12 asm ("r12"); + asm("" : "=r"(r12)); register long r13 asm ("r13"); + asm("" : "=r"(r13)); register long r14 asm ("r14"); + asm("" : "=r"(r14)); register long r15 asm ("r15"); + asm("" : "=r"(r15)); arr[0] = rbx; arr[1] = rbp; arr[2] = r12; diff --git a/unix/main.c b/unix/main.c index cc80811503..884ee9d32d 100644 --- a/unix/main.c +++ b/unix/main.c @@ -69,9 +69,10 @@ void microsocket_init(); void time_init(); void ffi_init(); -STATIC void execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, bool is_repl) { +// returns standard error codes: 0 for success, 1 for all other errors +STATIC int execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, bool is_repl) { if (lex == NULL) { - return; + return 1; } if (0) { @@ -81,7 +82,7 @@ STATIC void execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind mp_lexer_to_next(lex); } mp_lexer_free(lex); - return; + return 0; } mp_parse_error_kind_t parse_error_kind; @@ -91,7 +92,7 @@ STATIC void execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind // parse error mp_parse_show_exception(lex, parse_error_kind); mp_lexer_free(lex); - return; + return 1; } qstr source_name = mp_lexer_source_name(lex); @@ -107,11 +108,11 @@ STATIC void execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind if (module_fun == mp_const_none) { // compile error - return; + return 1; } if (compile_only) { - return; + return 0; } // execute it @@ -119,9 +120,16 @@ STATIC void execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind if (nlr_push(&nlr) == 0) { mp_call_function_0(module_fun); nlr_pop(); + return 0; } else { // uncaught exception + // check for SystemExit + mp_obj_t exc = (mp_obj_t)nlr.ret_val; + if (mp_obj_is_subclass_fast(mp_obj_get_type(exc), &mp_type_SystemExit)) { + exit(mp_obj_get_int(mp_obj_exception_get_value(exc))); + } mp_obj_print_exception((mp_obj_t)nlr.ret_val); + return 1; } } @@ -165,14 +173,14 @@ STATIC void do_repl(void) { } } -STATIC void do_file(const char *file) { +STATIC int do_file(const char *file) { mp_lexer_t *lex = mp_lexer_new_from_file(file); - execute_from_lexer(lex, MP_PARSE_FILE_INPUT, false); + return execute_from_lexer(lex, MP_PARSE_FILE_INPUT, false); } -STATIC void do_str(const char *str) { +STATIC int do_str(const char *str) { mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, str, strlen(str), false); - execute_from_lexer(lex, MP_PARSE_SINGLE_INPUT, false); + return execute_from_lexer(lex, MP_PARSE_SINGLE_INPUT, false); } int usage(char **argv) { @@ -230,7 +238,7 @@ void pre_process_options(int argc, char **argv) { } 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_BYTE_CODE; + 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) { @@ -321,20 +329,23 @@ int main(int argc, char **argv) { printf(" peak %d\n", m_get_peak_bytes_allocated()); */ - bool executed = false; + const int NOTHING_EXECUTED = -2; + int ret = NOTHING_EXECUTED; for (int a = 1; a < argc; a++) { if (argv[a][0] == '-') { if (strcmp(argv[a], "-c") == 0) { if (a + 1 >= argc) { return usage(argv); } - do_str(argv[a + 1]); - executed = true; + ret = do_str(argv[a + 1]); a += 1; } else if (strcmp(argv[a], "-X") == 0) { a += 1; } else if (strcmp(argv[a], "-v") == 0) { mp_verbose_flag++; + } else if (strcmp(argv[a], "-O") == 0) { + // optimisation; sets __debug__ to False + mp_set_debug(false); } else { return usage(argv); } @@ -344,7 +355,8 @@ int main(int argc, char **argv) { fprintf(stderr, "%s: can't open file '%s': [Errno %d] ", argv[0], argv[1], errno); perror(""); // CPython exits with 2 in such case - exit(2); + ret = 2; + break; } // Set base dir of the script as first entry in sys.path @@ -355,21 +367,30 @@ int main(int argc, char **argv) { for (int i = a; i < argc; i++) { mp_obj_list_append(mp_sys_argv, MP_OBJ_NEW_QSTR(qstr_from_str(argv[i]))); } - do_file(argv[a]); - executed = true; + ret = do_file(argv[a]); break; } } - if (!executed) { + if (ret == NOTHING_EXECUTED) { do_repl(); + ret = 0; } mp_deinit(); //printf("total bytes = %d\n", m_get_total_bytes_allocated()); - return 0; + return ret; +} + +STATIC mp_obj_t mp_sys_exit(uint n_args, const mp_obj_t *args) { + int rc = 0; + if (n_args > 0) { + rc = mp_obj_get_int(args[0]); + } + nlr_raise(mp_obj_new_exception_arg1(&mp_type_SystemExit, mp_obj_new_int(rc))); } +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_sys_exit_obj, 0, 1, mp_sys_exit); uint mp_import_stat(const char *path) { struct stat st; diff --git a/unix/modffi.c b/unix/modffi.c index aa26297d60..4ac9fef5aa 100644 --- a/unix/modffi.c +++ b/unix/modffi.c @@ -4,6 +4,7 @@ * 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 diff --git a/unix/modos.c b/unix/modos.c new file mode 100644 index 0000000000..5c81caa5cb --- /dev/null +++ b/unix/modos.c @@ -0,0 +1,87 @@ +/* + * This file is part of the Micro Python 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 "misc.h" +#include "mpconfig.h" +#include "nlr.h" +#include "qstr.h" +#include "obj.h" +#include "runtime.h" +#include "objtuple.h" + +#define RAISE_ERRNO(err_flag, error_val) \ + { if (err_flag == -1) \ + { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT((machine_int_t)error_val))); } } + +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_new_tuple(10, NULL); + t->items[0] = MP_OBJ_NEW_SMALL_INT((machine_int_t)sb.st_mode); + t->items[1] = MP_OBJ_NEW_SMALL_INT(sb.st_ino); + t->items[2] = MP_OBJ_NEW_SMALL_INT((machine_int_t)sb.st_dev); + t->items[3] = MP_OBJ_NEW_SMALL_INT((machine_int_t)sb.st_nlink); + t->items[4] = MP_OBJ_NEW_SMALL_INT((machine_int_t)sb.st_uid); + t->items[5] = MP_OBJ_NEW_SMALL_INT((machine_int_t)sb.st_gid); + t->items[6] = MP_OBJ_NEW_SMALL_INT(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 t; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_stat_obj, mod_os_stat); + +STATIC const mp_map_elem_t mp_module_os_globals_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR__os) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_stat), (mp_obj_t)&mod_os_stat_obj }, +}; + +STATIC const mp_obj_dict_t mp_module_os_globals = { + .base = {&mp_type_dict}, + .map = { + .all_keys_are_qstrs = 1, + .table_is_fixed_array = 1, + .used = ARRAY_SIZE(mp_module_os_globals_table), + .alloc = ARRAY_SIZE(mp_module_os_globals_table), + .table = (mp_map_elem_t*)mp_module_os_globals_table, + }, +}; + +const mp_obj_module_t mp_module_os = { + .base = { &mp_type_module }, + .name = MP_QSTR__os, + .globals = (mp_obj_dict_t*)&mp_module_os_globals, +}; diff --git a/unix/modsocket.c b/unix/modsocket.c index 72aee95eab..c4e80d3d52 100644 --- a/unix/modsocket.c +++ b/unix/modsocket.c @@ -4,6 +4,7 @@ * 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 @@ -36,6 +37,7 @@ #include <arpa/inet.h> #include <netdb.h> #include <errno.h> +#include <alloca.h> #include "mpconfig.h" #include "nlr.h" @@ -46,6 +48,7 @@ #include "objarray.h" #include "runtime.h" #include "stream.h" +#include "builtin.h" #define MICROPY_SOCKET_EXTRA (0) @@ -228,6 +231,18 @@ STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking); +STATIC mp_obj_t socket_makefile(uint 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 = 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((machine_int_t)self->fd); + return mp_builtin_open(n_args, new_args); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_makefile_obj, 1, 3, socket_makefile); + STATIC mp_obj_t socket_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { int family = AF_INET; int type = SOCK_STREAM; @@ -253,7 +268,7 @@ STATIC mp_obj_t socket_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const STATIC const mp_map_elem_t microsocket_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_fileno), (mp_obj_t)&socket_fileno_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_makefile), (mp_obj_t)&mp_identity_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_makefile), (mp_obj_t)&socket_makefile_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_readall), (mp_obj_t)&mp_stream_readall_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj}, @@ -291,6 +306,7 @@ STATIC const mp_obj_type_t microsocket_type = { .locals_dict = (mp_obj_t)µsocket_locals_dict, }; +#if MICROPY_SOCKET_EXTRA STATIC mp_obj_t mod_socket_htons(mp_obj_t arg) { return MP_OBJ_NEW_SMALL_INT((machine_int_t)htons(MP_OBJ_SMALL_INT_VALUE(arg))); } @@ -308,7 +324,6 @@ STATIC mp_obj_t mod_socket_inet_aton(mp_obj_t arg) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_socket_inet_aton_obj, mod_socket_inet_aton); -#if MICROPY_SOCKET_EXTRA STATIC mp_obj_t mod_socket_gethostbyname(mp_obj_t arg) { assert(MP_OBJ_IS_TYPE(arg, &mp_type_str)); const char *s = mp_obj_str_get_str(arg); @@ -321,7 +336,7 @@ STATIC mp_obj_t mod_socket_gethostbyname(mp_obj_t arg) { 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 +#endif // MICROPY_SOCKET_EXTRA STATIC mp_obj_t mod_socket_getaddrinfo(uint n_args, const mp_obj_t *args) { // TODO: Implement all args diff --git a/unix/modtime.c b/unix/modtime.c index 283b9dfd69..77d2945b8f 100644 --- a/unix/modtime.c +++ b/unix/modtime.c @@ -36,6 +36,33 @@ #include "obj.h" #include "runtime.h" +#ifdef _WIN32 +void msec_sleep_tv(struct timeval *tv) { + msec_sleep(tv->tv_sec * 1000.0 + tv->tv_usec / 1000.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) && (MP_CLOCKS_PER_SEC == 1000000) // POSIX +#define CLOCK_DIV 1000.0 +#elif defined(MP_CLOCKS_PER_SEC) && (MP_CLOCKS_PER_SEC == 1000) // WIN32 +#define CLOCK_DIV 1.0 +#else +#error Unsupported clock() implementation +#endif + STATIC mp_obj_t mod_time_time() { #if MICROPY_ENABLE_FLOAT struct timeval tv; @@ -51,11 +78,10 @@ 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() { #if MICROPY_ENABLE_FLOAT - // POSIX requires CLOCKS_PER_SEC equals 1000000, so that's what we assume. // 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) / 1000.0); + return mp_obj_new_float((float)(clock() / 1000) / CLOCK_DIV); #else return mp_obj_new_int((machine_int_t)clock()); #endif @@ -69,7 +95,7 @@ STATIC mp_obj_t mod_time_sleep(mp_obj_t arg) { double ipart; tv.tv_usec = round(modf(val, &ipart) * 1000000); tv.tv_sec = ipart; - select(0, NULL, NULL, NULL, &tv); + sleep_select(0, NULL, NULL, NULL, &tv); #else sleep(mp_obj_get_int(arg)); #endif diff --git a/unix/mpconfigport.h b/unix/mpconfigport.h index ca470d9c29..c56c9fa1a6 100644 --- a/unix/mpconfigport.h +++ b/unix/mpconfigport.h @@ -26,6 +26,7 @@ // options to control how Micro Python is built +#define MICROPY_ALLOC_PATH_MAX (PATH_MAX) #define MICROPY_EMIT_X64 (1) #define MICROPY_EMIT_THUMB (0) #define MICROPY_EMIT_INLINE_THUMB (0) @@ -33,27 +34,43 @@ #define MICROPY_ENABLE_FINALISER (1) #define MICROPY_MEM_STATS (1) #define MICROPY_DEBUG_PRINTERS (1) -#define MICROPY_ENABLE_REPL_HELPERS (1) -#define MICROPY_ENABLE_LEXER_UNIX (1) +#define MICROPY_HELPER_REPL (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_PATH_MAX (PATH_MAX) #define MICROPY_STREAMS_NON_BLOCK (1) -#define MICROPY_USE_COMPUTED_GOTO (1) -#define MICROPY_MOD_SYS_STDFILES (1) -#define MICROPY_ENABLE_MOD_CMATH (1) +#define MICROPY_OPT_COMPUTED_GOTO (1) +#define MICROPY_PY_FROZENSET (1) +#define MICROPY_PY_SYS_EXIT (1) +#define MICROPY_PY_SYS_STDFILES (1) +#define MICROPY_PY_CMATH (1) +#define MICROPY_PY_IO_FILEIO (1) // 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) +extern const struct _mp_obj_module_t mp_module_os; extern const struct _mp_obj_module_t mp_module_time; extern const struct _mp_obj_module_t mp_module_socket; extern const struct _mp_obj_module_t mp_module_ffi; -#define MICROPY_EXTRA_BUILTIN_MODULES \ - { MP_OBJ_NEW_QSTR(MP_QSTR_ffi), (mp_obj_t)&mp_module_ffi }, \ - { MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&mp_module_time }, \ + +#if MICROPY_PY_FFI +#define MICROPY_PY_FFI_DEF { MP_OBJ_NEW_QSTR(MP_QSTR_ffi), (mp_obj_t)&mp_module_ffi }, +#else +#define MICROPY_PY_FFI_DEF +#endif +#if MICROPY_PY_TIME +#define MICROPY_PY_TIME_DEF { MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&mp_module_time }, +#else +#define MICROPY_PY_TIME_DEF +#endif + +#define MICROPY_PORT_BUILTIN_MODULES \ + MICROPY_PY_FFI_DEF \ + MICROPY_PY_TIME_DEF \ { MP_OBJ_NEW_QSTR(MP_QSTR_microsocket), (mp_obj_t)&mp_module_socket }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR__os), (mp_obj_t)&mp_module_os }, \ // type definitions for the specific machine @@ -74,6 +91,6 @@ typedef const void *machine_const_ptr_t; // must be of pointer size extern const struct _mp_obj_fun_native_t mp_builtin_input_obj; extern const struct _mp_obj_fun_native_t mp_builtin_open_obj; -#define MICROPY_EXTRA_BUILTINS \ +#define MICROPY_PORT_BUILTINS \ { MP_OBJ_NEW_QSTR(MP_QSTR_input), (mp_obj_t)&mp_builtin_input_obj }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj }, diff --git a/unix/mpconfigport.mk b/unix/mpconfigport.mk index 352d010676..f9b99e234c 100644 --- a/unix/mpconfigport.mk +++ b/unix/mpconfigport.mk @@ -7,7 +7,7 @@ MICROPY_FORCE_32BIT = 0 MICROPY_USE_READLINE = 1 # Subset of CPython time module -MICROPY_MOD_TIME = 1 +MICROPY_PY_TIME = 1 # ffi module requires libffi (libffi-dev Debian package) -MICROPY_MOD_FFI = 1 +MICROPY_PY_FFI = 1 diff --git a/unix/qstrdefsport.h b/unix/qstrdefsport.h index 55a82ec067..de0b3d8fae 100644 --- a/unix/qstrdefsport.h +++ b/unix/qstrdefsport.h @@ -33,6 +33,9 @@ Q(makefile) Q(FileIO) +Q(_os) +Q(stat) + Q(ffi) Q(ffimod) Q(ffifunc) diff --git a/unix/seg_helpers.c b/unix/seg_helpers.c new file mode 100644 index 0000000000..1684f7a8f8 --- /dev/null +++ b/unix/seg_helpers.c @@ -0,0 +1,38 @@ +/* + * This file is part of the Micro Python 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 is a stub used to create the symbols __bss_start and _end in a Mach-O object file. + Thoses are needed by the GC, and should point to the start and end of the bss section. + We reach this goal by linking this file last (putting _end at the end...), and using an + order file (order.def) to move __bss_start at the start of bss. + + TODO: Some pragma to do it inline ? +*/ + +char __bss_start = 0; +char _end = 0; + |