blob: db611f3d9708103cde8ef9043057e18dd33260e8 [file] [log] [blame]
Damien George04b91472014-05-03 23:27:38 +01001/*
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
Dave Hylandsf14b92b2014-03-12 18:06:26 -070027#include <stdint.h>
28#include <string.h>
29#include <stdarg.h>
30
Paul Sokolovsky81394942014-06-28 23:32:03 +030031#include "mpconfig.h"
Dave Hylandsf14b92b2014-03-12 18:06:26 -070032#include "std.h"
33#include "misc.h"
34#include "systick.h"
Dave Hylandsf14b92b2014-03-12 18:06:26 -070035#include "qstr.h"
36#include "obj.h"
Dave Hylandsbaf6f142014-03-30 21:06:50 -070037#include "pfenv.h"
Dave Hylandsf14b92b2014-03-12 18:06:26 -070038#if 0
39#include "lcd.h"
40#endif
Damien George75337002014-04-21 12:03:09 +010041#include "uart.h"
Dave Hylandsf14b92b2014-03-12 18:06:26 -070042#include "usb.h"
Damien George951ed9d2014-07-20 13:57:43 +010043#include "pybstdio.h"
Dave Hylandsf14b92b2014-03-12 18:06:26 -070044
Damien Georgefb510b32014-06-01 13:32:54 +010045#if MICROPY_PY_BUILTINS_FLOAT
Dave Hylandsf14b92b2014-03-12 18:06:26 -070046#include "formatfloat.h"
47#endif
48
Paul Sokolovskycb66f412014-07-13 23:07:42 +030049int pfenv_vprintf(const pfenv_t *pfenv, const char *fmt, va_list args);
50
Damien George951ed9d2014-07-20 13:57:43 +010051STATIC void stdout_print_strn(void *dummy_env, const char *str, unsigned int len) {
52 stdout_tx_strn_cooked(str, len);
Dave Hylandsf14b92b2014-03-12 18:06:26 -070053}
54
Damien George951ed9d2014-07-20 13:57:43 +010055STATIC const pfenv_t pfenv_stdout = {0, stdout_print_strn};
Dave Hylandsf14b92b2014-03-12 18:06:26 -070056
57int printf(const char *fmt, ...) {
58 va_list ap;
59 va_start(ap, fmt);
Paul Sokolovskycb66f412014-07-13 23:07:42 +030060 int ret = pfenv_vprintf(&pfenv_stdout, fmt, ap);
Dave Hylandsf14b92b2014-03-12 18:06:26 -070061 va_end(ap);
62 return ret;
63}
64
65int vprintf(const char *fmt, va_list ap) {
Paul Sokolovskycb66f412014-07-13 23:07:42 +030066 return pfenv_vprintf(&pfenv_stdout, fmt, ap);
Dave Hylandsf14b92b2014-03-12 18:06:26 -070067}
68
69#if MICROPY_DEBUG_PRINTERS
70int DEBUG_printf(const char *fmt, ...) {
71 (void)stream;
72 va_list ap;
73 va_start(ap, fmt);
Damien George1163cb92014-07-20 13:10:18 +010074 int ret = pfenv_vprintf(&pfenv_stdout, fmt, ap);
Dave Hylandsf14b92b2014-03-12 18:06:26 -070075 va_end(ap);
76 return ret;
77}
78#endif
79
80// need this because gcc optimises printf("%c", c) -> putchar(c), and printf("a") -> putchar('a')
81int putchar(int c) {
82 char chr = c;
83 stdout_print_strn(0, &chr, 1);
84 return chr;
85}
86
87// need this because gcc optimises printf("string\n") -> puts("string")
88int puts(const char *s) {
89 stdout_print_strn(0, s, strlen(s));
90 char chr = '\n';
91 stdout_print_strn(0, &chr, 1);
92 return 1;
93}
94
95typedef struct _strn_pfenv_t {
96 char *cur;
97 size_t remain;
98} strn_pfenv_t;
99
100void strn_print_strn(void *data, const char *str, unsigned int len) {
101 strn_pfenv_t *strn_pfenv = data;
102 if (len > strn_pfenv->remain) {
103 len = strn_pfenv->remain;
104 }
105 memcpy(strn_pfenv->cur, str, len);
106 strn_pfenv->cur += len;
107 strn_pfenv->remain -= len;
108}
Damien Georged0f9f6c2014-04-17 18:58:09 +0100109
Dave Hylandsf14b92b2014-03-12 18:06:26 -0700110int vsnprintf(char *str, size_t size, const char *fmt, va_list ap) {
111 strn_pfenv_t strn_pfenv;
112 strn_pfenv.cur = str;
113 strn_pfenv.remain = size;
114 pfenv_t pfenv;
115 pfenv.data = &strn_pfenv;
116 pfenv.print_strn = strn_print_strn;
Damien George1163cb92014-07-20 13:10:18 +0100117 int len = pfenv_vprintf(&pfenv, fmt, ap);
Dave Hylandsf14b92b2014-03-12 18:06:26 -0700118 // add terminating null byte
119 if (size > 0) {
120 if (strn_pfenv.remain == 0) {
121 strn_pfenv.cur[-1] = 0;
122 } else {
123 strn_pfenv.cur[0] = 0;
124 }
125 }
126 return len;
127}
128
129int snprintf(char *str, size_t size, const char *fmt, ...) {
130 va_list ap;
131 va_start(ap, fmt);
132 int ret = vsnprintf(str, size, fmt, ap);
133 va_end(ap);
134 return ret;
135}