blob: d998a6277dc367cc5857a4ebcd8791b892f5e5a7 [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"
Dave Hylandsf14b92b2014-03-12 18:06:26 -070043
Damien Georgefb510b32014-06-01 13:32:54 +010044#if MICROPY_PY_BUILTINS_FLOAT
Dave Hylandsf14b92b2014-03-12 18:06:26 -070045#include "formatfloat.h"
46#endif
47
Paul Sokolovskycb66f412014-07-13 23:07:42 +030048int pfenv_vprintf(const pfenv_t *pfenv, const char *fmt, va_list args);
49
Dave Hylandsf14b92b2014-03-12 18:06:26 -070050void pfenv_prints(const pfenv_t *pfenv, const char *str) {
51 pfenv->print_strn(pfenv->data, str, strlen(str));
52}
53
Damien Georgee79c6692014-06-15 09:10:07 +010054STATIC void stdout_print_strn(void *data, const char *str, unsigned int len) {
Damien George34ab8dd2014-06-15 00:41:47 +010055 // TODO this needs to be replaced with a proper stdio interface ala CPython
56 // send stdout to UART and USB CDC VCP
Damien George75337002014-04-21 12:03:09 +010057 if (pyb_uart_global_debug != PYB_UART_NONE) {
58 uart_tx_strn_cooked(pyb_uart_global_debug, str, len);
Dave Hylandsf14b92b2014-03-12 18:06:26 -070059 }
Dave Hylandsf14b92b2014-03-12 18:06:26 -070060 if (usb_vcp_is_enabled()) {
61 usb_vcp_send_strn_cooked(str, len);
Dave Hylandsf14b92b2014-03-12 18:06:26 -070062 }
63}
64
65static const pfenv_t pfenv_stdout = {0, stdout_print_strn};
66
67int printf(const char *fmt, ...) {
68 va_list ap;
69 va_start(ap, fmt);
Paul Sokolovskycb66f412014-07-13 23:07:42 +030070 int ret = pfenv_vprintf(&pfenv_stdout, fmt, ap);
Dave Hylandsf14b92b2014-03-12 18:06:26 -070071 va_end(ap);
72 return ret;
73}
74
75int vprintf(const char *fmt, va_list ap) {
Paul Sokolovskycb66f412014-07-13 23:07:42 +030076 return pfenv_vprintf(&pfenv_stdout, fmt, ap);
Dave Hylandsf14b92b2014-03-12 18:06:26 -070077}
78
79#if MICROPY_DEBUG_PRINTERS
80int DEBUG_printf(const char *fmt, ...) {
81 (void)stream;
82 va_list ap;
83 va_start(ap, fmt);
84 int ret = pfenv_printf(&pfenv_stdout, fmt, ap);
85 va_end(ap);
86 return ret;
87}
88#endif
89
90// need this because gcc optimises printf("%c", c) -> putchar(c), and printf("a") -> putchar('a')
91int putchar(int c) {
92 char chr = c;
93 stdout_print_strn(0, &chr, 1);
94 return chr;
95}
96
97// need this because gcc optimises printf("string\n") -> puts("string")
98int puts(const char *s) {
99 stdout_print_strn(0, s, strlen(s));
100 char chr = '\n';
101 stdout_print_strn(0, &chr, 1);
102 return 1;
103}
104
105typedef struct _strn_pfenv_t {
106 char *cur;
107 size_t remain;
108} strn_pfenv_t;
109
110void strn_print_strn(void *data, const char *str, unsigned int len) {
111 strn_pfenv_t *strn_pfenv = data;
112 if (len > strn_pfenv->remain) {
113 len = strn_pfenv->remain;
114 }
115 memcpy(strn_pfenv->cur, str, len);
116 strn_pfenv->cur += len;
117 strn_pfenv->remain -= len;
118}
Damien Georged0f9f6c2014-04-17 18:58:09 +0100119
Dave Hylandsf14b92b2014-03-12 18:06:26 -0700120int vsnprintf(char *str, size_t size, const char *fmt, va_list ap) {
121 strn_pfenv_t strn_pfenv;
122 strn_pfenv.cur = str;
123 strn_pfenv.remain = size;
124 pfenv_t pfenv;
125 pfenv.data = &strn_pfenv;
126 pfenv.print_strn = strn_print_strn;
127 int len = pfenv_printf(&pfenv, fmt, ap);
128 // add terminating null byte
129 if (size > 0) {
130 if (strn_pfenv.remain == 0) {
131 strn_pfenv.cur[-1] = 0;
132 } else {
133 strn_pfenv.cur[0] = 0;
134 }
135 }
136 return len;
137}
138
139int snprintf(char *str, size_t size, const char *fmt, ...) {
140 va_list ap;
141 va_start(ap, fmt);
142 int ret = vsnprintf(str, size, fmt, ap);
143 va_end(ap);
144 return ret;
145}