CloverBootloader/Include/Library/printf_lite.h
2020-03-26 15:59:20 +03:00

200 lines
7.0 KiB
C
Executable File

//
// printf_lite.hpp
//
// Created by jief the 04 Apr 2019.
// Imported in CLover the 24 Feb 2020
//
#ifndef __PRINTF_LITE_H__
#define __PRINTF_LITE_H__
#include <stdarg.h>
#include <stddef.h> // for size_t
#include <printf_lite-conf.h>
#if defined(__cplusplus)
extern "C"
{
#endif
#ifdef DEBUG
#define DEFINE_SECTIONS 0
#endif
// To be able to compile on a platform where there are already std function snprintf, we need to change the name
#ifndef PRINTF_CFUNCTION_PREFIX
#define PRINTF_CFUNCTION_PREFIX
#endif
#ifndef PRINTF_CFUNCTION_SUFFIX
#define PRINTF_CFUNCTION_SUFFIX fl
#endif
#define PRINTF_MAKE_FN_NAME(prefix, root, suffix) prefix##root##suffix
#define PRINTF_FUNCTION_NAME(prefix, root, suffix) PRINTF_MAKE_FN_NAME(prefix, root, suffix)
#ifndef PRINTF_UTF8_INPUT_SUPPORT
#define PRINTF_UTF8_INPUT_SUPPORT 1
#endif
#ifndef PRINTF_UNICODE_INPUT_SUPPORT
#define PRINTF_UNICODE_INPUT_SUPPORT 1 // enable %ls. %ls = UTF16 or UTF32 string, depending of the size of wchar_t
#endif
#ifndef PRINTF_UTF8_OUTPUT_SUPPORT
#define PRINTF_UTF8_OUTPUT_SUPPORT 1
#endif
#ifndef PRINTF_UNICODE_OUTPUT_SUPPORT
#define PRINTF_UNICODE_OUTPUT_SUPPORT 1 // UTF16 or UTF32 depending of the size of wchar_t
#endif
#if PRINTF_UTF8_OUTPUT_SUPPORT == 0 && PRINTF_UNICODE_OUTPUT_SUPPORT == 0
#error no output format supported.
#endif
#ifndef PRINTF_LITE_SNPRINTF_SUPPORT
#define PRINTF_LITE_SNPRINTF_SUPPORT 1
#endif
#ifndef VSNWPRINTF_RETURN_MINUS1_ON_OVERFLOW
#define VSNWPRINTF_RETURN_MINUS1_ON_OVERFLOW 0
#endif
#ifndef PRINTF_CHECK_UNSUPPORTED_STRING_FORMAT
#define PRINTF_CHECK_UNSUPPORTED_STRING_FORMAT 0
#endif
/*
* A buffer is not needed. On some case it could be faster. For example when using semihosting
* It's 255 max, because of bufIdx of type uint8_t. It's possible to change it to int if bigger buffer needed.
* This buffer isn't statically allocated so it won't use permanent RAM.
* Not more than int because of cast in transmitBufXXX functions.
* 2017/08/31 : Save 22 bytes + bufsize of my STM32F103
*/
#ifndef PRINTF_LITE_BUF_SIZE
#define PRINTF_LITE_BUF_SIZE 200
#endif
/*
* Fallback on something close if specifier isn't supported.
* Unsupported specifier are ignored.
* if 0, any unsupported modifier or specifier will be seen as unknown.
*/
#ifndef PRINTF_LITE_FALLBACK_FOR_UNSUPPORTED
#define PRINTF_LITE_FALLBACK_FOR_UNSUPPORTED 0
#endif
#ifndef PRINTF_LITE_FLOAT_SUPPORT
#define PRINTF_LITE_FLOAT_SUPPORT 1
#endif
/*
* The int part of the float (or double) will be printed if PRINTF_LITE_FLOAT_SUPPORT is enabled
* June 2017, avr-gcc 4.9.2-atmel3.5.4-arduino2 :
* Float support increase 828 bytes of text and 16 bytes of data
*/
#ifndef PRINTF_LITE_FLOAT_AS_INT_SUPPORT
#define PRINTF_LITE_FLOAT_AS_INT_SUPPORT 1 // if float not supported, an int will be print instead.
#endif
/*
* Disabling LONG LONG support has an effect on printing double. If long int is disabled, the int part of the double has to be < ULONG_MAX
*/
#ifndef PRINTF_LITE_LONGLONGINT_SUPPORT
#define PRINTF_LITE_LONGLONGINT_SUPPORT 1 // 1712 bytes
#endif
/*
* Disabling LONG support automatically disable LONG LONG support whatever the value of PRINTF_LITE_LONGLONGINT_SUPPORT.
* Disabling LONG support has an effect on printing double. The int part of the double has to be < UINT_MAX max
*/
#ifndef PRINTF_LITE_LONGINT_SUPPORT
#define PRINTF_LITE_LONGINT_SUPPORT 1 // 1712 bytes
#endif
#ifndef PRINTF_LITE_TIMESTAMP_SUPPORT
#define PRINTF_LITE_TIMESTAMP_SUPPORT 0 // 240 bytes
#endif
#ifndef PRINTF_LITE_FIELDWIDTH_SUPPORT
#define PRINTF_LITE_FIELDWIDTH_SUPPORT 1 // 107 bytes
#endif
#ifndef PRINTF_LITE_FIELDPRECISION_SUPPORT
#define PRINTF_LITE_FIELDPRECISION_SUPPORT 1 // bytes
#endif
#ifndef PRINTF_LITE_PADCHAR_SUPPORT
#define PRINTF_LITE_PADCHAR_SUPPORT 1 // bytes
#endif
#ifndef PRINTF_LITE_ZSPECIFIER_SUPPORT
#define PRINTF_LITE_ZSPECIFIER_SUPPORT 1 // 230 bytes. If not supported, z modifier become llu
#endif
#ifndef PRINTF_LITE_XSPECIFIER_SUPPORT
#define PRINTF_LITE_XSPECIFIER_SUPPORT 1 // 96 bytes. If not supported, x specifier become u
#endif
#ifndef PRINTF_LITE_USPECIFIER_SUPPORT
#define PRINTF_LITE_USPECIFIER_SUPPORT 1 // 96 bytes. If not supported, u specifier become d
#endif
#ifndef PRINTF_EMIT_CR
#define PRINTF_EMIT_CR 0
#endif
/*===================================================== Private definition ============================================*/
#if PRINTF_UTF8_OUTPUT_SUPPORT == 1
typedef void (*transmitBufCallBackType)(const char* buf, unsigned int nbchar, void* context);
#endif
#if PRINTF_UNICODE_OUTPUT_SUPPORT == 1
typedef void (*transmitWBufCallBackType)(const wchar_t* buf, unsigned int nbchar, void* context);
#endif
typedef union {
#if PRINTF_UTF8_OUTPUT_SUPPORT == 1
transmitBufCallBackType transmitBufCallBack;
#endif
#if PRINTF_UNICODE_OUTPUT_SUPPORT == 1
transmitWBufCallBackType transmitWBufCallBack;
#endif
} printf_callback_t;
// I need to pass a va_list by reference, NOT value, because va_list is "incremented" in printf_handle_format_char
// On macOS, the builtin va_list type seems to already be a pointer
#ifdef __APPLE__
#define VALIST_PARAM_TYPE va_list
#define VALIST_PARAM(valist) valist
#define VALIST_ACCESS(valist) valist
#else
#define VALIST_PARAM_TYPE va_list*
#define VALIST_PARAM(valist) &valist
#define VALIST_ACCESS(valist) (*valist)
#endif
//void printf_handle_format_char(char c, VALIST_PARAM_TYPE valist, PrintfParams* printfParams);
/*===================================================== User function ============================================*/
void vprintf_with_callback(const char* format, va_list valist, transmitBufCallBackType transmitBufCallBack, void* context
#if PRINTF_LITE_TIMESTAMP_SUPPORT == 1
, int* newline, int timestamp
#endif
);
#if PRINTF_UNICODE_OUTPUT_SUPPORT == 1
void vwprintf_with_callback(const char* format, va_list valist, transmitWBufCallBackType transmitBufCallBack, void* context
#if PRINTF_LITE_TIMESTAMP_SUPPORT == 1
, int* newline, int timestamp
#endif
);
#endif
#if PRINTF_LITE_SNPRINTF_SUPPORT == 1
#if PRINTF_UTF8_OUTPUT_SUPPORT == 1
int PRINTF_FUNCTION_NAME(PRINTF_CFUNCTION_PREFIX, vsnprint, PRINTF_CFUNCTION_SUFFIX)(char*, size_t, const char *__restrict, va_list valist);
// gcc-4.9.2-atmel3.5.4-arduino2 report snprintf to undefined. Change the name and it'll work. Strange isn't it ?
int PRINTF_FUNCTION_NAME(PRINTF_CFUNCTION_PREFIX, snprint, PRINTF_CFUNCTION_SUFFIX)(char*, size_t len, const char *__restrict format, ...) __attribute__((__format__ (__printf__, 3, 4)));
#endif
#if PRINTF_UNICODE_OUTPUT_SUPPORT == 1
// ATTENTION : len is the number of wchar_t, NOT the number of bytes.
int PRINTF_FUNCTION_NAME(PRINTF_CFUNCTION_PREFIX, vsnwprint, PRINTF_CFUNCTION_SUFFIX)(wchar_t*, size_t len, const char *__restrict, va_list valist);
int PRINTF_FUNCTION_NAME(PRINTF_CFUNCTION_PREFIX, snwprint, PRINTF_CFUNCTION_SUFFIX)(wchar_t*, size_t len, const char *__restrict format, ...) __attribute__((__format__ (__printf__, 3, 4)));
#endif
#endif
#if defined(__cplusplus)
}
#endif
#endif // __PRINTF_LITE_H__