From 6e6b888e31f9a4c245f621ccd91d3fce5ac88463 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Wed, 5 Feb 2014 00:44:55 +0200 Subject: Add generic MIN()/MAX() functions. --- py/misc.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'py') diff --git a/py/misc.h b/py/misc.h index 52498c70b..f58a9f669 100644 --- a/py/misc.h +++ b/py/misc.h @@ -10,6 +10,11 @@ typedef unsigned char byte; typedef unsigned int uint; +/** generic ops *************************************************/ + +#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#define MAX(x, y) ((x) > (y) ? (x) : (y)) + /** memomry allocation ******************************************/ // TODO make a lazy m_renew that can increase by a smaller amount than requested (but by at least 1 more element) -- cgit v1.2.3 From e11b17c25ff23b5d6c5e74bc2a9bbd28bc8d2fde Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Wed, 5 Feb 2014 00:47:06 +0200 Subject: Implement support for sys.path when loading modules. sys.path is not initialized by rt_init(), that's left for platform-specific startup code. (For example, bare metal port may have some hardcoded defaults, and let user change sys.path directly; while port for OS with environment feature can take path from environment). If it's not explicitly initialized, modules will be imported only from a current directory. --- py/builtinimport.c | 41 ++++++++++++++++++++++++++++++++++++++--- py/lexerunix.c | 1 - py/misc.h | 11 +++++++++++ py/qstrdefs.h | 1 + py/runtime.c | 8 +++++++- py/runtime.h | 1 + 6 files changed, 58 insertions(+), 5 deletions(-) (limited to 'py') diff --git a/py/builtinimport.c b/py/builtinimport.c index a5deed392..92d9ada89 100644 --- a/py/builtinimport.c +++ b/py/builtinimport.c @@ -19,6 +19,8 @@ #include "map.h" #include "builtin.h" +mp_obj_t sys_path; + mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) { /* printf("import:\n"); @@ -37,10 +39,43 @@ mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) { } // find the file to import - mp_lexer_t *lex = mp_import_open_file(mod_name); + uint mod_name_len; + const byte* mod_name_p = qstr_data(mod_name, &mod_name_len); + mp_lexer_t *lex = NULL; + + uint path_num = 0; + mp_obj_t *path_items; + if (sys_path != MP_OBJ_NULL) { + mp_obj_list_get(sys_path, &path_num, &path_items); + } + + if (path_num == 0) { + CHECKBUF(fname, PATH_MAX); + CHECKBUF_APPEND(fname, mod_name_p, mod_name_len); + CHECKBUF_APPEND(fname, ".py", sizeof(".py") - 1); + CHECKBUF_APPEND_0(fname); + lex = mp_lexer_new_from_file(fname); + } else { + for (int i = 0; i < path_num; i++) { + CHECKBUF(fname, PATH_MAX); + uint p_len; + const byte *p = mp_obj_str_get_data(path_items[i], &p_len); + if (p_len > 0) { + CHECKBUF_APPEND(fname, p, p_len); + CHECKBUF_APPEND(fname, "/", 1); + } + CHECKBUF_APPEND(fname, mod_name_p, mod_name_len); + CHECKBUF_APPEND(fname, ".py", sizeof(".py") - 1); + CHECKBUF_APPEND_0(fname); + lex = mp_lexer_new_from_file(fname); + if (lex != NULL) { + break; + } + } + } + if (lex == NULL) { - // TODO handle lexer error correctly - return mp_const_none; + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_ImportError, "ImportError: No module named '%s'", mod_name_p)); } qstr source_name = mp_lexer_source_name(lex); diff --git a/py/lexerunix.c b/py/lexerunix.c index 5d96c468f..aa1cbc486 100644 --- a/py/lexerunix.c +++ b/py/lexerunix.c @@ -14,7 +14,6 @@ mp_lexer_t *mp_lexer_new_from_file(const char *filename) { int fd = open(filename, O_RDONLY); if (fd < 0) { - printf("cannot open file %s\n", filename); return NULL; } uint size = lseek(fd, 0, SEEK_END); diff --git a/py/misc.h b/py/misc.h index f58a9f669..0fad9459f 100644 --- a/py/misc.h +++ b/py/misc.h @@ -90,6 +90,17 @@ void vstr_add_strn(vstr_t *vstr, const char *str, int len); void vstr_cut_tail(vstr_t *vstr, int len); void vstr_printf(vstr_t *vstr, const char *fmt, ...); +/** non-dynamic size-bounded variable buffer/string *************/ + +#define CHECKBUF(buf, max_size) char buf[max_size + 1]; uint buf##_len = max_size; char *buf##_p = buf; +#define CHECKBUF_APPEND(buf, src, src_len) \ + { int l = MIN(src_len, buf##_len); \ + memcpy(buf##_p, src, l); \ + buf##_len -= l; \ + buf##_p += l; } +#define CHECKBUF_APPEND_0(buf) { *buf##_p = 0; } +#define CHECKBUF_LEN(buf) (buf##_p - buf) + #ifdef va_start void vstr_vprintf(vstr_t *vstr, const char *fmt, va_list ap); #endif diff --git a/py/qstrdefs.h b/py/qstrdefs.h index bf575e25d..3eb306723 100644 --- a/py/qstrdefs.h +++ b/py/qstrdefs.h @@ -73,6 +73,7 @@ Q(max) Q(min) Q(next) Q(ord) +Q(path) Q(pow) Q(print) Q(range) diff --git a/py/runtime.c b/py/runtime.c index c84a28e4c..6d3cbf85b 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -168,8 +168,14 @@ void rt_init(void) { #if MICROPY_CPYTHON_COMPAT // Precreate sys module, so "import sys" didn't throw exceptions. - mp_obj_new_module(MP_QSTR_sys); + mp_obj_t m_sys = mp_obj_new_module(MP_QSTR_sys); + // Avoid warning of unused var + (void)m_sys; #endif + // init sys.path + // for efficiency, left to platform-specific startup code + //sys_path = mp_obj_new_list(0, NULL); + //rt_store_attr(m_sys, MP_QSTR_path, sys_path); mp_module_micropython_init(); diff --git a/py/runtime.h b/py/runtime.h index aafe1a06a..20595c6a5 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -46,3 +46,4 @@ void rt_locals_set(struct _mp_map_t *m); struct _mp_map_t *rt_globals_get(void); void rt_globals_set(struct _mp_map_t *m); struct _mp_map_t *rt_loaded_modules_get(void); +extern mp_obj_t sys_path; -- cgit v1.2.3 From 911089606376e60bd9451a85eb9558a23cde9039 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Wed, 5 Feb 2014 02:03:23 +0200 Subject: Remove older import helpers, no longer used. --- py/lexerunix.c | 20 -------------------- 1 file changed, 20 deletions(-) (limited to 'py') diff --git a/py/lexerunix.c b/py/lexerunix.c index aa1cbc486..fb62d3d72 100644 --- a/py/lexerunix.c +++ b/py/lexerunix.c @@ -30,24 +30,4 @@ mp_lexer_t *mp_lexer_new_from_file(const char *filename) { return mp_lexer_new_from_str_len(qstr_from_str(filename), data, size, size); } -/******************************************************************************/ -/* unix implementation of import */ - -// TODO properly! - -static const char *import_base_dir = NULL; - -void mp_import_set_directory(const char *dir) { - import_base_dir = dir; -} - -mp_lexer_t *mp_import_open_file(qstr mod_name) { - vstr_t *vstr = vstr_new(); - if (import_base_dir != NULL) { - vstr_printf(vstr, "%s/", import_base_dir); - } - vstr_printf(vstr, "%s.py", qstr_str(mod_name)); - return mp_lexer_new_from_file(vstr_str(vstr)); // TODO does lexer need to copy the string? can we free it here? -} - #endif // MICROPY_ENABLE_LEXER_UNIX -- cgit v1.2.3