blob: 038ee99376e2aeb60f83b8de66ed481706be0e3f [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
Damien George2cf6dfa2015-01-01 21:06:20 +000031#include "py/obj.h"
32#include "py/pfenv.h"
Damien George601c8142015-02-13 15:26:53 +000033#ifdef MICROPY_HAL_H
Damien George0b32e502015-02-13 15:04:53 +000034#include MICROPY_HAL_H
Damien George601c8142015-02-13 15:26:53 +000035#endif
Dave Hylandsf14b92b2014-03-12 18:06:26 -070036
Damien Georgefb510b32014-06-01 13:32:54 +010037#if MICROPY_PY_BUILTINS_FLOAT
Damien George2cf6dfa2015-01-01 21:06:20 +000038#include "py/formatfloat.h"
Dave Hylandsf14b92b2014-03-12 18:06:26 -070039#endif
40
Damien Georged03c6812014-10-05 21:51:54 +010041STATIC void stdout_print_strn(void *dummy_env, const char *str, mp_uint_t len) {
Damien George0b32e502015-02-13 15:04:53 +000042 mp_hal_stdout_tx_strn_cooked(str, len);
Dave Hylandsf14b92b2014-03-12 18:06:26 -070043}
44
Damien George951ed9d2014-07-20 13:57:43 +010045STATIC const pfenv_t pfenv_stdout = {0, stdout_print_strn};
Dave Hylandsf14b92b2014-03-12 18:06:26 -070046
47int printf(const char *fmt, ...) {
48 va_list ap;
49 va_start(ap, fmt);
Paul Sokolovskycb66f412014-07-13 23:07:42 +030050 int ret = pfenv_vprintf(&pfenv_stdout, fmt, ap);
Dave Hylandsf14b92b2014-03-12 18:06:26 -070051 va_end(ap);
52 return ret;
53}
54
55int vprintf(const char *fmt, va_list ap) {
Paul Sokolovskycb66f412014-07-13 23:07:42 +030056 return pfenv_vprintf(&pfenv_stdout, fmt, ap);
Dave Hylandsf14b92b2014-03-12 18:06:26 -070057}
58
59#if MICROPY_DEBUG_PRINTERS
Dave Hylands3556e452014-10-07 00:50:20 -070060mp_uint_t mp_verbose_flag = 1;
61
Dave Hylandsf14b92b2014-03-12 18:06:26 -070062int DEBUG_printf(const char *fmt, ...) {
Dave Hylandsf14b92b2014-03-12 18:06:26 -070063 va_list ap;
64 va_start(ap, fmt);
Damien George1163cb92014-07-20 13:10:18 +010065 int ret = pfenv_vprintf(&pfenv_stdout, fmt, ap);
Dave Hylandsf14b92b2014-03-12 18:06:26 -070066 va_end(ap);
67 return ret;
68}
69#endif
70
71// need this because gcc optimises printf("%c", c) -> putchar(c), and printf("a") -> putchar('a')
72int putchar(int c) {
73 char chr = c;
74 stdout_print_strn(0, &chr, 1);
75 return chr;
76}
77
78// need this because gcc optimises printf("string\n") -> puts("string")
79int puts(const char *s) {
80 stdout_print_strn(0, s, strlen(s));
81 char chr = '\n';
82 stdout_print_strn(0, &chr, 1);
83 return 1;
84}
85
86typedef struct _strn_pfenv_t {
87 char *cur;
88 size_t remain;
89} strn_pfenv_t;
90
Damien Georged03c6812014-10-05 21:51:54 +010091STATIC void strn_print_strn(void *data, const char *str, mp_uint_t len) {
Dave Hylandsf14b92b2014-03-12 18:06:26 -070092 strn_pfenv_t *strn_pfenv = data;
93 if (len > strn_pfenv->remain) {
94 len = strn_pfenv->remain;
95 }
96 memcpy(strn_pfenv->cur, str, len);
97 strn_pfenv->cur += len;
98 strn_pfenv->remain -= len;
99}
Damien Georged0f9f6c2014-04-17 18:58:09 +0100100
Dave Hylandsf14b92b2014-03-12 18:06:26 -0700101int vsnprintf(char *str, size_t size, const char *fmt, va_list ap) {
102 strn_pfenv_t strn_pfenv;
103 strn_pfenv.cur = str;
104 strn_pfenv.remain = size;
105 pfenv_t pfenv;
106 pfenv.data = &strn_pfenv;
107 pfenv.print_strn = strn_print_strn;
Damien George1163cb92014-07-20 13:10:18 +0100108 int len = pfenv_vprintf(&pfenv, fmt, ap);
Dave Hylandsf14b92b2014-03-12 18:06:26 -0700109 // add terminating null byte
110 if (size > 0) {
111 if (strn_pfenv.remain == 0) {
112 strn_pfenv.cur[-1] = 0;
113 } else {
114 strn_pfenv.cur[0] = 0;
115 }
116 }
117 return len;
118}
119
120int snprintf(char *str, size_t size, const char *fmt, ...) {
121 va_list ap;
122 va_start(ap, fmt);
123 int ret = vsnprintf(str, size, fmt, ap);
124 va_end(ap);
125 return ret;
126}