Skip to content

Commit 721d624

Browse files
committed
2 parents ef20473 + 4038f51 commit 721d624

64 files changed

Lines changed: 9122 additions & 279 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

py/builtin.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
#include "runtime0.h"
3737
#include "runtime.h"
3838
#include "builtin.h"
39+
#include "stream.h"
40+
#include "pfenv.h"
3941

4042
#if MICROPY_PY_BUILTINS_FLOAT
4143
#include <math.h>
@@ -424,13 +426,36 @@ STATIC mp_obj_t mp_builtin_print(uint n_args, const mp_obj_t *args, mp_map_t *kw
424426
if (end_elem != NULL && end_elem->value != mp_const_none) {
425427
end_data = mp_obj_str_get_data(end_elem->value, &end_len);
426428
}
429+
#if MICROPY_PY_IO
430+
mp_obj_t stream_obj = &mp_sys_stdout_obj;
431+
mp_map_elem_t *file_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_file), MP_MAP_LOOKUP);
432+
if (file_elem != NULL && file_elem->value != mp_const_none) {
433+
stream_obj = file_elem->value;
434+
}
435+
436+
pfenv_t pfenv;
437+
pfenv.data = stream_obj;
438+
pfenv.print_strn = (void (*)(void *, const char *, unsigned int))mp_stream_write;
439+
#endif
427440
for (int i = 0; i < n_args; i++) {
428441
if (i > 0) {
442+
#if MICROPY_PY_IO
443+
mp_stream_write(stream_obj, sep_data, sep_len);
444+
#else
429445
printf("%.*s", sep_len, sep_data);
446+
#endif
430447
}
448+
#if MICROPY_PY_IO
449+
mp_obj_print_helper((void (*)(void *env, const char *fmt, ...))pfenv_printf, &pfenv, args[i], PRINT_STR);
450+
#else
431451
mp_obj_print(args[i], PRINT_STR);
452+
#endif
432453
}
454+
#if MICROPY_PY_IO
455+
mp_stream_write(stream_obj, end_data, end_len);
456+
#else
433457
printf("%.*s", end_len, end_data);
458+
#endif
434459
return mp_const_none;
435460
}
436461

py/builtin.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,5 +81,10 @@ extern const mp_obj_module_t mp_module_struct;
8181
extern const mp_obj_module_t mp_module_sys;
8282
extern const mp_obj_module_t mp_module_gc;
8383

84+
struct _dummy_t;
85+
extern struct _dummy_t mp_sys_stdin_obj;
86+
extern struct _dummy_t mp_sys_stdout_obj;
87+
extern struct _dummy_t mp_sys_stderr_obj;
88+
8489
// extmod modules
8590
extern const mp_obj_module_t mp_module_uctypes;

py/emitinlinethumb.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -315,15 +315,14 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, int n_args, m
315315
uint reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
316316
uint reg_src = get_arg_reg(emit, op_str, pn_args[1], 15);
317317
asm_thumb_mov_reg_reg(emit->as, reg_dest, reg_src);
318-
} else if (strcmp(op_str, "and") == 0) {
318+
} else if (strcmp(op_str, "and_") == 0) {
319319
op_code = ASM_THUMB_FORMAT_4_AND;
320320
uint reg_dest, reg_src;
321321
op_format_4:
322322
reg_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
323323
reg_src = get_arg_reg(emit, op_str, pn_args[1], 7);
324324
asm_thumb_format_4(emit->as, op_code, reg_dest, reg_src);
325325
// TODO probably uses less ROM if these ops are in a lookup table
326-
} else if (strcmp(op_str, "and") == 0) { op_code = ASM_THUMB_FORMAT_4_AND; goto op_format_4;
327326
} else if (strcmp(op_str, "eor") == 0) { op_code = ASM_THUMB_FORMAT_4_EOR; goto op_format_4;
328327
} else if (strcmp(op_str, "lsl") == 0) { op_code = ASM_THUMB_FORMAT_4_LSL; goto op_format_4;
329328
} else if (strcmp(op_str, "lsr") == 0) { op_code = ASM_THUMB_FORMAT_4_LSR; goto op_format_4;

py/formatfloat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ int format_float(float f, char *buf, size_t buf_size, char fmt, int prec, char s
7575

7676
if (buf_size < 7) {
7777
// Smallest exp notion is -9e+99 which is 6 chars plus terminating
78-
// nulll.
78+
// null.
7979

8080
if (buf_size >= 2) {
8181
*s++ = '?';

py/modsys.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,6 @@
4444
// only addresses.
4545
struct _dummy_t;
4646
extern struct _dummy_t mp_sys_exit_obj;
47-
extern struct _dummy_t mp_sys_stdin_obj;
48-
extern struct _dummy_t mp_sys_stdout_obj;
49-
extern struct _dummy_t mp_sys_stderr_obj;
5047

5148
extern mp_obj_int_t mp_maxsize_obj;
5249

py/objarray.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ STATIC mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg);
5959
STATIC void array_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
6060
mp_obj_array_t *o = o_in;
6161
if (o->typecode == BYTEARRAY_TYPECODE) {
62-
print(env, "bytearray(b", o->typecode);
62+
print(env, "bytearray(b");
6363
mp_str_print_quoted(print, env, o->items, o->len, true);
6464
} else {
6565
print(env, "array('%c'", o->typecode);

py/pfenv.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,6 @@ int pfenv_print_mp_int(const pfenv_t *pfenv, mp_obj_t x, int sgn, int base, int
4949
#if MICROPY_PY_BUILTINS_FLOAT
5050
int pfenv_print_float(const pfenv_t *pfenv, mp_float_t f, char fmt, int flags, char fill, int width, int prec);
5151
#endif
52+
53+
//int pfenv_vprintf(const pfenv_t *pfenv, const char *fmt, va_list args);
54+
int pfenv_printf(const pfenv_t *pfenv, const char *fmt, ...);

py/pfenv_printf.c

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
/*
2+
* This file is part of the Micro Python project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2013, 2014 Damien P. George
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include <assert.h>
28+
#include <stdio.h>
29+
#include <stdint.h>
30+
#include <string.h>
31+
#include <stdarg.h>
32+
33+
#include "mpconfig.h"
34+
#include "misc.h"
35+
#include "qstr.h"
36+
#include "obj.h"
37+
#include "pfenv.h"
38+
39+
#if MICROPY_PY_BUILTINS_FLOAT
40+
#include "formatfloat.h"
41+
#endif
42+
43+
int pfenv_vprintf(const pfenv_t *pfenv, const char *fmt, va_list args) {
44+
int chrs = 0;
45+
for (;;) {
46+
{
47+
const char *f = fmt;
48+
while (*f != '\0' && *f != '%') {
49+
++f; // XXX UTF8 advance char
50+
}
51+
if (f > fmt) {
52+
pfenv->print_strn(pfenv->data, fmt, f - fmt);
53+
chrs += f - fmt;
54+
fmt = f;
55+
}
56+
}
57+
58+
if (*fmt == '\0') {
59+
break;
60+
}
61+
62+
// move past % character
63+
++fmt;
64+
65+
// parse flags, if they exist
66+
int flags = 0;
67+
char fill = ' ';
68+
while (*fmt != '\0') {
69+
if (*fmt == '-') flags |= PF_FLAG_LEFT_ADJUST;
70+
else if (*fmt == '+') flags |= PF_FLAG_SHOW_SIGN;
71+
else if (*fmt == ' ') flags |= PF_FLAG_SPACE_SIGN;
72+
else if (*fmt == '!') flags |= PF_FLAG_NO_TRAILZ;
73+
else if (*fmt == '0') {
74+
flags |= PF_FLAG_PAD_AFTER_SIGN;
75+
fill = '0';
76+
} else break;
77+
++fmt;
78+
}
79+
80+
// parse width, if it exists
81+
int width = 0;
82+
for (; '0' <= *fmt && *fmt <= '9'; ++fmt) {
83+
width = width * 10 + *fmt - '0';
84+
}
85+
86+
// parse precision, if it exists
87+
int prec = -1;
88+
if (*fmt == '.') {
89+
++fmt;
90+
if (*fmt == '*') {
91+
++fmt;
92+
prec = va_arg(args, int);
93+
} else {
94+
prec = 0;
95+
for (; '0' <= *fmt && *fmt <= '9'; ++fmt) {
96+
prec = prec * 10 + *fmt - '0';
97+
}
98+
}
99+
if (prec < 0) {
100+
prec = 0;
101+
}
102+
}
103+
104+
// parse long specifiers (current not used)
105+
//bool long_arg = false;
106+
if (*fmt == 'l') {
107+
++fmt;
108+
//long_arg = true;
109+
}
110+
111+
if (*fmt == '\0') {
112+
break;
113+
}
114+
115+
switch (*fmt) {
116+
case 'b':
117+
if (va_arg(args, int)) {
118+
chrs += pfenv_print_strn(pfenv, "true", 4, flags, fill, width);
119+
} else {
120+
chrs += pfenv_print_strn(pfenv, "false", 5, flags, fill, width);
121+
}
122+
break;
123+
case 'c':
124+
{
125+
char str = va_arg(args, int);
126+
chrs += pfenv_print_strn(pfenv, &str, 1, flags, fill, width);
127+
break;
128+
}
129+
case 's':
130+
{
131+
const char *str = va_arg(args, const char*);
132+
if (str) {
133+
if (prec < 0) {
134+
prec = strlen(str);
135+
}
136+
chrs += pfenv_print_strn(pfenv, str, prec, flags, fill, width);
137+
} else {
138+
chrs += pfenv_print_strn(pfenv, "(null)", 6, flags, fill, width);
139+
}
140+
break;
141+
}
142+
case 'u':
143+
chrs += pfenv_print_int(pfenv, va_arg(args, int), 0, 10, 'a', flags, fill, width);
144+
break;
145+
case 'd':
146+
chrs += pfenv_print_int(pfenv, va_arg(args, int), 1, 10, 'a', flags, fill, width);
147+
break;
148+
case 'x':
149+
case 'p': // ?
150+
chrs += pfenv_print_int(pfenv, va_arg(args, int), 0, 16, 'a', flags, fill, width);
151+
break;
152+
case 'X':
153+
case 'P': // ?
154+
chrs += pfenv_print_int(pfenv, va_arg(args, int), 0, 16, 'A', flags, fill, width);
155+
break;
156+
#if MICROPY_PY_BUILTINS_FLOAT
157+
case 'e':
158+
case 'E':
159+
case 'f':
160+
case 'F':
161+
case 'g':
162+
case 'G':
163+
{
164+
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
165+
mp_float_t f = va_arg(args, double);
166+
chrs += pfenv_print_float(pfenv, f, *fmt, flags, fill, width, prec);
167+
#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
168+
// Currently pfenv_print_float uses snprintf, but snprintf
169+
// itself may be implemented in terms of pfenv_vprintf() for
170+
// some ports. So, for extra caution, this case is handled
171+
// with assert below. Note that currently ports which
172+
// use MICROPY_FLOAT_IMPL_DOUBLE, don't call pfenv_vprintf()
173+
// with float format specifier at all.
174+
// TODO: resolve this completely
175+
assert(0);
176+
//#error Calling pfenv_print_float with double not supported from within printf
177+
#else
178+
#error Unknown MICROPY FLOAT IMPL
179+
#endif
180+
break;
181+
}
182+
#endif
183+
default:
184+
pfenv->print_strn(pfenv->data, fmt, 1);
185+
chrs += 1;
186+
break;
187+
}
188+
++fmt;
189+
}
190+
return chrs;
191+
}
192+
193+
int pfenv_printf(const pfenv_t *pfenv, const char *fmt, ...) {
194+
va_list ap;
195+
va_start(ap, fmt);
196+
int ret = pfenv_vprintf(pfenv, fmt, ap);
197+
va_end(ap);
198+
return ret;
199+
}

py/py.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ PY_O_BASENAME = \
102102
repl.o \
103103
smallint.o \
104104
pfenv.o \
105+
pfenv_printf.o \
105106
../extmod/moductypes.o
106107

107108
# prepend the build destination prefix to the py object files

py/qstrdefs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,7 @@ Q(TextIOWrapper)
413413
Q(StringIO)
414414
Q(BytesIO)
415415
Q(getvalue)
416+
Q(file)
416417
#endif
417418

418419
#if MICROPY_PY_GC

0 commit comments

Comments
 (0)