summaryrefslogtreecommitdiffstatshomepage
path: root/py
diff options
context:
space:
mode:
Diffstat (limited to 'py')
-rw-r--r--py/misc.h2
-rw-r--r--py/modbuiltins.c18
-rw-r--r--py/modsys.c9
-rw-r--r--py/mpconfig.h7
-rw-r--r--py/mpprint.c (renamed from py/pfenv.c)224
-rw-r--r--py/mpprint.h (renamed from py/pfenv.h)40
-rw-r--r--py/obj.c36
-rw-r--r--py/obj.h9
-rw-r--r--py/objarray.c18
-rw-r--r--py/objbool.c10
-rw-r--r--py/objboundmeth.c12
-rw-r--r--py/objcell.c10
-rw-r--r--py/objclosure.c16
-rw-r--r--py/objcomplex.c18
-rw-r--r--py/objdict.c30
-rw-r--r--py/objexcept.c12
-rw-r--r--py/objfloat.c10
-rw-r--r--py/objfun.c4
-rw-r--r--py/objgenerator.c4
-rw-r--r--py/objint.c4
-rw-r--r--py/objint.h2
-rw-r--r--py/objlist.c10
-rw-r--r--py/objmodule.c6
-rw-r--r--py/objnamedtuple.c12
-rw-r--r--py/objnone.c6
-rw-r--r--py/objrange.c8
-rw-r--r--py/objset.c19
-rw-r--r--py/objslice.c20
-rw-r--r--py/objstr.c110
-rw-r--r--py/objstr.h2
-rw-r--r--py/objstringio.c4
-rw-r--r--py/objstrunicode.c33
-rw-r--r--py/objtuple.c16
-rw-r--r--py/objtuple.h2
-rw-r--r--py/objtype.c28
-rw-r--r--py/pfenv_printf.c204
-rw-r--r--py/py.mk3
-rw-r--r--py/runtime.h3
-rw-r--r--py/vstr.c37
39 files changed, 485 insertions, 533 deletions
diff --git a/py/misc.h b/py/misc.h
index f920d52a17..2c00b6880f 100644
--- a/py/misc.h
+++ b/py/misc.h
@@ -147,6 +147,8 @@ typedef struct _vstr_t {
void vstr_init(vstr_t *vstr, size_t alloc);
void vstr_init_len(vstr_t *vstr, size_t len);
void vstr_init_fixed_buf(vstr_t *vstr, size_t alloc, char *buf);
+struct _mp_print_t;
+void vstr_init_print(vstr_t *vstr, size_t alloc, struct _mp_print_t *print);
void vstr_clear(vstr_t *vstr);
vstr_t *vstr_new(void);
vstr_t *vstr_new_size(size_t alloc);
diff --git a/py/modbuiltins.c b/py/modbuiltins.c
index 04141edec9..f080f457b6 100644
--- a/py/modbuiltins.c
+++ b/py/modbuiltins.c
@@ -35,7 +35,6 @@
#include "py/runtime.h"
#include "py/builtin.h"
#include "py/stream.h"
-#include "py/pfenv.h"
#if MICROPY_PY_BUILTINS_FLOAT
#include <math.h>
@@ -413,9 +412,7 @@ STATIC mp_obj_t mp_builtin_print(mp_uint_t n_args, const mp_obj_t *args, mp_map_
stream_obj = file_elem->value;
}
- pfenv_t pfenv;
- pfenv.data = stream_obj;
- pfenv.print_strn = (void (*)(void *, const char *, mp_uint_t))mp_stream_write;
+ mp_print_t print = {stream_obj, (mp_print_strn_t)mp_stream_write};
#endif
for (mp_uint_t i = 0; i < n_args; i++) {
if (i > 0) {
@@ -426,7 +423,7 @@ STATIC mp_obj_t mp_builtin_print(mp_uint_t n_args, const mp_obj_t *args, mp_map_
#endif
}
#if MICROPY_PY_IO
- mp_obj_print_helper((void (*)(void *env, const char *fmt, ...))pfenv_printf, &pfenv, args[i], PRINT_STR);
+ mp_obj_print_helper(&print, args[i], PRINT_STR);
#else
mp_obj_print(args[i], PRINT_STR);
#endif
@@ -443,10 +440,8 @@ MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_print_obj, 0, mp_builtin_print);
STATIC mp_obj_t mp_builtin___repl_print__(mp_obj_t o) {
if (o != mp_const_none) {
#if MICROPY_PY_IO
- pfenv_t pfenv;
- pfenv.data = &mp_sys_stdout_obj;
- pfenv.print_strn = (void (*)(void *, const char *, mp_uint_t))mp_stream_write;
- mp_obj_print_helper((void (*)(void *env, const char *fmt, ...))pfenv_printf, &pfenv, o, PRINT_REPR);
+ mp_print_t print = {&mp_sys_stdout_obj, (mp_print_strn_t)mp_stream_write};
+ mp_obj_print_helper(&print, o, PRINT_REPR);
mp_stream_write(&mp_sys_stdout_obj, "\n", 1);
#else
mp_obj_print(o, PRINT_REPR);
@@ -459,8 +454,9 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin___repl_print___obj, mp_builtin___repl_print
STATIC mp_obj_t mp_builtin_repr(mp_obj_t o_in) {
vstr_t vstr;
- vstr_init(&vstr, 16);
- mp_obj_print_helper((void (*)(void *env, const char *fmt, ...))vstr_printf, &vstr, o_in, PRINT_REPR);
+ mp_print_t print;
+ vstr_init_print(&vstr, 16, &print);
+ mp_obj_print_helper(&print, o_in, PRINT_REPR);
return mp_obj_new_str_from_vstr(&mp_type_str, &vstr);
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_repr_obj, mp_builtin_repr);
diff --git a/py/modsys.c b/py/modsys.c
index 5051e72951..09e72e98ad 100644
--- a/py/modsys.c
+++ b/py/modsys.c
@@ -31,7 +31,6 @@
#include "py/objtuple.h"
#include "py/objstr.h"
#include "py/objint.h"
-#include "py/pfenv.h"
#include "py/stream.h"
#if MICROPY_PY_SYS
@@ -78,12 +77,10 @@ STATIC mp_obj_t mp_sys_print_exception(mp_uint_t n_args, const mp_obj_t *args) {
stream_obj = args[1];
}
- pfenv_t pfenv;
- pfenv.data = stream_obj;
- pfenv.print_strn = (void (*)(void *, const char *, mp_uint_t))mp_stream_write;
- mp_obj_print_exception((void (*)(void *env, const char *fmt, ...))pfenv_printf, &pfenv, args[0]);
+ mp_print_t print = {stream_obj, (mp_print_strn_t)mp_stream_write};
+ mp_obj_print_exception(&print, args[0]);
#else
- mp_obj_print_exception(printf_wrapper, NULL, args[0]);
+ mp_obj_print_exception(&mp_plat_print, args[0]);
#endif
return mp_const_none;
diff --git a/py/mpconfig.h b/py/mpconfig.h
index 21ae0c3f53..c78221f3a5 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -691,7 +691,7 @@ typedef double mp_float_t;
#define MICROPY_MAKE_POINTER_CALLABLE(p) (p)
#endif
-// If these MP_PLAT_* macros are overridden then the memory allocated by them
+// If these MP_PLAT_*_EXEC macros are overridden then the memory allocated by them
// must be somehow reachable for marking by the GC, since the native code
// generators store pointers to GC managed memory in the code.
#ifndef MP_PLAT_ALLOC_EXEC
@@ -702,6 +702,11 @@ typedef double mp_float_t;
#define MP_PLAT_FREE_EXEC(ptr, size) m_del(byte, ptr, size)
#endif
+// This macro is used to do all output (except when MICROPY_PY_IO is defined)
+#ifndef MP_PLAT_PRINT_STRN
+#define MP_PLAT_PRINT_STRN(str, len) printf("%.*s", (int)len, str)
+#endif
+
#ifndef MP_SSIZE_MAX
#define MP_SSIZE_MAX SSIZE_MAX
#endif
diff --git a/py/pfenv.c b/py/mpprint.c
index f0a894e49b..cb39aa8131 100644
--- a/py/pfenv.c
+++ b/py/mpprint.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2013-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
@@ -24,11 +24,16 @@
* THE SOFTWARE.
*/
+#include <assert.h>
+#include <stdarg.h>
#include <stdint.h>
+#include <stdio.h>
#include <string.h>
+#include "py/mpprint.h"
+#include "py/obj.h"
#include "py/objint.h"
-#include "py/pfenv.h"
+#include "py/runtime.h"
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
#include <stdio.h>
@@ -41,11 +46,22 @@
static const char pad_spaces[] = " ";
static const char pad_zeroes[] = "0000000000000000";
-void pfenv_vstr_add_strn(void *data, const char *str, mp_uint_t len) {
- vstr_add_strn(data, str, len);
+STATIC void plat_print_strn(void *env, const char *str, mp_uint_t len) {
+ (void)env;
+ MP_PLAT_PRINT_STRN(str, len);
}
-int pfenv_print_strn(const pfenv_t *pfenv, const char *str, mp_uint_t len, int flags, char fill, int width) {
+const mp_print_t mp_plat_print = {NULL, plat_print_strn};
+
+int mp_print_str(const mp_print_t *print, const char *str) {
+ mp_uint_t len = strlen(str);
+ if (len) {
+ print->print_strn(print->data, str, len);
+ }
+ return len;
+}
+
+int mp_print_strn(const mp_print_t *print, const char *str, mp_uint_t len, int flags, char fill, int width) {
int left_pad = 0;
int right_pad = 0;
int pad = width - len;
@@ -53,7 +69,7 @@ int pfenv_print_strn(const pfenv_t *pfenv, const char *str, mp_uint_t len, int f
int total_chars_printed = 0;
const char *pad_chars;
- if (!fill || fill == ' ' ) {
+ if (!fill || fill == ' ') {
pad_chars = pad_spaces;
pad_size = sizeof(pad_spaces) - 1;
} else if (fill == '0') {
@@ -82,12 +98,12 @@ int pfenv_print_strn(const pfenv_t *pfenv, const char *str, mp_uint_t len, int f
if (p > pad_size) {
p = pad_size;
}
- pfenv->print_strn(pfenv->data, pad_chars, p);
+ print->print_strn(print->data, pad_chars, p);
left_pad -= p;
}
}
if (len) {
- pfenv->print_strn(pfenv->data, str, len);
+ print->print_strn(print->data, str, len);
total_chars_printed += len;
}
if (right_pad > 0) {
@@ -97,7 +113,7 @@ int pfenv_print_strn(const pfenv_t *pfenv, const char *str, mp_uint_t len, int f
if (p > pad_size) {
p = pad_size;
}
- pfenv->print_strn(pfenv->data, pad_chars, p);
+ print->print_strn(print->data, pad_chars, p);
right_pad -= p;
}
}
@@ -109,8 +125,8 @@ int pfenv_print_strn(const pfenv_t *pfenv, const char *str, mp_uint_t len, int f
#define INT_BUF_SIZE (sizeof(mp_int_t) * 4)
// This function is used by stmhal port to implement printf.
-// It needs to be a separate function to pfenv_print_mp_int, since converting to a mp_int looses the MSB.
-int pfenv_print_int(const pfenv_t *pfenv, mp_uint_t x, int sgn, int base, int base_char, int flags, char fill, int width) {
+// It needs to be a separate function to mp_print_mp_int, since converting to a mp_int looses the MSB.
+int mp_print_int(const mp_print_t *print, mp_uint_t x, int sgn, int base, int base_char, int flags, char fill, int width) {
char sign = 0;
if (sgn) {
if ((mp_int_t)x < 0) {
@@ -156,12 +172,12 @@ int pfenv_print_int(const pfenv_t *pfenv, mp_uint_t x, int sgn, int base, int ba
int len = 0;
if (flags & PF_FLAG_PAD_AFTER_SIGN) {
if (sign) {
- len += pfenv_print_strn(pfenv, &sign, 1, flags, fill, 1);
+ len += mp_print_strn(print, &sign, 1, flags, fill, 1);
width--;
}
if (prefix_char) {
- len += pfenv_print_strn(pfenv, "0", 1, flags, fill, 1);
- len += pfenv_print_strn(pfenv, &prefix_char, 1, flags, fill, 1);
+ len += mp_print_strn(print, "0", 1, flags, fill, 1);
+ len += mp_print_strn(print, &prefix_char, 1, flags, fill, 1);
width -= 2;
}
} else {
@@ -174,11 +190,11 @@ int pfenv_print_int(const pfenv_t *pfenv, mp_uint_t x, int sgn, int base, int ba
}
}
- len += pfenv_print_strn(pfenv, b, buf + INT_BUF_SIZE - b, flags, fill, width);
+ len += mp_print_strn(print, b, buf + INT_BUF_SIZE - b, flags, fill, width);
return len;
}
-int pfenv_print_mp_int(const pfenv_t *pfenv, mp_obj_t x, int base, int base_char, int flags, char fill, int width, int prec) {
+int mp_print_mp_int(const mp_print_t *print, mp_obj_t x, int base, int base_char, int flags, char fill, int width, int prec) {
if (!MP_OBJ_IS_INT(x)) {
// This will convert booleans to int, or raise an error for
// non-integer types.
@@ -282,16 +298,16 @@ int pfenv_print_mp_int(const pfenv_t *pfenv, mp_obj_t x, int base, int base_char
int len = 0;
if (spaces_before) {
- len += pfenv_print_strn(pfenv, "", 0, 0, ' ', spaces_before);
+ len += mp_print_strn(print, "", 0, 0, ' ', spaces_before);
}
if (flags & PF_FLAG_PAD_AFTER_SIGN) {
// pad after sign implies pad after prefix as well.
if (sign) {
- len += pfenv_print_strn(pfenv, &sign, 1, 0, 0, 1);
+ len += mp_print_strn(print, &sign, 1, 0, 0, 1);
width--;
}
if (prefix_len) {
- len += pfenv_print_strn(pfenv, prefix, prefix_len, 0, 0, 1);
+ len += mp_print_strn(print, prefix, prefix_len, 0, 0, 1);
width -= prefix_len;
}
}
@@ -299,10 +315,10 @@ int pfenv_print_mp_int(const pfenv_t *pfenv, mp_obj_t x, int base, int base_char
width = prec;
}
- len += pfenv_print_strn(pfenv, str, fmt_size, flags, fill, width);
+ len += mp_print_strn(print, str, fmt_size, flags, fill, width);
if (spaces_after) {
- len += pfenv_print_strn(pfenv, "", 0, 0, ' ', spaces_after);
+ len += mp_print_strn(print, "", 0, 0, ' ', spaces_after);
}
if (buf != stack_buf) {
@@ -312,7 +328,7 @@ int pfenv_print_mp_int(const pfenv_t *pfenv, mp_obj_t x, int base, int base_char
}
#if MICROPY_PY_BUILTINS_FLOAT
-int pfenv_print_float(const pfenv_t *pfenv, mp_float_t f, char fmt, int flags, char fill, int width, int prec) {
+int mp_print_float(const mp_print_t *print, mp_float_t f, char fmt, int flags, char fill, int width, int prec) {
char buf[32];
char sign = '\0';
int chrs = 0;
@@ -361,7 +377,7 @@ int pfenv_print_float(const pfenv_t *pfenv, mp_float_t f, char fmt, int flags, c
if (*s <= '9' || (flags & PF_FLAG_PAD_NAN_INF)) {
// We have a number, or we have a inf/nan and PAD_NAN_INF is set
// With '{:06e}'.format(float('-inf')) you get '-00inf'
- chrs += pfenv_print_strn(pfenv, &buf[0], 1, 0, 0, 1);
+ chrs += mp_print_strn(print, &buf[0], 1, 0, 0, 1);
width--;
len--;
}
@@ -373,8 +389,168 @@ int pfenv_print_float(const pfenv_t *pfenv, mp_float_t f, char fmt, int flags, c
// so suppress the zero fill.
fill = ' ';
}
- chrs += pfenv_print_strn(pfenv, s, len, flags, fill, width);
+ chrs += mp_print_strn(print, s, len, flags, fill, width);
return chrs;
}
#endif
+
+int mp_printf(const mp_print_t *print, const char *fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ int ret = mp_vprintf(print, fmt, ap);
+ va_end(ap);
+ return ret;
+}
+
+int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) {
+ int chrs = 0;
+ for (;;) {
+ {
+ const char *f = fmt;
+ while (*f != '\0' && *f != '%') {
+ ++f; // XXX UTF8 advance char
+ }
+ if (f > fmt) {
+ print->print_strn(print->data, fmt, f - fmt);
+ chrs += f - fmt;
+ fmt = f;
+ }
+ }
+
+ if (*fmt == '\0') {
+ break;
+ }
+
+ // move past % character
+ ++fmt;
+
+ // parse flags, if they exist
+ int flags = 0;
+ char fill = ' ';
+ while (*fmt != '\0') {
+ if (*fmt == '-') flags |= PF_FLAG_LEFT_ADJUST;
+ else if (*fmt == '+') flags |= PF_FLAG_SHOW_SIGN;
+ else if (*fmt == ' ') flags |= PF_FLAG_SPACE_SIGN;
+ else if (*fmt == '!') flags |= PF_FLAG_NO_TRAILZ;
+ else if (*fmt == '0') {
+ flags |= PF_FLAG_PAD_AFTER_SIGN;
+ fill = '0';
+ } else break;
+ ++fmt;
+ }
+
+ // parse width, if it exists
+ int width = 0;
+ for (; '0' <= *fmt && *fmt <= '9'; ++fmt) {
+ width = width * 10 + *fmt - '0';
+ }
+
+ // parse precision, if it exists
+ int prec = -1;
+ if (*fmt == '.') {
+ ++fmt;
+ if (*fmt == '*') {
+ ++fmt;
+ prec = va_arg(args, int);
+ } else {
+ prec = 0;
+ for (; '0' <= *fmt && *fmt <= '9'; ++fmt) {
+ prec = prec * 10 + *fmt - '0';
+ }
+ }
+ if (prec < 0) {
+ prec = 0;
+ }
+ }
+
+ // parse long specifiers (current not used)
+ //bool long_arg = false;
+ if (*fmt == 'l') {
+ ++fmt;
+ //long_arg = true;
+ }
+
+ if (*fmt == '\0') {
+ break;
+ }
+
+ switch (*fmt) {
+ case 'b':
+ if (va_arg(args, int)) {
+ chrs += mp_print_strn(print, "true", 4, flags, fill, width);
+ } else {
+ chrs += mp_print_strn(print, "false", 5, flags, fill, width);
+ }
+ break;
+ case 'c':
+ {
+ char str = va_arg(args, int);
+ chrs += mp_print_strn(print, &str, 1, flags, fill, width);
+ break;
+ }
+ case 's':
+ {
+ const char *str = va_arg(args, const char*);
+ if (str) {
+ if (prec < 0) {
+ prec = strlen(str);
+ }
+ chrs += mp_print_strn(print, str, prec, flags, fill, width);
+ } else {
+ chrs += mp_print_strn(print, "(null)", 6, flags, fill, width);
+ }
+ break;
+ }
+ case 'u':
+ chrs += mp_print_int(print, va_arg(args, int), 0, 10, 'a', flags, fill, width);
+ break;
+ case 'd':
+ chrs += mp_print_int(print, va_arg(args, int), 1, 10, 'a', flags, fill, width);
+ break;
+ case 'x':
+ chrs += mp_print_int(print, va_arg(args, int), 0, 16, 'a', flags, fill, width);
+ break;
+ case 'X':
+ chrs += mp_print_int(print, va_arg(args, int), 0, 16, 'A', flags, fill, width);
+ break;
+ case 'p':
+ case 'P': // don't bother to handle upcase for 'P'
+ chrs += mp_print_int(print, va_arg(args, unsigned int), 0, 16, 'a', flags, fill, width);
+ break;
+#if MICROPY_PY_BUILTINS_FLOAT
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'F':
+ case 'g':
+ case 'G':
+ {
+#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
+ mp_float_t f = va_arg(args, double);
+ chrs += mp_print_float(print, f, *fmt, flags, fill, width, prec);
+#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
+ // Currently mp_print_float uses snprintf, but snprintf
+ // itself may be implemented in terms of mp_vprintf() for
+ // some ports. So, for extra caution, this case is handled
+ // with assert below. Note that currently ports which
+ // use MICROPY_FLOAT_IMPL_DOUBLE, don't call mp_vprintf()
+ // with float format specifier at all.
+ // TODO: resolve this completely
+ assert(0);
+//#error Calling mp_print_float with double not supported from within printf
+#else
+#error Unknown MICROPY FLOAT IMPL
+#endif
+ break;
+ }
+#endif
+ default:
+ print->print_strn(print->data, fmt, 1);
+ chrs += 1;
+ break;
+ }
+ ++fmt;
+ }
+ return chrs;
+}
diff --git a/py/pfenv.h b/py/mpprint.h
index 3d2b31b5d0..60fa18acf9 100644
--- a/py/pfenv.h
+++ b/py/mpprint.h
@@ -23,12 +23,10 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-#ifndef __MICROPY_INCLUDED_PY_PFENV_H__
-#define __MICROPY_INCLUDED_PY_PFENV_H__
+#ifndef __MICROPY_INCLUDED_PY_MPPRINT_H__
+#define __MICROPY_INCLUDED_PY_MPPRINT_H__
-#include <stdarg.h>
-
-#include "py/obj.h"
+#include "py/mpconfig.h"
#define PF_FLAG_LEFT_ADJUST (0x001)
#define PF_FLAG_SHOW_SIGN (0x002)
@@ -42,24 +40,28 @@
#define PF_FLAG_PAD_NAN_INF (0x200)
#define PF_FLAG_SHOW_OCTAL_LETTER (0x400)
-typedef struct _pfenv_t {
+typedef void (*mp_print_strn_t)(void *data, const char *str, mp_uint_t len);
+
+typedef struct _mp_print_t {
void *data;
- void (*print_strn)(void *, const char *str, mp_uint_t len);
-} pfenv_t;
+ mp_print_strn_t print_strn;
+} mp_print_t;
-void pfenv_vstr_add_strn(void *data, const char *str, mp_uint_t len);
+// Wrapper for platform print function, which wraps MP_PLAT_PRINT_STRN.
+// All (non-debug) prints go through this interface (except some which
+// go through mp_sys_stdout_obj if MICROPY_PY_IO is defined).
+extern const mp_print_t mp_plat_print;
-int pfenv_print_strn(const pfenv_t *pfenv, const char *str, mp_uint_t len, int flags, char fill, int width);
-int pfenv_print_int(const pfenv_t *pfenv, mp_uint_t x, int sgn, int base, int base_char, int flags, char fill, int width);
-int pfenv_print_mp_int(const pfenv_t *pfenv, mp_obj_t x, int base, int base_char, int flags, char fill, int width, int prec);
+int mp_print_str(const mp_print_t *print, const char *str);
+int mp_print_strn(const mp_print_t *print, const char *str, mp_uint_t len, int flags, char fill, int width);
+int mp_print_int(const mp_print_t *print, mp_uint_t x, int sgn, int base, int base_char, int flags, char fill, int width);
#if MICROPY_PY_BUILTINS_FLOAT
-int pfenv_print_float(const pfenv_t *pfenv, mp_float_t f, char fmt, int flags, char fill, int width, int prec);
+int mp_print_float(const mp_print_t *print, mp_float_t f, char fmt, int flags, char fill, int width, int prec);
#endif
-int pfenv_vprintf(const pfenv_t *pfenv, const char *fmt, va_list args);
-int pfenv_printf(const pfenv_t *pfenv, const char *fmt, ...);
-
-// Wrapper for system printf
-void printf_wrapper(void *env, const char *fmt, ...);
+int mp_printf(const mp_print_t *print, const char *fmt, ...);
+#ifdef va_start
+int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args);
+#endif
-#endif // __MICROPY_INCLUDED_PY_PFENV_H__
+#endif // __MICROPY_INCLUDED_PY_MPPRINT_H__
diff --git a/py/obj.c b/py/obj.c
index 6c851dfb08..0d318fa14d 100644
--- a/py/obj.c
+++ b/py/obj.c
@@ -36,7 +36,7 @@
#include "py/runtime0.h"
#include "py/runtime.h"
#include "py/stackctrl.h"
-#include "py/pfenv.h"
+//#include "py/pfenv.h"
#include "py/stream.h" // for mp_obj_print
mp_obj_type_t *mp_obj_get_type(mp_const_obj_t o_in) {
@@ -54,20 +54,20 @@ const char *mp_obj_get_type_str(mp_const_obj_t o_in) {
return qstr_str(mp_obj_get_type(o_in)->name);
}
-void mp_obj_print_helper(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
+void mp_obj_print_helper(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
// There can be data structures nested too deep, or just recursive
MP_STACK_CHECK();
#ifndef NDEBUG
if (o_in == NULL) {
- print(env, "(nil)");
+ mp_print_str(print, "(nil)");
return;
}
#endif
mp_obj_type_t *type = mp_obj_get_type(o_in);
if (type->print != NULL) {
- type->print(print, env, o_in, kind);
+ type->print((mp_print_t*)print, o_in, kind);
} else {
- print(env, "<%s>", qstr_str(type->name));
+ mp_printf(print, "<%s>", qstr_str(type->name));
}
}
@@ -75,41 +75,41 @@ void mp_obj_print(mp_obj_t o_in, mp_print_kind_t kind) {
#if MICROPY_PY_IO
// defined per port; type of these is irrelevant, just need pointer
extern struct _mp_dummy_t mp_sys_stdout_obj;
- pfenv_t pfenv;
- pfenv.data = &mp_sys_stdout_obj;
- pfenv.print_strn = (void (*)(void *, const char *, mp_uint_t))mp_stream_write;
- mp_obj_print_helper((void (*)(void *env, const char *fmt, ...))pfenv_printf, &pfenv, o_in, kind);
+ mp_print_t print;
+ print.data = &mp_sys_stdout_obj;
+ print.print_strn = (mp_print_strn_t)mp_stream_write;
+ mp_obj_print_helper(&print, o_in, kind);
#else
- mp_obj_print_helper(printf_wrapper, NULL, o_in, kind);
+ mp_obj_print_helper(&mp_plat_print, o_in, kind);
#endif
}
// helper function to print an exception with traceback
-void mp_obj_print_exception(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t exc) {
+void mp_obj_print_exception(const mp_print_t *print, mp_obj_t exc) {
if (mp_obj_is_exception_instance(exc)) {
mp_uint_t n, *values;
mp_obj_exception_get_traceback(exc, &n, &values);
if (n > 0) {
assert(n % 3 == 0);
- print(env, "Traceback (most recent call last):\n");
+ mp_print_str(print, "Traceback (most recent call last):\n");
for (int i = n - 3; i >= 0; i -= 3) {
#if MICROPY_ENABLE_SOURCE_LINE
- print(env, " File \"%s\", line %d", qstr_str(values[i]), (int)values[i + 1]);
+ mp_printf(print, " File \"%s\", line %d", qstr_str(values[i]), (int)values[i + 1]);
#else
- print(env, " File \"%s\"", qstr_str(values[i]));
+ mp_printf(print, " File \"%s\"", qstr_str(values[i]));
#endif
// the block name can be NULL if it's unknown
qstr block = values[i + 2];
if (block == MP_QSTR_NULL) {
- print(env, "\n");
+ mp_print_str(print, "\n");
} else {
- print(env, ", in %s\n", qstr_str(block));
+ mp_printf(print, ", in %s\n", qstr_str(block));
}
}
}
}
- mp_obj_print_helper(print, env, exc, PRINT_EXC);
- print(env, "\n");
+ mp_obj_print_helper(print, exc, PRINT_EXC);
+ mp_print_str(print, "\n");
}
bool mp_obj_is_true(mp_obj_t arg) {
diff --git a/py/obj.h b/py/obj.h
index a5423f0824..86f560ff51 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -29,6 +29,7 @@
#include "py/mpconfig.h"
#include "py/misc.h"
#include "py/qstr.h"
+#include "py/mpprint.h"
// All Micro Python objects are at least this type
// It must be of pointer size
@@ -260,7 +261,7 @@ typedef enum {
PRINT_EXC_SUBCLASS = 0x80, // Internal flag for printing exception subclasses
} mp_print_kind_t;
-typedef void (*mp_print_fun_t)(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o, mp_print_kind_t kind);
+typedef void (*mp_print_fun_t)(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind);
typedef mp_obj_t (*mp_make_new_fun_t)(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args);
typedef mp_obj_t (*mp_call_fun_t)(mp_obj_t fun, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args);
typedef mp_obj_t (*mp_unary_op_fun_t)(mp_uint_t op, mp_obj_t);
@@ -499,9 +500,9 @@ const char *mp_obj_get_type_str(mp_const_obj_t o_in);
bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo); // arguments should be type objects
mp_obj_t mp_instance_cast_to_native_base(mp_const_obj_t self_in, mp_const_obj_t native_type);
-void mp_obj_print_helper(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind);
+void mp_obj_print_helper(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind);
void mp_obj_print(mp_obj_t o, mp_print_kind_t kind);
-void mp_obj_print_exception(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t exc);
+void mp_obj_print_exception(const mp_print_t *print, mp_obj_t exc);
bool mp_obj_is_true(mp_obj_t arg);
bool mp_obj_is_callable(mp_obj_t o_in);
@@ -561,7 +562,7 @@ qstr mp_obj_str_get_qstr(mp_obj_t self_in); // use this if you will anyway conve
const char *mp_obj_str_get_str(mp_obj_t self_in); // use this only if you need the string to be null terminated
const char *mp_obj_str_get_data(mp_obj_t self_in, mp_uint_t *len);
mp_obj_t mp_obj_str_intern(mp_obj_t str);
-void mp_str_print_quoted(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, mp_uint_t str_len, bool is_bytes);
+void mp_str_print_quoted(const mp_print_t *print, const byte *str_data, mp_uint_t str_len, bool is_bytes);
#if MICROPY_PY_BUILTINS_FLOAT
// float
diff --git a/py/objarray.c b/py/objarray.c
index cb2b2b6a1a..33cd7ecc3b 100644
--- a/py/objarray.c
+++ b/py/objarray.c
@@ -76,26 +76,26 @@ STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_ui
// array
#if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY
-STATIC void array_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
+STATIC void array_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
(void)kind;
mp_obj_array_t *o = o_in;
if (o->typecode == BYTEARRAY_TYPECODE) {
- print(env, "bytearray(b");
- mp_str_print_quoted(print, env, o->items, o->len, true);
+ mp_print_str(print, "bytearray(b");
+ mp_str_print_quoted(print, o->items, o->len, true);
} else {
- print(env, "array('%c'", o->typecode);
+ mp_printf(print, "array('%c'", o->typecode);
if (o->len > 0) {
- print(env, ", [");
+ mp_print_str(print, ", [");
for (mp_uint_t i = 0; i < o->len; i++) {
if (i > 0) {
- print(env, ", ");
+ mp_print_str(print, ", ");
}
- mp_obj_print_helper(print, env, mp_binary_get_val_array(o->typecode, o->items, i), PRINT_REPR);
+ mp_obj_print_helper(print, mp_binary_get_val_array(o->typecode, o->items, i), PRINT_REPR);
}
- print(env, "]");
+ mp_print_str(print, "]");
}
}
- print(env, ")");
+ mp_print_str(print, ")");
}
#endif
diff --git a/py/objbool.c b/py/objbool.c
index d60dc8c0bd..478491bfc2 100644
--- a/py/objbool.c
+++ b/py/objbool.c
@@ -35,19 +35,19 @@ typedef struct _mp_obj_bool_t {
bool value;
} mp_obj_bool_t;
-STATIC void bool_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+STATIC void bool_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
mp_obj_bool_t *self = self_in;
if (MICROPY_PY_UJSON && kind == PRINT_JSON) {
if (self->value) {
- print(env, "true");
+ mp_print_str(print, "true");
} else {
- print(env, "false");
+ mp_print_str(print, "false");
}
} else {
if (self->value) {
- print(env, "True");
+ mp_print_str(print, "True");
} else {
- print(env, "False");
+ mp_print_str(print, "False");
}
}
}
diff --git a/py/objboundmeth.c b/py/objboundmeth.c
index 0f9ff08c81..b961592359 100644
--- a/py/objboundmeth.c
+++ b/py/objboundmeth.c
@@ -36,14 +36,14 @@ typedef struct _mp_obj_bound_meth_t {
} mp_obj_bound_meth_t;
#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED
-STATIC void bound_meth_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
+STATIC void bound_meth_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
(void)kind;
mp_obj_bound_meth_t *o = o_in;
- print(env, "<bound_method %p ", o);
- mp_obj_print_helper(print, env, o->self, PRINT_REPR);
- print(env, ".");
- mp_obj_print_helper(print, env, o->meth, PRINT_REPR);
- print(env, ">");
+ mp_printf(print, "<bound_method %p ", o);
+ mp_obj_print_helper(print, o->self, PRINT_REPR);
+ mp_print_str(print, ".");
+ mp_obj_print_helper(print, o->meth, PRINT_REPR);
+ mp_print_str(print, ">");
}
#endif
diff --git a/py/objcell.c b/py/objcell.c
index 9adbc16aea..97f1ecd63c 100644
--- a/py/objcell.c
+++ b/py/objcell.c
@@ -42,16 +42,16 @@ void mp_obj_cell_set(mp_obj_t self_in, mp_obj_t obj) {
}
#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED
-STATIC void cell_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
+STATIC void cell_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
(void)kind;
mp_obj_cell_t *o = o_in;
- print(env, "<cell %p ", o->obj);
+ mp_printf(print, "<cell %p ", o->obj);
if (o->obj == MP_OBJ_NULL) {
- print(env, "(nil)");
+ mp_print_str(print, "(nil)");
} else {
- mp_obj_print_helper(print, env, o->obj, PRINT_REPR);
+ mp_obj_print_helper(print, o->obj, PRINT_REPR);
}
- print(env, ">");
+ mp_print_str(print, ">");
}
#endif
diff --git a/py/objclosure.c b/py/objclosure.c
index 95c1adde0c..a4000e5ddb 100644
--- a/py/objclosure.c
+++ b/py/objclosure.c
@@ -60,21 +60,21 @@ STATIC mp_obj_t closure_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw,
}
#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED
-STATIC void closure_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
+STATIC void closure_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
(void)kind;
mp_obj_closure_t *o = o_in;
- print(env, "<closure ");
- mp_obj_print_helper(print, env, o->fun, PRINT_REPR);
- print(env, " at %p, n_closed=%u ", o, o->n_closed);
+ mp_print_str(print, "<closure ");
+ mp_obj_print_helper(print, o->fun, PRINT_REPR);
+ mp_printf(print, " at %p, n_closed=%u ", o, o->n_closed);
for (mp_uint_t i = 0; i < o->n_closed; i++) {
if (o->closed[i] == MP_OBJ_NULL) {
- print(env, "(nil)");
+ mp_print_str(print, "(nil)");
} else {
- mp_obj_print_helper(print, env, o->closed[i], PRINT_REPR);
+ mp_obj_print_helper(print, o->closed[i], PRINT_REPR);
}
- print(env, " ");
+ mp_print_str(print, " ");
}
- print(env, ">");
+ mp_print_str(print, ">");
}
#endif
diff --git a/py/objcomplex.c b/py/objcomplex.c
index f4a68851a5..12f10ec10b 100644
--- a/py/objcomplex.c
+++ b/py/objcomplex.c
@@ -48,36 +48,36 @@ typedef struct _mp_obj_complex_t {
mp_float_t imag;
} mp_obj_complex_t;
-STATIC void complex_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
+STATIC void complex_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
(void)kind;
mp_obj_complex_t *o = o_in;
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
char buf[16];
if (o->real == 0) {
mp_format_float(o->imag, buf, sizeof(buf), 'g', 7, '\0');
- print(env, "%sj", buf);
+ mp_printf(print, "%sj", buf);
} else {
mp_format_float(o->real, buf, sizeof(buf), 'g', 7, '\0');
- print(env, "(%s", buf);
+ mp_printf(print, "(%s", buf);
if (o->imag >= 0) {
- print(env, "+");
+ mp_print_str(print, "+");
}
mp_format_float(o->imag, buf, sizeof(buf), 'g', 7, '\0');
- print(env, "%sj)", buf);
+ mp_printf(print, "%sj)", buf);
}
#else
char buf[32];
if (o->real == 0) {
sprintf(buf, "%.16g", (double)o->imag);
- print(env, "%sj", buf);
+ mp_printf(print, "%sj", buf);
} else {
sprintf(buf, "%.16g", (double)o->real);
- print(env, "(%s", buf);
+ mp_printf(print, "(%s", buf);
if (o->imag >= 0) {
- print(env, "+");
+ mp_print_str(print, "+");
}
sprintf(buf, "%.16g", (double)o->imag);
- print(env, "%sj)", buf);
+ mp_printf(print, "%sj)", buf);
}
#endif
}
diff --git a/py/objdict.c b/py/objdict.c
index 3e255ec883..23024d5496 100644
--- a/py/objdict.c
+++ b/py/objdict.c
@@ -55,30 +55,30 @@ STATIC mp_map_elem_t *dict_iter_next(mp_obj_dict_t *dict, mp_uint_t *cur) {
return NULL;
}
-STATIC void dict_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+STATIC void dict_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
mp_obj_dict_t *self = MP_OBJ_CAST(self_in);
bool first = true;
if (!(MICROPY_PY_UJSON && kind == PRINT_JSON)) {
kind = PRINT_REPR;
}
if (MICROPY_PY_COLLECTIONS_ORDEREDDICT && self->base.type != &mp_type_dict) {
- print(env, "%s(", qstr_str(self->base.type->name));
+ mp_printf(print, "%s(", qstr_str(self->base.type->name));
}
- print(env, "{");
+ mp_print_str(print, "{");
mp_uint_t cur = 0;
mp_map_elem_t *next = NULL;
while ((next = dict_iter_next(self, &cur)) != NULL) {
if (!first) {
- print(env, ", ");
+ mp_print_str(print, ", ");
}
first = false;
- mp_obj_print_helper(print, env, next->key, kind);
- print(env, ": ");
- mp_obj_print_helper(print, env, next->value, kind);
+ mp_obj_print_helper(print, next->key, kind);
+ mp_print_str(print, ": ");
+ mp_obj_print_helper(print, next->value, kind);
}
- print(env, "}");
+ mp_print_str(print, "}");
if (MICROPY_PY_COLLECTIONS_ORDEREDDICT && self->base.type != &mp_type_dict) {
- print(env, ")");
+ mp_print_str(print, ")");
}
}
@@ -473,23 +473,23 @@ STATIC mp_obj_t dict_view_getiter(mp_obj_t view_in) {
return o_out;
}
-STATIC void dict_view_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+STATIC void dict_view_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
assert(MP_OBJ_IS_TYPE(self_in, &dict_view_type));
mp_obj_dict_view_t *self = MP_OBJ_CAST(self_in);
bool first = true;
- print(env, mp_dict_view_names[self->kind]);
- print(env, "([");
+ mp_print_str(print, mp_dict_view_names[self->kind]);
+ mp_print_str(print, "([");
mp_obj_t self_iter = dict_view_getiter(self_in);
mp_obj_t next = MP_OBJ_NULL;
while ((next = dict_view_it_iternext(self_iter)) != MP_OBJ_STOP_ITERATION) {
if (!first) {
- print(env, ", ");
+ mp_print_str(print, ", ");
}
first = false;
- mp_obj_print_helper(print, env, next, PRINT_REPR);
+ mp_obj_print_helper(print, next, PRINT_REPR);
}
- print(env, "])");
+ mp_print_str(print, "])");
}
STATIC mp_obj_t dict_view_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
diff --git a/py/objexcept.c b/py/objexcept.c
index 2d23f160a2..8a008d1fff 100644
--- a/py/objexcept.c
+++ b/py/objexcept.c
@@ -90,28 +90,28 @@ mp_obj_t mp_alloc_emergency_exception_buf(mp_obj_t size_in) {
// definition module-private so far, have it here.
const mp_obj_exception_t mp_const_GeneratorExit_obj = {{&mp_type_GeneratorExit}, 0, 0, MP_OBJ_NULL, mp_const_empty_tuple};
-STATIC void mp_obj_exception_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
+STATIC void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
mp_obj_exception_t *o = o_in;
mp_print_kind_t k = kind & ~PRINT_EXC_SUBCLASS;
bool is_subclass = kind & PRINT_EXC_SUBCLASS;
if (!is_subclass && (k == PRINT_REPR || k == PRINT_EXC)) {
- print(env, "%s", qstr_str(o->base.type->name));
+ mp_printf(print, "%s", qstr_str(o->base.type->name));
}
if (k == PRINT_EXC) {
- print(env, ": ");
+ mp_print_str(print, ": ");
}
if (k == PRINT_STR || k == PRINT_EXC) {
if (o->args == NULL || o->args->len == 0) {
- print(env, "");
+ mp_print_str(print, "");
return;
} else if (o->args->len == 1) {
- mp_obj_print_helper(print, env, o->args->items[0], PRINT_STR);
+ mp_obj_print_helper(print, o->args->items[0], PRINT_STR);
return;
}
}
- mp_obj_tuple_print(print, env, o->args, kind);
+ mp_obj_tuple_print(print, o->args, kind);
}
mp_obj_t mp_obj_exception_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
diff --git a/py/objfloat.c b/py/objfloat.c
index b94caf3c06..eb59cc5b78 100644
--- a/py/objfloat.c
+++ b/py/objfloat.c
@@ -42,24 +42,24 @@
#include "py/formatfloat.h"
#endif
-STATIC void float_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
+STATIC void float_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
(void)kind;
mp_obj_float_t *o = o_in;
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
char buf[16];
mp_format_float(o->value, buf, sizeof(buf), 'g', 7, '\0');
- print(env, "%s", buf);
+ mp_print_str(print, buf);
if (strchr(buf, '.') == NULL && strchr(buf, 'e') == NULL) {
// Python floats always have decimal point
- print(env, ".0");
+ mp_print_str(print, ".0");
}
#else
char buf[32];
sprintf(buf, "%.16g", (double) o->value);
- print(env, buf);
+ mp_print_str(print, buf);
if (strchr(buf, '.') == NULL && strchr(buf, 'e') == NULL) {
// Python floats always have decimal point
- print(env, ".0");
+ mp_print_str(print, ".0");
}
#endif
}
diff --git a/py/objfun.c b/py/objfun.c
index f00a90a089..8b9d3f553b 100644
--- a/py/objfun.c
+++ b/py/objfun.c
@@ -125,10 +125,10 @@ qstr mp_obj_fun_get_name(mp_const_obj_t fun_in) {
}
#if MICROPY_CPYTHON_COMPAT
-STATIC void fun_bc_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
+STATIC void fun_bc_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
(void)kind;
mp_obj_fun_bc_t *o = o_in;
- print(env, "<function %s at 0x%x>", qstr_str(mp_obj_fun_get_name(o)), o);
+ mp_printf(print, "<function %s at 0x%x>", qstr_str(mp_obj_fun_get_name(o)), o);
}
#endif
diff --git a/py/objgenerator.c b/py/objgenerator.c
index f672b8d99d..ed4e1fd151 100644
--- a/py/objgenerator.c
+++ b/py/objgenerator.c
@@ -95,10 +95,10 @@ mp_obj_t mp_obj_new_gen_wrap(mp_obj_t fun) {
/******************************************************************************/
/* generator instance */
-STATIC void gen_instance_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+STATIC void gen_instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
mp_obj_gen_instance_t *self = self_in;
- print(env, "<generator object '%s' at %p>", qstr_str(mp_obj_code_get_name(self->code_state.code_info)), self_in);
+ mp_printf(print, "<generator object '%s' at %p>", qstr_str(mp_obj_code_get_name(self->code_state.code_info)), self_in);
}
mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val) {
diff --git a/py/objint.c b/py/objint.c
index 26e1cc048f..64faed636f 100644
--- a/py/objint.c
+++ b/py/objint.c
@@ -124,7 +124,7 @@ mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val) {
#undef MP_FLOAT_EXP_SHIFT_I32
#endif
-void mp_obj_int_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+void mp_obj_int_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
// The size of this buffer is rather arbitrary. If it's not large
// enough, a dynamic one will be allocated.
@@ -134,7 +134,7 @@ void mp_obj_int_print(void (*print)(void *env, const char *fmt, ...), void *env,
mp_uint_t fmt_size;
char *str = mp_obj_int_formatted(&buf, &buf_size, &fmt_size, self_in, 10, NULL, '\0', '\0');
- print(env, "%s", str);
+ mp_print_str(print, str);
if (buf != stack_buf) {
m_del(char, buf, buf_size);
diff --git a/py/objint.h b/py/objint.h
index 63cd91a698..daeb3c499d 100644
--- a/py/objint.h
+++ b/py/objint.h
@@ -50,7 +50,7 @@ typedef enum {
mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val);
#endif // MICROPY_PY_BUILTINS_FLOAT
-void mp_obj_int_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind);
+void mp_obj_int_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind);
char *mp_obj_int_formatted(char **buf, mp_uint_t *buf_size, mp_uint_t *fmt_size, mp_const_obj_t self_in,
int base, const char *prefix, char base_char, char comma);
char *mp_obj_int_formatted_impl(char **buf, mp_uint_t *buf_size, mp_uint_t *fmt_size, mp_const_obj_t self_in,
diff --git a/py/objlist.c b/py/objlist.c
index e1343d9b32..9404032128 100644
--- a/py/objlist.c
+++ b/py/objlist.c
@@ -44,19 +44,19 @@ STATIC mp_obj_t list_pop(mp_uint_t n_args, const mp_obj_t *args);
/******************************************************************************/
/* list */
-STATIC void list_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
+STATIC void list_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
mp_obj_list_t *o = MP_OBJ_CAST(o_in);
if (!(MICROPY_PY_UJSON && kind == PRINT_JSON)) {
kind = PRINT_REPR;
}
- print(env, "[");
+ mp_print_str(print, "[");
for (mp_uint_t i = 0; i < o->len; i++) {
if (i > 0) {
- print(env, ", ");
+ mp_print_str(print, ", ");
}
- mp_obj_print_helper(print, env, o->items[i], kind);
+ mp_obj_print_helper(print, o->items[i], kind);
}
- print(env, "]");
+ mp_print_str(print, "]");
}
STATIC mp_obj_t list_extend_from_iter(mp_obj_t list, mp_obj_t iterable) {
diff --git a/py/objmodule.c b/py/objmodule.c
index 971c7f38c5..84d97f4948 100644
--- a/py/objmodule.c
+++ b/py/objmodule.c
@@ -33,7 +33,7 @@
#include "py/runtime.h"
#include "py/builtin.h"
-STATIC void module_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+STATIC void module_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
mp_obj_module_t *self = self_in;
const char *name = qstr_str(self->name);
@@ -43,12 +43,12 @@ STATIC void module_print(void (*print)(void *env, const char *fmt, ...), void *e
// symbol to give more information about the module.
mp_map_elem_t *elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(MP_QSTR___file__), MP_MAP_LOOKUP);
if (elem != NULL) {
- print(env, "<module '%s' from '%s'>", name, mp_obj_str_get_str(elem->value));
+ mp_printf(print, "<module '%s' from '%s'>", name, mp_obj_str_get_str(elem->value));
return;
}
#endif
- print(env, "<module '%s'>", name);
+ mp_printf(print, "<module '%s'>", name);
}
STATIC void module_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
diff --git a/py/objnamedtuple.c b/py/objnamedtuple.c
index 9cc6da1b7a..ef635a7a9c 100644
--- a/py/objnamedtuple.c
+++ b/py/objnamedtuple.c
@@ -53,19 +53,19 @@ STATIC mp_uint_t namedtuple_find_field(mp_obj_namedtuple_type_t *type, qstr name
return -1;
}
-STATIC void namedtuple_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
+STATIC void namedtuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
(void)kind;
mp_obj_namedtuple_t *o = o_in;
- print(env, "%s(", qstr_str(o->tuple.base.type->name));
+ mp_printf(print, "%s(", qstr_str(o->tuple.base.type->name));
const qstr *fields = ((mp_obj_namedtuple_type_t*)o->tuple.base.type)->fields;
for (mp_uint_t i = 0; i < o->tuple.len; i++) {
if (i > 0) {
- print(env, ", ");
+ mp_print_str(print, ", ");
}
- print(env, "%s=", qstr_str(fields[i]));
- mp_obj_print_helper(print, env, o->tuple.items[i], PRINT_REPR);
+ mp_printf(print, "%s=", qstr_str(fields[i]));
+ mp_obj_print_helper(print, o->tuple.items[i], PRINT_REPR);
}
- print(env, ")");
+ mp_print_str(print, ")");
}
STATIC void namedtuple_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
diff --git a/py/objnone.c b/py/objnone.c
index 523158d00e..d47452bb4d 100644
--- a/py/objnone.c
+++ b/py/objnone.c
@@ -34,12 +34,12 @@ typedef struct _mp_obj_none_t {
mp_obj_base_t base;
} mp_obj_none_t;
-STATIC void none_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+STATIC void none_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)self_in;
if (MICROPY_PY_UJSON && kind == PRINT_JSON) {
- print(env, "null");
+ mp_print_str(print, "null");
} else {
- print(env, "None");
+ mp_print_str(print, "None");
}
}
diff --git a/py/objrange.c b/py/objrange.c
index 9f7e6591e1..58d90a75e6 100644
--- a/py/objrange.c
+++ b/py/objrange.c
@@ -79,14 +79,14 @@ typedef struct _mp_obj_range_t {
mp_int_t step;
} mp_obj_range_t;
-STATIC void range_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+STATIC void range_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
mp_obj_range_t *self = self_in;
- print(env, "range(%d, %d", self->start, self->stop);
+ mp_printf(print, "range(%d, %d", self->start, self->stop);
if (self->step == 1) {
- print(env, ")");
+ mp_print_str(print, ")");
} else {
- print(env, ", %d)", self->step);
+ mp_printf(print, ", %d)", self->step);
}
}
diff --git a/py/objset.c b/py/objset.c
index c4e59280e1..6e303fe4bb 100644
--- a/py/objset.c
+++ b/py/objset.c
@@ -79,7 +79,7 @@ STATIC void check_set(mp_obj_t o) {
}
}
-STATIC void set_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+STATIC void set_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
mp_obj_set_t *self = self_in;
#if MICROPY_PY_BUILTINS_FROZENSET
@@ -88,37 +88,36 @@ STATIC void set_print(void (*print)(void *env, const char *fmt, ...), void *env,
if (self->set.used == 0) {
#if MICROPY_PY_BUILTINS_FROZENSET
if (is_frozen) {
- print(env, "frozen");
+ mp_print_str(print, "frozen");
}
#endif
- print(env, "set()");
+ mp_print_str(print, "set()");
return;
}
bool first = true;
#if MICROPY_PY_BUILTINS_FROZENSET
if (is_frozen) {
- print(env, "frozenset(");
+ mp_print_str(print, "frozenset(");
}
#endif
- print(env, "{");
+ mp_print_str(print, "{");
for (mp_uint_t i = 0; i < self->set.alloc; i++) {
if (MP_SET_SLOT_IS_FILLED(&self->set, i)) {
if (!first) {
- print(env, ", ");
+ mp_print_str(print, ", ");
}
first = false;
- mp_obj_print_helper(print, env, self->set.table[i], PRINT_REPR);
+ mp_obj_print_helper(print, self->set.table[i], PRINT_REPR);
}
}
- print(env, "}");
+ mp_print_str(print, "}");
#if MICROPY_PY_BUILTINS_FROZENSET
if (is_frozen) {
- print(env, ")");
+ mp_print_str(print, ")");
}
#endif
}
-
STATIC mp_obj_t set_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 1, false);
diff --git a/py/objslice.c b/py/objslice.c
index 4f3d054c68..7983864b2c 100644
--- a/py/objslice.c
+++ b/py/objslice.c
@@ -38,10 +38,10 @@ typedef struct _mp_obj_ellipsis_t {
mp_obj_base_t base;
} mp_obj_ellipsis_t;
-STATIC void ellipsis_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+STATIC void ellipsis_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)self_in;
(void)kind;
- print(env, "Ellipsis");
+ mp_print_str(print, "Ellipsis");
}
const mp_obj_type_t mp_type_ellipsis = {
@@ -66,16 +66,16 @@ typedef struct _mp_obj_slice_t {
mp_obj_t step;
} mp_obj_slice_t;
-STATIC void slice_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
+STATIC void slice_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
(void)kind;
mp_obj_slice_t *o = o_in;
- print(env, "slice(");
- mp_obj_print_helper(print, env, o->start, PRINT_REPR);
- print(env, ", ");
- mp_obj_print_helper(print, env, o->stop, PRINT_REPR);
- print(env, ", ");
- mp_obj_print_helper(print, env, o->step, PRINT_REPR);
- print(env, ")");
+ mp_print_str(print, "slice(");
+ mp_obj_print_helper(print, o->start, PRINT_REPR);
+ mp_print_str(print, ", ");
+ mp_obj_print_helper(print, o->stop, PRINT_REPR);
+ mp_print_str(print, ", ");
+ mp_obj_print_helper(print, o->step, PRINT_REPR);
+ mp_print_str(print, ")");
}
const mp_obj_type_t mp_type_slice = {
diff --git a/py/objstr.c b/py/objstr.c
index e35fc2976e..50fe10378b 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -34,7 +34,6 @@
#include "py/objlist.h"
#include "py/runtime0.h"
#include "py/runtime.h"
-#include "py/pfenv.h"
STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, mp_uint_t n_args, const mp_obj_t *args, mp_obj_t dict);
@@ -45,8 +44,7 @@ STATIC NORETURN void bad_implicit_conversion(mp_obj_t self_in);
/******************************************************************************/
/* str */
-void mp_str_print_quoted(void (*print)(void *env, const char *fmt, ...), void *env,
- const byte *str_data, mp_uint_t str_len, bool is_bytes) {
+void mp_str_print_quoted(const mp_print_t *print, const byte *str_data, mp_uint_t str_len, bool is_bytes) {
// this escapes characters, but it will be very slow to print (calling print many times)
bool has_single_quote = false;
bool has_double_quote = false;
@@ -61,72 +59,72 @@ void mp_str_print_quoted(void (*print)(void *env, const char *fmt, ...), void *e
if (has_single_quote && !has_double_quote) {
quote_char = '"';
}
- print(env, "%c", quote_char);
+ mp_printf(print, "%c", quote_char);
for (const byte *s = str_data, *top = str_data + str_len; s < top; s++) {
if (*s == quote_char) {
- print(env, "\\%c", quote_char);
+ mp_printf(print, "\\%c", quote_char);
} else if (*s == '\\') {
- print(env, "\\\\");
+ mp_print_str(print, "\\\\");
} else if (*s >= 0x20 && *s != 0x7f && (!is_bytes || *s < 0x80)) {
// In strings, anything which is not ascii control character
// is printed as is, this includes characters in range 0x80-0xff
// (which can be non-Latin letters, etc.)
- print(env, "%c", *s);
+ mp_printf(print, "%c", *s);
} else if (*s == '\n') {
- print(env, "\\n");
+ mp_print_str(print, "\\n");
} else if (*s == '\r') {
- print(env, "\\r");
+ mp_print_str(print, "\\r");
} else if (*s == '\t') {
- print(env, "\\t");
+ mp_print_str(print, "\\t");
} else {
- print(env, "\\x%02x", *s);
+ mp_printf(print, "\\x%02x", *s);
}
}
- print(env, "%c", quote_char);
+ mp_printf(print, "%c", quote_char);
}
#if MICROPY_PY_UJSON
-void mp_str_print_json(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, mp_uint_t str_len) {
+void mp_str_print_json(const mp_print_t *print, const byte *str_data, mp_uint_t str_len) {
// for JSON spec, see http://www.ietf.org/rfc/rfc4627.txt
// if we are given a valid utf8-encoded string, we will print it in a JSON-conforming way
- print(env, "\"");
+ mp_print_str(print, "\"");
for (const byte *s = str_data, *top = str_data + str_len; s < top; s++) {
if (*s == '"' || *s == '\\') {
- print(env, "\\%c", *s);
+ mp_printf(print, "\\%c", *s);
} else if (*s >= 32) {
// this will handle normal and utf-8 encoded chars
- print(env, "%c", *s);
+ mp_printf(print, "%c", *s);
} else if (*s == '\n') {
- print(env, "\\n");
+ mp_print_str(print, "\\n");
} else if (*s == '\r') {
- print(env, "\\r");
+ mp_print_str(print, "\\r");
} else if (*s == '\t') {
- print(env, "\\t");
+ mp_print_str(print, "\\t");
} else {
// this will handle control chars
- print(env, "\\u%04x", *s);
+ mp_printf(print, "\\u%04x", *s);
}
}
- print(env, "\"");
+ mp_print_str(print, "\"");
}
#endif
-STATIC void str_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+STATIC void str_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
GET_STR_DATA_LEN(self_in, str_data, str_len);
#if MICROPY_PY_UJSON
if (kind == PRINT_JSON) {
- mp_str_print_json(print, env, str_data, str_len);
+ mp_str_print_json(print, str_data, str_len);
return;
}
#endif
bool is_bytes = MP_OBJ_IS_TYPE(self_in, &mp_type_bytes);
if (kind == PRINT_STR && !is_bytes) {
- print(env, "%.*s", str_len, str_data);
+ mp_printf(print, "%.*s", str_len, str_data);
} else {
if (is_bytes) {
- print(env, "b");
+ mp_print_str(print, "b");
}
- mp_str_print_quoted(print, env, str_data, str_len, is_bytes);
+ mp_str_print_quoted(print, str_data, str_len, is_bytes);
}
}
@@ -145,8 +143,9 @@ mp_obj_t mp_obj_str_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw,
case 1: {
vstr_t vstr;
- vstr_init(&vstr, 16);
- mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf, &vstr, args[0], PRINT_STR);
+ mp_print_t print;
+ vstr_init_print(&vstr, 16, &print);
+ mp_obj_print_helper(&print, args[0], PRINT_STR);
return mp_obj_new_str_from_vstr(type_in, &vstr);
}
@@ -840,10 +839,8 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwa
GET_STR_DATA_LEN(args[0], str, len);
int arg_i = 0;
vstr_t vstr;
- vstr_init(&vstr, 16);
- pfenv_t pfenv_vstr;
- pfenv_vstr.data = &vstr;
- pfenv_vstr.print_strn = pfenv_vstr_add_strn;
+ mp_print_t print;
+ vstr_init_print(&vstr, 16, &print);
for (const byte *top = str + len; str < top; str++) {
if (*str == '}') {
@@ -998,8 +995,9 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwa
}
}
vstr_t arg_vstr;
- vstr_init(&arg_vstr, 16);
- mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf, &arg_vstr, arg, print_kind);
+ mp_print_t arg_print;
+ vstr_init_print(&arg_vstr, 16, &arg_print);
+ mp_obj_print_helper(&arg_print, arg, print_kind);
arg = mp_obj_new_str_from_vstr(&mp_type_str, &arg_vstr);
}
@@ -1108,20 +1106,20 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwa
if (arg_looks_integer(arg)) {
switch (type) {
case 'b':
- pfenv_print_mp_int(&pfenv_vstr, arg, 2, 'a', flags, fill, width, 0);
+ mp_print_mp_int(&print, arg, 2, 'a', flags, fill, width, 0);
continue;
case 'c':
{
char ch = mp_obj_get_int(arg);
- pfenv_print_strn(&pfenv_vstr, &ch, 1, flags, fill, width);
+ mp_print_strn(&print, &ch, 1, flags, fill, width);
continue;
}
case '\0': // No explicit format type implies 'd'
case 'n': // I don't think we support locales in uPy so use 'd'
case 'd':
- pfenv_print_mp_int(&pfenv_vstr, arg, 10, 'a', flags, fill, width, 0);
+ mp_print_mp_int(&print, arg, 10, 'a', flags, fill, width, 0);
continue;
case 'o':
@@ -1129,12 +1127,12 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwa
flags |= PF_FLAG_SHOW_OCTAL_LETTER;
}
- pfenv_print_mp_int(&pfenv_vstr, arg, 8, 'a', flags, fill, width, 0);
+ mp_print_mp_int(&print, arg, 8, 'a', flags, fill, width, 0);
continue;
case 'X':
case 'x':
- pfenv_print_mp_int(&pfenv_vstr, arg, 16, type - ('X' - 'A'), flags, fill, width, 0);
+ mp_print_mp_int(&print, arg, 16, type - ('X' - 'A'), flags, fill, width, 0);
continue;
case 'e':
@@ -1206,7 +1204,7 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwa
case 'F':
case 'g':
case 'G':
- pfenv_print_float(&pfenv_vstr, mp_obj_get_float(arg), type, flags, fill, width, precision);
+ mp_print_float(&print, mp_obj_get_float(arg), type, flags, fill, width, precision);
break;
case '%':
@@ -1216,7 +1214,7 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwa
#else
#define F100 100.0
#endif
- pfenv_print_float(&pfenv_vstr, mp_obj_get_float(arg) * F100, 'f', flags, fill, width, precision);
+ mp_print_float(&print, mp_obj_get_float(arg) * F100, 'f', flags, fill, width, precision);
#undef F100
break;
#endif
@@ -1244,7 +1242,7 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwa
switch (type) {
case '\0':
- mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf, &vstr, arg, PRINT_STR);
+ mp_obj_print_helper(&print, arg, PRINT_STR);
break;
case 's': {
@@ -1256,7 +1254,7 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwa
if (slen > (mp_uint_t)precision) {
slen = precision;
}
- pfenv_print_strn(&pfenv_vstr, s, slen, flags, fill, width);
+ mp_print_strn(&print, s, slen, flags, fill, width);
break;
}
@@ -1282,10 +1280,8 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, mp_uint_t n_args, const mp_o
const byte *start_str = str;
int arg_i = 0;
vstr_t vstr;
- vstr_init(&vstr, 16);
- pfenv_t pfenv_vstr;
- pfenv_vstr.data = &vstr;
- pfenv_vstr.print_strn = pfenv_vstr_add_strn;
+ mp_print_t print;
+ vstr_init_print(&vstr, 16, &print);
for (const byte *top = str + len; str < top; str++) {
mp_obj_t arg = MP_OBJ_NULL;
@@ -1389,10 +1385,10 @@ not_enough_args:
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
"%%c requires int or char"));
}
- pfenv_print_strn(&pfenv_vstr, s, 1, flags, ' ', width);
+ mp_print_strn(&print, s, 1, flags, ' ', width);
} else if (arg_looks_integer(arg)) {
char ch = mp_obj_get_int(arg);
- pfenv_print_strn(&pfenv_vstr, &ch, 1, flags, ' ', width);
+ mp_print_strn(&print, &ch, 1, flags, ' ', width);
} else {
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
"integer required"));
@@ -1402,7 +1398,7 @@ not_enough_args:
case 'd':
case 'i':
case 'u':
- pfenv_print_mp_int(&pfenv_vstr, arg_as_int(arg), 10, 'a', flags, fill, width, prec);
+ mp_print_mp_int(&print, arg_as_int(arg), 10, 'a', flags, fill, width, prec);
break;
#if MICROPY_PY_BUILTINS_FLOAT
@@ -1412,7 +1408,7 @@ not_enough_args:
case 'F':
case 'g':
case 'G':
- pfenv_print_float(&pfenv_vstr, mp_obj_get_float(arg), *str, flags, fill, width, prec);
+ mp_print_float(&print, mp_obj_get_float(arg), *str, flags, fill, width, prec);
break;
#endif
@@ -1420,16 +1416,16 @@ not_enough_args:
if (alt) {
flags |= (PF_FLAG_SHOW_PREFIX | PF_FLAG_SHOW_OCTAL_LETTER);
}
- pfenv_print_mp_int(&pfenv_vstr, arg, 8, 'a', flags, fill, width, prec);
+ mp_print_mp_int(&print, arg, 8, 'a', flags, fill, width, prec);
break;
case 'r':
case 's':
{
vstr_t arg_vstr;
- vstr_init(&arg_vstr, 16);
- mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf,
- &arg_vstr, arg, *str == 'r' ? PRINT_REPR : PRINT_STR);
+ mp_print_t arg_print;
+ vstr_init_print(&arg_vstr, 16, &arg_print);
+ mp_obj_print_helper(&arg_print, arg, *str == 'r' ? PRINT_REPR : PRINT_STR);
uint vlen = arg_vstr.len;
if (prec < 0) {
prec = vlen;
@@ -1437,14 +1433,14 @@ not_enough_args:
if (vlen > (uint)prec) {
vlen = prec;
}
- pfenv_print_strn(&pfenv_vstr, arg_vstr.buf, vlen, flags, ' ', width);
+ mp_print_strn(&print, arg_vstr.buf, vlen, flags, ' ', width);
vstr_clear(&arg_vstr);
break;
}
case 'X':
case 'x':
- pfenv_print_mp_int(&pfenv_vstr, arg, 16, *str - ('X' - 'A'), flags | alt, fill, width, prec);
+ mp_print_mp_int(&print, arg, 16, *str - ('X' - 'A'), flags | alt, fill, width, prec);
break;
default:
diff --git a/py/objstr.h b/py/objstr.h
index 291f49a096..9c00c914b3 100644
--- a/py/objstr.h
+++ b/py/objstr.h
@@ -55,7 +55,7 @@ typedef struct _mp_obj_str_t {
else { str_len = ((mp_obj_str_t*)str_obj_in)->len; str_data = ((mp_obj_str_t*)str_obj_in)->data; }
mp_obj_t mp_obj_str_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args);
-void mp_str_print_json(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, mp_uint_t str_len);
+void mp_str_print_json(const mp_print_t *print, const byte *str_data, mp_uint_t str_len);
mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwargs);
mp_obj_t mp_obj_str_split(mp_uint_t n_args, const mp_obj_t *args);
mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte* data, mp_uint_t len);
diff --git a/py/objstringio.c b/py/objstringio.c
index c7e8395b49..1823ed3981 100644
--- a/py/objstringio.c
+++ b/py/objstringio.c
@@ -52,10 +52,10 @@ STATIC void check_stringio_is_open(const mp_obj_stringio_t *o) {
#define check_stringio_is_open(o)
#endif
-STATIC void stringio_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+STATIC void stringio_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
mp_obj_stringio_t *self = self_in;
- print(env, self->base.type == &mp_type_stringio ? "<io.StringIO 0x%x>" : "<io.BytesIO 0x%x>", self);
+ mp_printf(print, self->base.type == &mp_type_stringio ? "<io.StringIO 0x%x>" : "<io.BytesIO 0x%x>", self);
}
STATIC mp_uint_t stringio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
diff --git a/py/objstrunicode.c b/py/objstrunicode.c
index 406eaad49f..63ca6a8bf8 100644
--- a/py/objstrunicode.c
+++ b/py/objstrunicode.c
@@ -33,7 +33,6 @@
#include "py/objlist.h"
#include "py/runtime0.h"
#include "py/runtime.h"
-#include "py/pfenv.h"
#if MICROPY_PY_BUILTINS_STR_UNICODE
@@ -42,7 +41,7 @@ STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str);
/******************************************************************************/
/* str */
-STATIC void uni_print_quoted(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, uint str_len) {
+STATIC void uni_print_quoted(const mp_print_t *print, const byte *str_data, uint str_len) {
// this escapes characters, but it will be very slow to print (calling print many times)
bool has_single_quote = false;
bool has_double_quote = false;
@@ -57,47 +56,47 @@ STATIC void uni_print_quoted(void (*print)(void *env, const char *fmt, ...), voi
if (has_single_quote && !has_double_quote) {
quote_char = '"';
}
- print(env, "%c", quote_char);
+ mp_printf(print, "%c", quote_char);
const byte *s = str_data, *top = str_data + str_len;
while (s < top) {
unichar ch;
ch = utf8_get_char(s);
s = utf8_next_char(s);
if (ch == quote_char) {
- print(env, "\\%c", quote_char);
+ mp_printf(print, "\\%c", quote_char);
} else if (ch == '\\') {
- print(env, "\\\\");
+ mp_print_str(print, "\\\\");
} else if (32 <= ch && ch <= 126) {
- print(env, "%c", ch);
+ mp_printf(print, "%c", ch);
} else if (ch == '\n') {
- print(env, "\\n");
+ mp_print_str(print, "\\n");
} else if (ch == '\r') {
- print(env, "\\r");
+ mp_print_str(print, "\\r");
} else if (ch == '\t') {
- print(env, "\\t");
+ mp_print_str(print, "\\t");
} else if (ch < 0x100) {
- print(env, "\\x%02x", ch);
+ mp_printf(print, "\\x%02x", ch);
} else if (ch < 0x10000) {
- print(env, "\\u%04x", ch);
+ mp_printf(print, "\\u%04x", ch);
} else {
- print(env, "\\U%08x", ch);
+ mp_printf(print, "\\U%08x", ch);
}
}
- print(env, "%c", quote_char);
+ mp_printf(print, "%c", quote_char);
}
-STATIC void uni_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+STATIC void uni_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
GET_STR_DATA_LEN(self_in, str_data, str_len);
#if MICROPY_PY_UJSON
if (kind == PRINT_JSON) {
- mp_str_print_json(print, env, str_data, str_len);
+ mp_str_print_json(print, str_data, str_len);
return;
}
#endif
if (kind == PRINT_STR) {
- print(env, "%.*s", str_len, str_data);
+ mp_printf(print, "%.*s", str_len, str_data);
} else {
- uni_print_quoted(print, env, str_data, str_len);
+ uni_print_quoted(print, str_data, str_len);
}
}
diff --git a/py/objtuple.c b/py/objtuple.c
index d575decfd4..3ba37d0278 100644
--- a/py/objtuple.c
+++ b/py/objtuple.c
@@ -37,27 +37,27 @@ STATIC mp_obj_t mp_obj_new_tuple_iterator(mp_obj_tuple_t *tuple, mp_uint_t cur);
/******************************************************************************/
/* tuple */
-void mp_obj_tuple_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
+void mp_obj_tuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
mp_obj_tuple_t *o = o_in;
if (MICROPY_PY_UJSON && kind == PRINT_JSON) {
- print(env, "[");
+ mp_print_str(print, "[");
} else {
- print(env, "(");
+ mp_print_str(print, "(");
kind = PRINT_REPR;
}
for (mp_uint_t i = 0; i < o->len; i++) {
if (i > 0) {
- print(env, ", ");
+ mp_print_str(print, ", ");
}
- mp_obj_print_helper(print, env, o->items[i], kind);
+ mp_obj_print_helper(print, o->items[i], kind);
}
if (MICROPY_PY_UJSON && kind == PRINT_JSON) {
- print(env, "]");
+ mp_print_str(print, "]");
} else {
if (o->len == 1) {
- print(env, ",");
+ mp_print_str(print, ",");
}
- print(env, ")");
+ mp_print_str(print, ")");
}
}
diff --git a/py/objtuple.h b/py/objtuple.h
index 4cac487557..5fb82ba529 100644
--- a/py/objtuple.h
+++ b/py/objtuple.h
@@ -34,7 +34,7 @@ typedef struct _mp_obj_tuple_t {
mp_obj_t items[];
} mp_obj_tuple_t;
-void mp_obj_tuple_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind);
+void mp_obj_tuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind);
mp_obj_t mp_obj_tuple_unary_op(mp_uint_t op, mp_obj_t self_in);
mp_obj_t mp_obj_tuple_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs);
mp_obj_t mp_obj_tuple_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value);
diff --git a/py/objtype.c b/py/objtype.c
index cb7110572d..5b6a011ed4 100644
--- a/py/objtype.c
+++ b/py/objtype.c
@@ -196,7 +196,7 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_
}
}
-STATIC void instance_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+STATIC void instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
mp_obj_instance_t *self = self_in;
qstr meth = (kind == PRINT_STR) ? MP_QSTR___str__ : MP_QSTR___repr__;
mp_obj_t member[2] = {MP_OBJ_NULL};
@@ -219,23 +219,23 @@ STATIC void instance_print(void (*print)(void *env, const char *fmt, ...), void
// Handle Exception subclasses specially
if (mp_obj_is_native_exception_instance(self->subobj[0])) {
if (kind != PRINT_STR) {
- print(env, "%s", qstr_str(self->base.type->name));
+ mp_print_str(print, qstr_str(self->base.type->name));
}
- mp_obj_print_helper(print, env, self->subobj[0], kind | PRINT_EXC_SUBCLASS);
+ mp_obj_print_helper(print, self->subobj[0], kind | PRINT_EXC_SUBCLASS);
} else {
- mp_obj_print_helper(print, env, self->subobj[0], kind);
+ mp_obj_print_helper(print, self->subobj[0], kind);
}
return;
}
if (member[0] != MP_OBJ_NULL) {
mp_obj_t r = mp_call_function_1(member[0], self_in);
- mp_obj_print_helper(print, env, r, PRINT_STR);
+ mp_obj_print_helper(print, r, PRINT_STR);
return;
}
// TODO: CPython prints fully-qualified type name
- print(env, "<%s object at %p>", mp_obj_get_type_str(self_in), self_in);
+ mp_printf(print, "<%s object at %p>", mp_obj_get_type_str(self_in), self_in);
}
mp_obj_t instance_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
@@ -737,10 +737,10 @@ STATIC mp_int_t instance_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo,
// - there is a constant mp_obj_type_t (called mp_type_type) for the 'type' object
// - creating a new class (a new type) creates a new mp_obj_type_t
-STATIC void type_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+STATIC void type_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
mp_obj_type_t *self = self_in;
- print(env, "<class '%s'>", qstr_str(self->name));
+ mp_printf(print, "<class '%s'>", qstr_str(self->name));
}
STATIC mp_obj_t type_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
@@ -911,14 +911,14 @@ typedef struct _mp_obj_super_t {
mp_obj_t obj;
} mp_obj_super_t;
-STATIC void super_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+STATIC void super_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
mp_obj_super_t *self = self_in;
- print(env, "<super: ");
- mp_obj_print_helper(print, env, self->type, PRINT_STR);
- print(env, ", ");
- mp_obj_print_helper(print, env, self->obj, PRINT_STR);
- print(env, ">");
+ mp_print_str(print, "<super: ");
+ mp_obj_print_helper(print, self->type, PRINT_STR);
+ mp_print_str(print, ", ");
+ mp_obj_print_helper(print, self->obj, PRINT_STR);
+ mp_print_str(print, ">");
}
STATIC mp_obj_t super_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
diff --git a/py/pfenv_printf.c b/py/pfenv_printf.c
deleted file mode 100644
index 599700edcf..0000000000
--- a/py/pfenv_printf.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * 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.
- */
-
-#include <assert.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdio.h>
-
-#include "py/pfenv.h"
-
-#if MICROPY_PY_BUILTINS_FLOAT
-#include "py/formatfloat.h"
-#endif
-
-int pfenv_vprintf(const pfenv_t *pfenv, const char *fmt, va_list args) {
- int chrs = 0;
- for (;;) {
- {
- const char *f = fmt;
- while (*f != '\0' && *f != '%') {
- ++f; // XXX UTF8 advance char
- }
- if (f > fmt) {
- pfenv->print_strn(pfenv->data, fmt, f - fmt);
- chrs += f - fmt;
- fmt = f;
- }
- }
-
- if (*fmt == '\0') {
- break;
- }
-
- // move past % character
- ++fmt;
-
- // parse flags, if they exist
- int flags = 0;
- char fill = ' ';
- while (*fmt != '\0') {
- if (*fmt == '-') flags |= PF_FLAG_LEFT_ADJUST;
- else if (*fmt == '+') flags |= PF_FLAG_SHOW_SIGN;
- else if (*fmt == ' ') flags |= PF_FLAG_SPACE_SIGN;
- else if (*fmt == '!') flags |= PF_FLAG_NO_TRAILZ;
- else if (*fmt == '0') {
- flags |= PF_FLAG_PAD_AFTER_SIGN;
- fill = '0';
- } else break;
- ++fmt;
- }
-
- // parse width, if it exists
- int width = 0;
- for (; '0' <= *fmt && *fmt <= '9'; ++fmt) {
- width = width * 10 + *fmt - '0';
- }
-
- // parse precision, if it exists
- int prec = -1;
- if (*fmt == '.') {
- ++fmt;
- if (*fmt == '*') {
- ++fmt;
- prec = va_arg(args, int);
- } else {
- prec = 0;
- for (; '0' <= *fmt && *fmt <= '9'; ++fmt) {
- prec = prec * 10 + *fmt - '0';
- }
- }
- if (prec < 0) {
- prec = 0;
- }
- }
-
- // parse long specifiers (current not used)
- //bool long_arg = false;
- if (*fmt == 'l') {
- ++fmt;
- //long_arg = true;
- }
-
- if (*fmt == '\0') {
- break;
- }
-
- switch (*fmt) {
- case 'b':
- if (va_arg(args, int)) {
- chrs += pfenv_print_strn(pfenv, "true", 4, flags, fill, width);
- } else {
- chrs += pfenv_print_strn(pfenv, "false", 5, flags, fill, width);
- }
- break;
- case 'c':
- {
- char str = va_arg(args, int);
- chrs += pfenv_print_strn(pfenv, &str, 1, flags, fill, width);
- break;
- }
- case 's':
- {
- const char *str = va_arg(args, const char*);
- if (str) {
- if (prec < 0) {
- prec = strlen(str);
- }
- chrs += pfenv_print_strn(pfenv, str, prec, flags, fill, width);
- } else {
- chrs += pfenv_print_strn(pfenv, "(null)", 6, flags, fill, width);
- }
- break;
- }
- case 'u':
- chrs += pfenv_print_int(pfenv, va_arg(args, int), 0, 10, 'a', flags, fill, width);
- break;
- case 'd':
- chrs += pfenv_print_int(pfenv, va_arg(args, int), 1, 10, 'a', flags, fill, width);
- break;
- case 'x':
- chrs += pfenv_print_int(pfenv, va_arg(args, int), 0, 16, 'a', flags, fill, width);
- break;
- case 'X':
- chrs += pfenv_print_int(pfenv, va_arg(args, int), 0, 16, 'A', flags, fill, width);
- break;
- case 'p':
- case 'P': // don't bother to handle upcase for 'P'
- chrs += pfenv_print_int(pfenv, va_arg(args, unsigned int), 0, 16, 'a', flags, fill, width);
- break;
-#if MICROPY_PY_BUILTINS_FLOAT
- case 'e':
- case 'E':
- case 'f':
- case 'F':
- case 'g':
- case 'G':
- {
-#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
- mp_float_t f = va_arg(args, double);
- chrs += pfenv_print_float(pfenv, f, *fmt, flags, fill, width, prec);
-#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
- // Currently pfenv_print_float uses snprintf, but snprintf
- // itself may be implemented in terms of pfenv_vprintf() for
- // some ports. So, for extra caution, this case is handled
- // with assert below. Note that currently ports which
- // use MICROPY_FLOAT_IMPL_DOUBLE, don't call pfenv_vprintf()
- // with float format specifier at all.
- // TODO: resolve this completely
- assert(0);
-//#error Calling pfenv_print_float with double not supported from within printf
-#else
-#error Unknown MICROPY FLOAT IMPL
-#endif
- break;
- }
-#endif
- default:
- pfenv->print_strn(pfenv->data, fmt, 1);
- chrs += 1;
- break;
- }
- ++fmt;
- }
- return chrs;
-}
-
-int pfenv_printf(const pfenv_t *pfenv, const char *fmt, ...) {
- va_list ap;
- va_start(ap, fmt);
- int ret = pfenv_vprintf(pfenv, fmt, ap);
- va_end(ap);
- return ret;
-}
-
-void printf_wrapper(void *env, const char *fmt, ...) {
- (void)env;
- va_list args;
- va_start(args, fmt);
- vprintf(fmt, args);
- va_end(args);
-}
diff --git a/py/py.mk b/py/py.mk
index e120f8be4a..98c6041156 100644
--- a/py/py.mk
+++ b/py/py.mk
@@ -22,6 +22,7 @@ PY_O_BASENAME = \
gc.o \
qstr.o \
vstr.o \
+ mpprint.o \
unicode.o \
mpz.o \
lexer.o \
@@ -108,8 +109,6 @@ PY_O_BASENAME = \
showbc.o \
repl.o \
smallint.o \
- pfenv.o \
- pfenv_printf.o \
frozenmod.o \
../extmod/moductypes.o \
../extmod/modujson.o \
diff --git a/py/runtime.h b/py/runtime.h
index f05a7d0a89..d171f1582c 100644
--- a/py/runtime.h
+++ b/py/runtime.h
@@ -63,6 +63,9 @@ extern const qstr mp_binary_op_method_name[];
void mp_init(void);
void mp_deinit(void);
+// extra printing method specifically for mp_obj_t's which are integral type
+int mp_print_mp_int(const mp_print_t *print, mp_obj_t x, int base, int base_char, int flags, char fill, int width, int prec);
+
void mp_arg_check_num(mp_uint_t n_args, mp_uint_t n_kw, mp_uint_t n_args_min, mp_uint_t n_args_max, bool takes_kw);
void mp_arg_parse_all(mp_uint_t n_pos, const mp_obj_t *pos, mp_map_t *kws, mp_uint_t n_allowed, const mp_arg_t *allowed, mp_arg_val_t *out_vals);
void mp_arg_parse_all_kw_array(mp_uint_t n_pos, mp_uint_t n_kw, const mp_obj_t *args, mp_uint_t n_allowed, const mp_arg_t *allowed, mp_arg_val_t *out_vals);
diff --git a/py/vstr.c b/py/vstr.c
index 953e8edb51..45915e7c42 100644
--- a/py/vstr.c
+++ b/py/vstr.c
@@ -31,6 +31,7 @@
#include "py/mpconfig.h"
#include "py/misc.h"
+#include "py/mpprint.h"
// returned value is always at least 1 greater than argument
#define ROUND_ALLOC(a) (((a) & ((~0) - 7)) + 8)
@@ -65,6 +66,12 @@ void vstr_init_fixed_buf(vstr_t *vstr, size_t alloc, char *buf) {
vstr->fixed_buf = true;
}
+void vstr_init_print(vstr_t *vstr, size_t alloc, mp_print_t *print) {
+ vstr_init(vstr, alloc);
+ print->data = vstr;
+ print->print_strn = (mp_print_strn_t)vstr_add_strn;
+}
+
void vstr_clear(vstr_t *vstr) {
if (!vstr->fixed_buf) {
m_del(char, vstr->buf, vstr->alloc);
@@ -322,32 +329,6 @@ void vstr_vprintf(vstr_t *vstr, const char *fmt, va_list ap) {
return;
}
- while (1) {
- // try to print in the allocated space
- // need to make a copy of the va_list because we may call vsnprintf multiple times
- size_t size = vstr->alloc - vstr->len;
- va_list ap2;
- va_copy(ap2, ap);
- int n = vsnprintf(vstr->buf + vstr->len, size, fmt, ap2);
- va_end(ap2);
-
- // if that worked, return
- if (n > -1 && (size_t)n < size) {
- vstr->len += n;
- return;
- }
-
- // else try again with more space
- if (n > -1) { // glibc 2.1
- // n + 1 is precisely what is needed
- if (!vstr_ensure_extra(vstr, n + 1)) {
- return;
- }
- } else { // glibc 2.0
- // increase to twice the old size
- if (!vstr_ensure_extra(vstr, size * 2)) {
- return;
- }
- }
- }
+ mp_print_t print = {vstr, (mp_print_strn_t)vstr_add_strn};
+ mp_vprintf(&print, fmt, ap);
}