Mercurial > pub > halpp
diff l476rg-hal-test/src/tiny_printf.c @ 0:32a3b1785697
a rough draft of Hardware Abstraction Layer for C++
STM32L476RG drivers
author | cin |
---|---|
date | Thu, 12 Jan 2017 02:45:43 +0300 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/l476rg-hal-test/src/tiny_printf.c Thu Jan 12 02:45:43 2017 +0300 @@ -0,0 +1,353 @@ +/* +****************************************************************************** +File: tiny_printf.c +Info: Generated by Atollic TrueSTUDIO 7.0.1 2017-01-12 + +Abstract: Atollic TrueSTUDIO Minimal iprintf/siprintf/fiprintf + and puts/fputs. + Provides aliased declarations for printf/sprintf/fprintf + pointing to *iprintf variants. + + The argument contains a format string that may include + conversion specifications. Each conversion specification + is introduced by the character %, and ends with a + conversion specifier. + + The following conversion specifiers are supported + cdisuxX% + + Usage: + c character + d,i signed integer (-sign added, + sign not supported) + s character string + u unsigned integer as decimal + x,X unsigned integer as hexadecimal (uppercase letter) + % % is written (conversion specification is '%%') + + Note: + Character padding is not supported + +The MIT License (MIT) +Copyright (c) 2009-2016 Atollic AB + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +****************************************************************************** +*/ + +/* Includes */ +#include <stdarg.h> +#include <stdio.h> +#include <string.h> + +/* Create aliases for *printf to integer variants *iprintf */ +__attribute__ ((alias("iprintf"))) int printf(const char *fmt, ...); +__attribute__ ((alias("fiprintf"))) int fprintf(FILE* fp, const char *fmt, ...); +__attribute__ ((alias("siprintf"))) int sprintf(char* str, const char *fmt, ...); + +/* External function prototypes (defined in syscalls.c) */ +extern int _write(int fd, char *str, int len); + +/* Private function prototypes */ +void ts_itoa(char **buf, unsigned int d, int base); +int ts_formatstring(char *buf, const char *fmt, va_list va); +int ts_formatlength(const char *fmt, va_list va); + +/* Private functions */ + +/** +**--------------------------------------------------------------------------- +** Abstract: Convert integer to ascii +** Returns: void +**--------------------------------------------------------------------------- +*/ +void ts_itoa(char **buf, unsigned int d, int base) +{ + int div = 1; + while (d/div >= base) + div *= base; + + while (div != 0) + { + int num = d/div; + d = d%div; + div /= base; + if (num > 9) + *((*buf)++) = (num-10) + 'A'; + else + *((*buf)++) = num + '0'; + } +} + +/** +**--------------------------------------------------------------------------- +** Abstract: Writes arguments va to buffer buf according to format fmt +** Returns: Length of string +**--------------------------------------------------------------------------- +*/ +int ts_formatstring(char *buf, const char *fmt, va_list va) +{ + char *start_buf = buf; + while(*fmt) + { + /* Character needs formating? */ + if (*fmt == '%') + { + switch (*(++fmt)) + { + case 'c': + *buf++ = va_arg(va, int); + break; + case 'd': + case 'i': + { + signed int val = va_arg(va, signed int); + if (val < 0) + { + val *= -1; + *buf++ = '-'; + } + ts_itoa(&buf, val, 10); + } + break; + case 's': + { + char * arg = va_arg(va, char *); + while (*arg) + { + *buf++ = *arg++; + } + } + break; + case 'u': + ts_itoa(&buf, va_arg(va, unsigned int), 10); + break; + case 'x': + case 'X': + ts_itoa(&buf, va_arg(va, int), 16); + break; + case '%': + *buf++ = '%'; + break; + } + fmt++; + } + /* Else just copy */ + else + { + *buf++ = *fmt++; + } + } + *buf = 0; + + return (int)(buf - start_buf); +} + + +/** +**--------------------------------------------------------------------------- +** Abstract: Calculate maximum length of the resulting string from the +** format string and va_list va +** Returns: Maximum length +**--------------------------------------------------------------------------- +*/ +int ts_formatlength(const char *fmt, va_list va) +{ + int length = 0; + while (*fmt) + { + if (*fmt == '%') + { + ++fmt; + switch (*fmt) + { + case 'c': + va_arg(va, int); + ++length; + break; + case 'd': + case 'i': + case 'u': + /* 32 bits integer is max 11 characters with minus sign */ + length += 11; + va_arg(va, int); + break; + case 's': + { + char * str = va_arg(va, char *); + while (*str++) + ++length; + } + break; + case 'x': + case 'X': + /* 32 bits integer as hex is max 8 characters */ + length += 8; + va_arg(va, unsigned int); + break; + default: + ++length; + break; + } + } + else + { + ++length; + } + ++fmt; + } + return length; +} + +/** +**=========================================================================== +** Abstract: Loads data from the given locations and writes them to the +** given character string according to the format parameter. +** Returns: Number of bytes written +**=========================================================================== +*/ +int siprintf(char *buf, const char *fmt, ...) +{ + int length; + va_list va; + va_start(va, fmt); + length = ts_formatstring(buf, fmt, va); + va_end(va); + return length; +} + +/** +**=========================================================================== +** Abstract: Loads data from the given locations and writes them to the +** given file stream according to the format parameter. +** Returns: Number of bytes written +**=========================================================================== +*/ +int fiprintf(FILE * stream, const char *fmt, ...) +{ + int length = 0; + va_list va; + va_start(va, fmt); + length = ts_formatlength(fmt, va); + va_end(va); + { + char buf[length]; + va_start(va, fmt); + length = ts_formatstring(buf, fmt, va); + length = _write(stream->_file, buf, length); + va_end(va); + } + return length; +} + +/** +**=========================================================================== +** Abstract: Loads data from the given locations and writes them to the +** standard output according to the format parameter. +** Returns: Number of bytes written +** +**=========================================================================== +*/ +int iprintf(const char *fmt, ...) +{ + int length = 0; + va_list va; + va_start(va, fmt); + length = ts_formatlength(fmt, va); + va_end(va); + { + char buf[length]; + va_start(va, fmt); + length = ts_formatstring(buf, fmt, va); + length = _write(1, buf, length); + va_end(va); + } + return length; +} + +/** +**=========================================================================== +** Abstract: fputs writes the string at s (but without the trailing null) to +** the file or stream identified by fp. +** Returns: If successful, the result is 0; otherwise, the result is EOF. +** +**=========================================================================== +*/ +int fputs(const char *s, FILE *fp) +{ + int length = strlen(s); + int wlen = 0; + int res; + + wlen = _write((fp->_file), (char*)s, length); + wlen += _write((fp->_file), "\n", 1); + + if (wlen == (length+1)) + { + res = 0; + } + else + { + res = EOF; + } + + return res; +} + +/** +**=========================================================================== +** Abstract: puts writes the string at s (followed by a newline, instead of +** the trailing null) to the standard output stream. +** Returns: If successful, the result is a nonnegative integer; otherwise, +** the result is EOF. +** +**=========================================================================== +*/ +int puts(const char *s) +{ + int length = strlen(s); + int numbytes = 0; + int res; + + numbytes = _write(1, (char*)s, length); + numbytes += _write(1, "\n", 1); + + if (numbytes == (length+1)) + { + res = 0; + } + else + { + res = EOF; + } + + return res; +} + +/** +**=========================================================================== +** Abstract: Copy, starting from the memory location buf, count elements +** (each of size size) into the file or stream identified by fp. +** Returns: Number of elements written +** +**=========================================================================== +*/ +size_t fwrite(const void * buf, size_t size, size_t count, FILE * fp) +{ + return (_write((fp->_file), (char*)buf, size * count) / size); +}