summaryrefslogtreecommitdiffstatshomepage
path: root/unix
diff options
context:
space:
mode:
Diffstat (limited to 'unix')
-rw-r--r--unix/Makefile27
-rw-r--r--unix/file.c73
-rw-r--r--unix/gccollect.c6
-rw-r--r--unix/main.c59
-rw-r--r--unix/modffi.c1
-rw-r--r--unix/modos.c87
-rw-r--r--unix/modsocket.c21
-rw-r--r--unix/modtime.c32
-rw-r--r--unix/mpconfigport.h37
-rw-r--r--unix/mpconfigport.mk4
-rw-r--r--unix/qstrdefsport.h3
-rw-r--r--unix/seg_helpers.c38
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)&microsocket_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;
+