summaryrefslogtreecommitdiffstatshomepage
path: root/py
diff options
context:
space:
mode:
Diffstat (limited to 'py')
-rw-r--r--py/builtinimport.c26
-rw-r--r--py/misc.h11
-rw-r--r--py/mpconfig.h6
-rw-r--r--py/vstr.c40
4 files changed, 63 insertions, 20 deletions
diff --git a/py/builtinimport.c b/py/builtinimport.c
index c725f075b6..1ef7be8702 100644
--- a/py/builtinimport.c
+++ b/py/builtinimport.c
@@ -149,7 +149,7 @@ mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) {
const char *mod_str = (const char*)mp_obj_str_get_data(args[0], &mod_len);
uint last = 0;
- vstr_t *path = vstr_new();
+ VSTR_FIXED(path, MICROPY_PATH_MAX)
module_obj = MP_OBJ_NULL;
uint i;
for (i = 1; i <= mod_len; i++) {
@@ -159,14 +159,14 @@ mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) {
// find the file corresponding to the module name
mp_import_stat_t stat;
- if (vstr_len(path) == 0) {
+ if (vstr_len(&path) == 0) {
// first module in the dotted-name; search for a directory or file
- stat = find_file(mod_str, i, path);
+ stat = find_file(mod_str, i, &path);
} else {
// latter module in the dotted-name; append to path
- vstr_add_char(path, PATH_SEP_CHAR);
- vstr_add_strn(path, mod_str + last, i - last);
- stat = stat_dir_or_file(path);
+ vstr_add_char(&path, PATH_SEP_CHAR);
+ vstr_add_strn(&path, mod_str + last, i - last);
+ stat = stat_dir_or_file(&path);
}
last = i + 1;
@@ -182,14 +182,14 @@ mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) {
module_obj = mp_obj_new_module(mod_name);
if (stat == MP_IMPORT_STAT_DIR) {
- vstr_add_char(path, PATH_SEP_CHAR);
- vstr_add_str(path, "__init__.py");
- if (mp_import_stat(vstr_str(path)) == MP_IMPORT_STAT_FILE) {
- do_load(module_obj, path);
+ vstr_add_char(&path, PATH_SEP_CHAR);
+ vstr_add_str(&path, "__init__.py");
+ if (mp_import_stat(vstr_str(&path)) == MP_IMPORT_STAT_FILE) {
+ do_load(module_obj, &path);
}
- vstr_cut_tail(path, 12); // cut off /__init__.py
+ vstr_cut_tail(&path, 12); // cut off /__init__.py
} else { // MP_IMPORT_STAT_FILE
- do_load(module_obj, path);
+ do_load(module_obj, &path);
break;
}
}
@@ -202,8 +202,6 @@ mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) {
assert(0);
}
- vstr_free(path);
-
return module_obj;
}
diff --git a/py/misc.h b/py/misc.h
index 679a14b5b9..065b070892 100644
--- a/py/misc.h
+++ b/py/misc.h
@@ -68,10 +68,17 @@ typedef struct _vstr_t {
int alloc;
int len;
char *buf;
- bool had_error;
+ struct {
+ bool had_error : 1;
+ bool fixed_buf : 1;
+ };
} vstr_t;
+// convenience macro to declare a vstr with a fixed size buffer on the stack
+#define VSTR_FIXED(vstr, alloc) vstr_t vstr; char vstr##_buf[(alloc)]; vstr_init_fixed_buf(&vstr, (alloc), vstr##_buf);
+
void vstr_init(vstr_t *vstr, int alloc);
+void vstr_init_fixed_buf(vstr_t *vstr, int alloc, char *buf);
void vstr_clear(vstr_t *vstr);
vstr_t *vstr_new(void);
vstr_t *vstr_new_size(int alloc);
@@ -81,7 +88,7 @@ bool vstr_had_error(vstr_t *vstr);
char *vstr_str(vstr_t *vstr);
int vstr_len(vstr_t *vstr);
void vstr_hint_size(vstr_t *vstr, int size);
-char *vstr_extend(vstr_t *vstr, int size);
+char *vstr_extend(vstr_t *vstr, int size);
bool vstr_set_size(vstr_t *vstr, int size);
bool vstr_shrink(vstr_t *vstr);
char *vstr_add_len(vstr_t *vstr, int len);
diff --git a/py/mpconfig.h b/py/mpconfig.h
index 38b74b733a..799c9d8e71 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -101,6 +101,12 @@ typedef long long mp_longint_impl_t;
#define MICROPY_CPYTHON_COMPAT (1)
#endif
+// Maximum length of a path in the filesystem
+// So we can allocate a buffer on the stack for path manipulation in import
+#ifndef MICROPY_PATH_MAX
+#define MICROPY_PATH_MAX (512)
+#endif
+
/*****************************************************************************/
/* Miscellaneous settings */
diff --git a/py/vstr.c b/py/vstr.c
index b2e46c89f9..4d10dfba82 100644
--- a/py/vstr.c
+++ b/py/vstr.c
@@ -1,6 +1,7 @@
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
+#include <assert.h>
#include "misc.h"
// returned value is always at least 1 greater than argument
@@ -16,10 +17,23 @@ void vstr_init(vstr_t *vstr, int alloc) {
}
vstr->buf[0] = 0;
vstr->had_error = false;
+ vstr->fixed_buf = false;
+}
+
+void vstr_init_fixed_buf(vstr_t *vstr, int alloc, char *buf) {
+ assert(alloc > 0); // need at least room for the null byte
+ vstr->alloc = alloc;
+ vstr->len = 0;
+ vstr->buf = buf;
+ vstr->buf[0] = 0;
+ vstr->had_error = false;
+ vstr->fixed_buf = true;
}
void vstr_clear(vstr_t *vstr) {
- m_del(char, vstr->buf, vstr->alloc);
+ if (!vstr->fixed_buf) {
+ m_del(char, vstr->buf, vstr->alloc);
+ }
vstr->buf = NULL;
}
@@ -43,7 +57,9 @@ vstr_t *vstr_new_size(int alloc) {
void vstr_free(vstr_t *vstr) {
if (vstr != NULL) {
- m_del(char, vstr->buf, vstr->alloc);
+ if (!vstr->fixed_buf) {
+ m_del(char, vstr->buf, vstr->alloc);
+ }
m_del_obj(vstr_t, vstr);
}
}
@@ -73,7 +89,10 @@ int vstr_len(vstr_t *vstr) {
}
// Extend vstr strictly to by requested size, return pointer to newly added chunk
-char *vstr_extend(vstr_t *vstr, int size) {
+char *vstr_extend(vstr_t *vstr, int size) {
+ if (vstr->fixed_buf) {
+ return NULL;
+ }
char *new_buf = m_renew(char, vstr->buf, vstr->alloc, vstr->alloc + size);
if (new_buf == NULL) {
vstr->had_error = true;
@@ -87,6 +106,9 @@ char *vstr_extend(vstr_t *vstr, int size) {
// Shrink vstr to be given size
bool vstr_set_size(vstr_t *vstr, int size) {
+ if (vstr->fixed_buf) {
+ return false;
+ }
char *new_buf = m_renew(char, vstr->buf, vstr->alloc, size);
if (new_buf == NULL) {
vstr->had_error = true;
@@ -102,8 +124,11 @@ bool vstr_shrink(vstr_t *vstr) {
return vstr_set_size(vstr, vstr->len);
}
-bool vstr_ensure_extra(vstr_t *vstr, int size) {
+static bool vstr_ensure_extra(vstr_t *vstr, int size) {
if (vstr->len + size + 1 > vstr->alloc) {
+ if (vstr->fixed_buf) {
+ return false;
+ }
int new_alloc = ROUND_ALLOC((vstr->len + size + 1) * 2);
char *new_buf = m_renew(char, vstr->buf, vstr->alloc, new_alloc);
if (new_buf == NULL) {
@@ -156,8 +181,15 @@ void vstr_add_str(vstr_t *vstr, const char *str) {
void vstr_add_strn(vstr_t *vstr, const char *str, int len) {
if (vstr->had_error || !vstr_ensure_extra(vstr, len)) {
+ // if buf is fixed, we got here because there isn't enough room left
+ // so just try to copy as much as we can, with room for null byte
+ if (vstr->fixed_buf && vstr->len + 1 < vstr->alloc) {
+ len = vstr->alloc - vstr->len - 1;
+ goto copy;
+ }
return;
}
+copy:
memmove(vstr->buf + vstr->len, str, len);
vstr->len += len;
vstr->buf[vstr->len] = 0;