From c2da90bfd809739d34926b5b6ecd145924e58ab1 Mon Sep 17 00:00:00 2001
From: monad <foobar@example.com>
Date: Sat, 24 Aug 2019 16:56:55 +0200
Subject: [PATCH] made text non-destructive

---
 py/builtin.h     |  1 +
 py/modbuiltins.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 53 insertions(+)

diff --git a/py/builtin.h b/py/builtin.h
index a5e0f5f2d..ae7ec2bf7 100644
--- a/py/builtin.h
+++ b/py/builtin.h
@@ -72,6 +72,7 @@ MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_oct_obj);
 MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_ord_obj);
 MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_pow_obj);
 MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_print_obj);
+MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_print_no_bg_obj);
 MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_repr_obj);
 MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_round_obj);
 MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_sorted_obj);
diff --git a/py/modbuiltins.c b/py/modbuiltins.c
index a65f3beec..4057950f0 100644
--- a/py/modbuiltins.c
+++ b/py/modbuiltins.c
@@ -446,6 +446,57 @@ STATIC mp_obj_t mp_builtin_print(size_t n_args, const mp_obj_t *pos_args, mp_map
 }
 MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_print_obj, 0, mp_builtin_print);
 
+STATIC mp_obj_t mp_builtin_print_no_bg(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+    enum { ARG_sep, ARG_end, ARG_file };
+    static const mp_arg_t allowed_args[] = {
+        { MP_QSTR_sep, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_QSTR(MP_QSTR__space_)} },
+        { MP_QSTR_end, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_QSTR(MP_QSTR__0x0a_)} },
+        #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES
+        { MP_QSTR_file, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_sys_stdout_obj)} },
+        #endif
+    };
+
+    // parse args (a union is used to reduce the amount of C stack that is needed)
+    union {
+        mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+        size_t len[2];
+    } u;
+    mp_arg_parse_all(0, NULL, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, u.args);
+
+    #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES
+    mp_get_stream_raise(u.args[ARG_file].u_obj, MP_STREAM_OP_WRITE);
+    mp_print_t print = {MP_OBJ_TO_PTR(u.args[ARG_file].u_obj), mp_stream_write_adaptor};
+    #endif
+
+    // extract the objects first because we are going to use the other part of the union
+    mp_obj_t sep = u.args[ARG_sep].u_obj;
+    mp_obj_t end = u.args[ARG_end].u_obj;
+    const char *sep_data = mp_obj_str_get_data(sep, &u.len[0]);
+    const char *end_data = mp_obj_str_get_data(end, &u.len[1]);
+
+    for (size_t i = 0; i < n_args; i++) {
+        if (i > 0) {
+            #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES
+            mp_stream_write_adaptor(print.data, sep_data, u.len[0]);
+            #else
+            mp_print_strn(&mp_plat_print, sep_data, u.len[0], 0, 0, 0);
+            #endif
+        }
+        #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES
+        mp_obj_print_helper(&print, pos_args[i], PRINT_STR);
+        #else
+        mp_obj_print_helper(&mp_plat_print, pos_args[i], PRINT_STR);
+        #endif
+    }
+    #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES
+    mp_stream_write_adaptor(print.data, end_data, u.len[1]);
+    #else
+    mp_print_strn(&mp_plat_print, end_data, u.len[1], 0, 0, 0);
+    #endif
+    return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_print_no_bg_obj, 0, mp_builtin_print_no_bg);
+
 STATIC mp_obj_t mp_builtin___repl_print__(mp_obj_t o) {
     if (o != mp_const_none) {
         mp_obj_print_helper(MP_PYTHON_PRINTER, o, PRINT_REPR);
@@ -722,6 +773,7 @@ STATIC const mp_rom_map_elem_t mp_module_builtins_globals_table[] = {
     { MP_ROM_QSTR(MP_QSTR_ord), MP_ROM_PTR(&mp_builtin_ord_obj) },
     { MP_ROM_QSTR(MP_QSTR_pow), MP_ROM_PTR(&mp_builtin_pow_obj) },
     { MP_ROM_QSTR(MP_QSTR_print), MP_ROM_PTR(&mp_builtin_print_obj) },
+    { MP_ROM_QSTR(MP_QSTR_print_no_bg), MP_ROM_PTR(&mp_builtin_print_no_bg_obj) },
     { MP_ROM_QSTR(MP_QSTR_repr), MP_ROM_PTR(&mp_builtin_repr_obj) },
     { MP_ROM_QSTR(MP_QSTR_round), MP_ROM_PTR(&mp_builtin_round_obj) },
     { MP_ROM_QSTR(MP_QSTR_sorted), MP_ROM_PTR(&mp_builtin_sorted_obj) },
-- 
GitLab