Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 8621 → Rev 8622

/contrib/kolibri-libc/source/stdio/clearerr.c
0,0 → 1,6
#include <stdio.h>
 
void clearerr(FILE *stream) {
stream->error = 0;
stream->eof = 0;
}
/contrib/kolibri-libc/source/stdio/conio.c
0,0 → 1,56
#include <ksys.h>
#include "conio.h"
 
static char* __con_caption = "Console application";
static char* __con_dllname = "/sys/lib/console.obj";
 
int __con_is_load = 0;
 
unsigned *__con_dll_ver;
void stdcall (*__con_init_hidden)(int wnd_width, int wnd_height,int scr_width, int scr_height, const char* title);
void stdcall (*__con_write_asciiz)(const char* str);
void stdcall (*__con_write_string)(const char* str, unsigned length);
int stdcall (*__con_getch)(void);
short stdcall (*__con_getch2)(void);
int stdcall (*__con_kbhit)(void);
char* stdcall (*__con_gets)(char* str, int n);
char* stdcall (*__con_gets2)(__con_gets2_callback callback, char* str, int n);
void stdcall (*__con_exit)(int status);
 
static void __con_lib_link(ksys_coff_etable_t *exp)
{
__con_dll_ver = _ksys_cofflib_getproc(exp, "con_dll_ver");
__con_init_hidden = _ksys_cofflib_getproc(exp, "con_init");
__con_write_asciiz = _ksys_cofflib_getproc(exp, "con_write_asciiz");
__con_write_string = _ksys_cofflib_getproc(exp, "con_write_string");
__con_getch = _ksys_cofflib_getproc(exp, "con_getch");
__con_getch2 = _ksys_cofflib_getproc(exp, "con_getch2");
__con_kbhit = _ksys_cofflib_getproc(exp, "con_kbhit");
__con_gets = _ksys_cofflib_getproc(exp, "con_gets");
__con_gets2 = _ksys_cofflib_getproc(exp, "con_gets2");
__con_exit = _ksys_cofflib_getproc(exp, "con_exit");
}
 
 
int __con_init(void)
{
return __con_init_opt(-1, -1, -1, -1, __con_caption);
}
 
 
int __con_init_opt(int wnd_width, int wnd_height,int scr_width, int scr_height, const char* title)
{
if(!__con_is_load){
ksys_coff_etable_t *__con_lib;
__con_lib = _ksys_cofflib_load(__con_dllname);
if(__con_lib==NULL){
_ksys_debug_puts("Error! Can't load console.obj lib\n");
return 1;
}
__con_lib_link(__con_lib);
__con_init_hidden(wnd_width, wnd_height, scr_width, scr_height, title);
__con_is_load= 1;
return 0;
}
return 1;
}
/contrib/kolibri-libc/source/stdio/conio.h
0,0 → 1,76
/*
 
This is adapded thunk for console.obj sys library
Only for internal use in stdio.h
 
Adapted for tcc by Siemargl, 2016
 
*/
#ifndef _CONIO_H_
#define _CONIO_H_
 
#define cdecl __attribute__ ((cdecl))
#define stdcall __attribute__ ((stdcall))
 
extern void stdcall (*__con_write_asciiz)(const char* str);
/* Display ASCIIZ-string to the console at the current position, shifting
the current position. */
 
extern void stdcall (*__con_write_string)(const char* str, unsigned length);
/* Similar to __con_write_asciiz, but length of the string must be given as a
separate parameter */
 
extern int stdcall (*__con_getch)(void);
/* Get one character from the keyboard.
 
For normal characters function returns ASCII-code. For extended
characters (eg, Fx, and arrows), first function call returns 0
and second call returns the extended code (similar to the DOS-function
input). Starting from version 7, after closing the console window,
this function returns 0. */
 
extern short stdcall (*__con_getch2)(void);
/* Reads a character from the keyboard. Low byte contains the ASCII-code
(0 for extended characters), high byte - advanced code (like in BIOS
input functions). Starting from version 7, after closing the console
window, this function returns 0. */
 
extern int stdcall (*__con_kbhit)(void);
/* Returns 1 if a key was pressed, 0 otherwise. To read pressed keys use
__con_getch and __con_getch2. Starting from version 6, after closing
the console window, this function returns 1. */
 
extern char* stdcall (*__con_gets)(char* str, int n);
/* Reads a string from the keyboard. Reading is interrupted when got
"new line" character, or after reading the (n-1) characters (depending on
what comes first). In the first case the newline is also recorded in the
str. The acquired line is complemented by a null character.
Starting from version 6, the function returns a pointer to the entered
line if reading was successful, and NULL if the console window was closed. */
 
typedef int (stdcall * __con_gets2_callback)(int keycode, char** pstr, int* pn,
int* ppos);
 
extern char* stdcall (*__con_gets2)(__con_gets2_callback callback, char* str, int n);
/* Con_gets completely analogous, except that when the user
press unrecognized key, it calls the specified callback-procedure
(which may, for example, handle up / down for history and tab to enter
autocompletion). You should pass to the procedure: key code and three pointers
- to the string, to the maximum length and to the current position.
function may change the contents of string and may change the string
itself (for example, to reallocate memory for increase the limit),
maximum length, and position of the line - pointers are passed for it.
Return value: 0 = line wasn't changed 1 = line changed, you should
remove old string and display new, 2 = line changed, it is necessary
to display it; 3 = immediately exit the function.
Starting from version 6, the function returns a pointer to the entered
line with the successful reading, and NULL if the console window was closed. */
 
extern int __con_is_load;
extern unsigned *__con_dll_ver;
 
extern int __con_init(void);
extern int __con_init_opt(int wnd_width, int wnd_height, int scr_width, int scr_height, const char* title);
extern void stdcall (*__con_exit)(int status);
 
#endif
/contrib/kolibri-libc/source/stdio/debug_printf.c
0,0 → 1,14
/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */
 
#include <stdio.h>
#include <stdarg.h>
 
void debug_printf(const char *format,...)
{
va_list ap;
char log_board[300];
va_start (ap, format);
vsnprintf(log_board, 300, format, ap);
va_end(ap);
_ksys_debug_puts(log_board);
}
/contrib/kolibri-libc/source/stdio/fclose.c
0,0 → 1,7
#include <stdio.h>
#include <stdlib.h>
 
int fclose(FILE *stream) {
free(stream);
return 0;
}
/contrib/kolibri-libc/source/stdio/feof.c
0,0 → 1,5
#include <stdio.h>
 
int feof(FILE *stream) {
return stream->eof;
}
/contrib/kolibri-libc/source/stdio/ferror.c
0,0 → 1,5
#include <stdio.h>
 
int ferror(FILE *stream) {
return stream->error;
}
/contrib/kolibri-libc/source/stdio/fflush.c
0,0 → 1,5
#include <stdio.h>
 
int fflush(FILE *stream) {
return 0;
}
/contrib/kolibri-libc/source/stdio/fgetc.c
0,0 → 1,11
#include <stdio.h>
 
int fgetc(FILE* stream)
{
int c, rc;
rc = fread(&c, sizeof(char), 1, stream);
if(rc<1){
return EOF;
}
return c;
}
/contrib/kolibri-libc/source/stdio/fgetpos.c
0,0 → 1,6
#include <stdio.h>
 
int fgetpos(FILE *restrict stream, fpos_t *restrict pos) {
*pos = stream->position;
return 0;
}
/contrib/kolibri-libc/source/stdio/fgets.c
0,0 → 1,24
#include <stdio.h>
#include "conio.h"
#include <errno.h>
 
char *fgets(char *str, int n, FILE *stream)
{
int i=0, sym_code;
 
if(!stream || !str){
errno = EINVAL;
return NULL;
}
while (i<n-1){
sym_code = fgetc(stream);
if(sym_code =='\n' || sym_code == EOF){ break; }
str[i]=(char)sym_code;
i++;
}
if(i<1){ return NULL; }
return str;
}
/contrib/kolibri-libc/source/stdio/fopen.c
0,0 → 1,7
#include <stdio.h>
#include <stdlib.h>
 
FILE *fopen(const char *restrict _name, const char *restrict _mode) {
FILE *out = malloc(sizeof(FILE));
return freopen(_name, _mode, out);
}
/contrib/kolibri-libc/source/stdio/format_print.c
0,0 → 1,816
///////////////////////////////////////////////////////////////////////////////
// \author (c) Marco Paland (info@paland.com)
// 2014-2019, PALANDesign Hannover, Germany
//
// \license The MIT License (MIT)
//
// 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.
//
// \brief Tiny printf, sprintf and (v)snprintf implementation, optimized for speed on
// embedded systems with a very limited resources. These routines are thread
// safe and reentrant!
// Use this instead of the bloated standard/newlib printf cause these use
// malloc for printf (and may not be thread safe).
//
///////////////////////////////////////////////////////////////////////////////
 
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "format_print.h"
 
// 'ntoa' conversion buffer size, this must be big enough to hold one converted
// numeric number including padded zeros (dynamically created on stack)
// default: 32 byte
#ifndef PRINTF_NTOA_BUFFER_SIZE
#define PRINTF_NTOA_BUFFER_SIZE 32U
#endif
 
// 'ftoa' conversion buffer size, this must be big enough to hold one converted
// float number including padded zeros (dynamically created on stack)
// default: 32 byte
#ifndef PRINTF_FTOA_BUFFER_SIZE
#define PRINTF_FTOA_BUFFER_SIZE 32U
#endif
 
// support for the floating point type (%f)
// default: activated
#ifndef PRINTF_DISABLE_SUPPORT_FLOAT
#define PRINTF_SUPPORT_FLOAT
#endif
 
// support for exponential floating point notation (%e/%g)
// default: activated
#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL
#define PRINTF_SUPPORT_EXPONENTIAL
#endif
 
// define the default floating point precision
// default: 6 digits
#ifndef PRINTF_DEFAULT_FLOAT_PRECISION
#define PRINTF_DEFAULT_FLOAT_PRECISION 6U
#endif
 
// define the largest float suitable to print with %f
// default: 1e9
#ifndef PRINTF_MAX_FLOAT
#define PRINTF_MAX_FLOAT 1e9
#endif
 
// support for the long long types (%llu or %p)
// default: activated
#ifndef PRINTF_DISABLE_SUPPORT_LONG_LONG
#define PRINTF_SUPPORT_LONG_LONG
#endif
 
// support for the ptrdiff_t type (%t)
// ptrdiff_t is normally defined in <stddef.h> as long or long long type
// default: activated
#ifndef PRINTF_DISABLE_SUPPORT_PTRDIFF_T
#define PRINTF_SUPPORT_PTRDIFF_T
#endif
 
///////////////////////////////////////////////////////////////////////////////
 
// internal flag definitions
#define FLAGS_ZEROPAD (1U << 0U)
#define FLAGS_LEFT (1U << 1U)
#define FLAGS_PLUS (1U << 2U)
#define FLAGS_SPACE (1U << 3U)
#define FLAGS_HASH (1U << 4U)
#define FLAGS_UPPERCASE (1U << 5U)
#define FLAGS_CHAR (1U << 6U)
#define FLAGS_SHORT (1U << 7U)
#define FLAGS_LONG (1U << 8U)
#define FLAGS_LONG_LONG (1U << 9U)
#define FLAGS_PRECISION (1U << 10U)
#define FLAGS_ADAPT_EXP (1U << 11U)
 
 
// import float.h for DBL_MAX
#if defined(PRINTF_SUPPORT_FLOAT)
#include <float.h>
#endif
 
 
// internal buffer output
void _out_buffer(char character, void* buffer, size_t idx, size_t maxlen)
{
if (idx < maxlen) {
((char*)buffer)[idx] = character;
}
}
 
 
// internal null output
void _out_null(char character, void* buffer, size_t idx, size_t maxlen)
{
(void)character; (void)buffer; (void)idx; (void)maxlen;
}
 
 
// internal secure strlen
// \return The length of the string (excluding the terminating 0) limited by 'maxsize'
static inline unsigned int _strnlen_s(const char* str, size_t maxsize)
{
const char* s;
for (s = str; *s && maxsize--; ++s);
return (unsigned int)(s - str);
}
 
 
// internal test if char is a digit (0-9)
// \return true if char is a digit
static inline bool _is_digit(char ch)
{
return (ch >= '0') && (ch <= '9');
}
 
 
// internal ASCII string to unsigned int conversion
static unsigned int _atoi(const char** str)
{
unsigned int i = 0U;
while (_is_digit(**str)) {
i = i * 10U + (unsigned int)(*((*str)++) - '0');
}
return i;
}
 
 
// output the specified string in reverse, taking care of any zero-padding
static size_t _out_rev(out_fct_type out, char* buffer, size_t idx, size_t maxlen, const char* buf, size_t len, unsigned int width, unsigned int flags)
{
const size_t start_idx = idx;
 
// pad spaces up to given width
if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) {
for (size_t i = len; i < width; i++) {
out(' ', buffer, idx++, maxlen);
}
}
 
// reverse string
while (len) {
out(buf[--len], buffer, idx++, maxlen);
}
 
// append pad spaces up to given width
if (flags & FLAGS_LEFT) {
while (idx - start_idx < width) {
out(' ', buffer, idx++, maxlen);
}
}
 
return idx;
}
 
 
// internal itoa format
static size_t _ntoa_format(out_fct_type out, char* buffer, size_t idx, size_t maxlen, char* buf, size_t len, bool negative, unsigned int base, unsigned int prec, unsigned int width, unsigned int flags)
{
// pad leading zeros
if (!(flags & FLAGS_LEFT)) {
if (width && (flags & FLAGS_ZEROPAD) && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
width--;
}
while ((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = '0';
}
while ((flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = '0';
}
}
 
// handle hash
if (flags & FLAGS_HASH) {
if (!(flags & FLAGS_PRECISION) && len && ((len == prec) || (len == width))) {
len--;
if (len && (base == 16U)) {
len--;
}
}
if ((base == 16U) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = 'x';
}
else if ((base == 16U) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = 'X';
}
else if ((base == 2U) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = 'b';
}
if (len < PRINTF_NTOA_BUFFER_SIZE) {
buf[len++] = '0';
}
}
 
if (len < PRINTF_NTOA_BUFFER_SIZE) {
if (negative) {
buf[len++] = '-';
}
else if (flags & FLAGS_PLUS) {
buf[len++] = '+'; // ignore the space if the '+' exists
}
else if (flags & FLAGS_SPACE) {
buf[len++] = ' ';
}
}
 
return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
}
 
 
// internal itoa for 'long' type
static size_t _ntoa_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long value, bool negative, unsigned long base, unsigned int prec, unsigned int width, unsigned int flags)
{
char buf[PRINTF_NTOA_BUFFER_SIZE];
size_t len = 0U;
 
// no hash for 0 values
if (!value) {
flags &= ~FLAGS_HASH;
}
 
// write if precision != 0 and value is != 0
if (!(flags & FLAGS_PRECISION) || value) {
do {
const char digit = (char)(value % base);
buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
value /= base;
} while (value && (len < PRINTF_NTOA_BUFFER_SIZE));
}
 
return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags);
}
 
 
// internal itoa for 'long long' type
#if defined(PRINTF_SUPPORT_LONG_LONG)
static size_t _ntoa_long_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long long value, bool negative, unsigned long long base, unsigned int prec, unsigned int width, unsigned int flags)
{
char buf[PRINTF_NTOA_BUFFER_SIZE];
size_t len = 0U;
 
// no hash for 0 values
if (!value) {
flags &= ~FLAGS_HASH;
}
 
// write if precision != 0 and value is != 0
if (!(flags & FLAGS_PRECISION) || value) {
do {
const char digit = (char)(value % base);
buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
value /= base;
} while (value && (len < PRINTF_NTOA_BUFFER_SIZE));
}
 
return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags);
}
#endif // PRINTF_SUPPORT_LONG_LONG
 
 
#if defined(PRINTF_SUPPORT_FLOAT)
 
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
// forward declaration so that _ftoa can switch to exp notation for values > PRINTF_MAX_FLOAT
static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags);
#endif
 
 
// internal ftoa for fixed decimal floating point
static size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags)
{
char buf[PRINTF_FTOA_BUFFER_SIZE];
size_t len = 0U;
double diff = 0.0;
 
// powers of 10
static const double pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
 
// test for special values
if (value != value)
return _out_rev(out, buffer, idx, maxlen, "nan", 3, width, flags);
if (value < -DBL_MAX)
return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags);
if (value > DBL_MAX)
return _out_rev(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags);
 
// test for very large values
// standard printf behavior is to print EVERY whole number digit -- which could be 100s of characters overflowing your buffers == bad
if ((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) {
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
return _etoa(out, buffer, idx, maxlen, value, prec, width, flags);
#else
return 0U;
#endif
}
 
// test for negative
bool negative = false;
if (value < 0) {
negative = true;
value = 0 - value;
}
 
// set default precision, if not set explicitly
if (!(flags & FLAGS_PRECISION)) {
prec = PRINTF_DEFAULT_FLOAT_PRECISION;
}
// limit precision to 9, cause a prec >= 10 can lead to overflow errors
while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) {
buf[len++] = '0';
prec--;
}
 
int whole = (int)value;
double tmp = (value - whole) * pow10[prec];
unsigned long frac = (unsigned long)tmp;
diff = tmp - frac;
 
if (diff > 0.5) {
++frac;
// handle rollover, e.g. case 0.99 with prec 1 is 1.0
if (frac >= pow10[prec]) {
frac = 0;
++whole;
}
}
else if (diff < 0.5) {
}
else if ((frac == 0U) || (frac & 1U)) {
// if halfway, round up if odd OR if last digit is 0
++frac;
}
 
if (prec == 0U) {
diff = value - (double)whole;
if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) {
// exactly 0.5 and ODD, then round up
// 1.5 -> 2, but 2.5 -> 2
++whole;
}
}
else {
unsigned int count = prec;
// now do fractional part, as an unsigned number
while (len < PRINTF_FTOA_BUFFER_SIZE) {
--count;
buf[len++] = (char)(48U + (frac % 10U));
if (!(frac /= 10U)) {
break;
}
}
// add extra 0s
while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) {
buf[len++] = '0';
}
if (len < PRINTF_FTOA_BUFFER_SIZE) {
// add decimal
buf[len++] = '.';
}
}
 
// do whole part, number is reversed
while (len < PRINTF_FTOA_BUFFER_SIZE) {
buf[len++] = (char)(48 + (whole % 10));
if (!(whole /= 10)) {
break;
}
}
 
// pad leading zeros
if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) {
if (width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
width--;
}
while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) {
buf[len++] = '0';
}
}
 
if (len < PRINTF_FTOA_BUFFER_SIZE) {
if (negative) {
buf[len++] = '-';
}
else if (flags & FLAGS_PLUS) {
buf[len++] = '+'; // ignore the space if the '+' exists
}
else if (flags & FLAGS_SPACE) {
buf[len++] = ' ';
}
}
 
return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
}
 
 
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
// internal ftoa variant for exponential floating-point type, contributed by Martijn Jasperse <m.jasperse@gmail.com>
static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags)
{
// check for NaN and special values
if ((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) {
return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags);
}
 
// determine the sign
const bool negative = value < 0;
if (negative) {
value = -value;
}
 
// default precision
if (!(flags & FLAGS_PRECISION)) {
prec = PRINTF_DEFAULT_FLOAT_PRECISION;
}
 
// determine the decimal exponent
// based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c)
union {
uint64_t U;
double F;
} conv;
 
conv.F = value;
int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023; // effectively log2
conv.U = (conv.U & ((1ULL << 52U) - 1U)) | (1023ULL << 52U); // drop the exponent so conv.F is now in [1,2)
// now approximate log10 from the log2 integer part and an expansion of ln around 1.5
int expval = (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168);
// now we want to compute 10^expval but we want to be sure it won't overflow
exp2 = (int)(expval * 3.321928094887362 + 0.5);
const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453;
const double z2 = z * z;
conv.U = (uint64_t)(exp2 + 1023) << 52U;
// compute exp(z) using continued fractions, see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex
conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14)))));
// correct for rounding errors
if (value < conv.F) {
expval--;
conv.F /= 10;
}
 
// the exponent format is "%+03d" and largest value is "307", so set aside 4-5 characters
unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U;
 
// in "%g" mode, "prec" is the number of *significant figures* not decimals
if (flags & FLAGS_ADAPT_EXP) {
// do we want to fall-back to "%f" mode?
if ((value >= 1e-4) && (value < 1e6)) {
if ((int)prec > expval) {
prec = (unsigned)((int)prec - expval - 1);
}
else {
prec = 0;
}
flags |= FLAGS_PRECISION; // make sure _ftoa respects precision
// no characters in exponent
minwidth = 0U;
expval = 0;
}
else {
// we use one sigfig for the whole part
if ((prec > 0) && (flags & FLAGS_PRECISION)) {
--prec;
}
}
}
 
// will everything fit?
unsigned int fwidth = width;
if (width > minwidth) {
// we didn't fall-back so subtract the characters required for the exponent
fwidth -= minwidth;
} else {
// not enough characters, so go back to default sizing
fwidth = 0U;
}
if ((flags & FLAGS_LEFT) && minwidth) {
// if we're padding on the right, DON'T pad the floating part
fwidth = 0U;
}
 
// rescale the float value
if (expval) {
value /= conv.F;
}
 
// output the floating part
const size_t start_idx = idx;
idx = _ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, flags & ~FLAGS_ADAPT_EXP);
 
// output the exponent part
if (minwidth) {
// output the exponential symbol
out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen);
// output the exponent value
idx = _ntoa_long(out, buffer, idx, maxlen, (expval < 0) ? -expval : expval, expval < 0, 10, 0, minwidth-1, FLAGS_ZEROPAD | FLAGS_PLUS);
// might need to right-pad spaces
if (flags & FLAGS_LEFT) {
while (idx - start_idx < width) out(' ', buffer, idx++, maxlen);
}
}
return idx;
}
#endif // PRINTF_SUPPORT_EXPONENTIAL
#endif // PRINTF_SUPPORT_FLOAT
 
 
// internal vsnprintf
int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const char* format, va_list va)
{
unsigned int flags, width, precision, n;
size_t idx = 0U;
 
if (!buffer) {
// use null output function
out = _out_null;
}
 
while (*format)
{
// format specifier? %[flags][width][.precision][length]
if (*format != '%') {
// no
out(*format, buffer, idx++, maxlen);
format++;
continue;
}
else {
// yes, evaluate it
format++;
}
 
// evaluate flags
flags = 0U;
do {
switch (*format) {
case '0': flags |= FLAGS_ZEROPAD; format++; n = 1U; break;
case '-': flags |= FLAGS_LEFT; format++; n = 1U; break;
case '+': flags |= FLAGS_PLUS; format++; n = 1U; break;
case ' ': flags |= FLAGS_SPACE; format++; n = 1U; break;
case '#': flags |= FLAGS_HASH; format++; n = 1U; break;
default : n = 0U; break;
}
} while (n);
 
// evaluate width field
width = 0U;
if (_is_digit(*format)) {
width = _atoi(&format);
}
else if (*format == '*') {
const int w = va_arg(va, int);
if (w < 0) {
flags |= FLAGS_LEFT; // reverse padding
width = (unsigned int)-w;
}
else {
width = (unsigned int)w;
}
format++;
}
 
// evaluate precision field
precision = 0U;
if (*format == '.') {
flags |= FLAGS_PRECISION;
format++;
if (_is_digit(*format)) {
precision = _atoi(&format);
}
else if (*format == '*') {
const int prec = (int)va_arg(va, int);
precision = prec > 0 ? (unsigned int)prec : 0U;
format++;
}
}
 
// evaluate length field
switch (*format) {
case 'l' :
flags |= FLAGS_LONG;
format++;
if (*format == 'l') {
flags |= FLAGS_LONG_LONG;
format++;
}
break;
case 'h' :
flags |= FLAGS_SHORT;
format++;
if (*format == 'h') {
flags |= FLAGS_CHAR;
format++;
}
break;
#if defined(PRINTF_SUPPORT_PTRDIFF_T)
case 't' :
flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
format++;
break;
#endif
case 'j' :
flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
format++;
break;
case 'z' :
flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
format++;
break;
default :
break;
}
 
// evaluate specifier
switch (*format) {
case 'd' :
case 'i' :
case 'u' :
case 'x' :
case 'X' :
case 'o' :
case 'b' : {
// set the base
unsigned int base;
if (*format == 'x' || *format == 'X') {
base = 16U;
}
else if (*format == 'o') {
base = 8U;
}
else if (*format == 'b') {
base = 2U;
}
else {
base = 10U;
flags &= ~FLAGS_HASH; // no hash for dec format
}
// uppercase
if (*format == 'X') {
flags |= FLAGS_UPPERCASE;
}
 
// no plus or space flag for u, x, X, o, b
if ((*format != 'i') && (*format != 'd')) {
flags &= ~(FLAGS_PLUS | FLAGS_SPACE);
}
 
// ignore '0' flag when precision is given
if (flags & FLAGS_PRECISION) {
flags &= ~FLAGS_ZEROPAD;
}
 
// convert the integer
if ((*format == 'i') || (*format == 'd')) {
// signed
if (flags & FLAGS_LONG_LONG) {
#if defined(PRINTF_SUPPORT_LONG_LONG)
const long long value = va_arg(va, long long);
idx = _ntoa_long_long(out, buffer, idx, maxlen, (unsigned long long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
#endif
}
else if (flags & FLAGS_LONG) {
const long value = va_arg(va, long);
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
}
else {
const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int) : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) : va_arg(va, int);
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned int)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
}
}
else {
// unsigned
if (flags & FLAGS_LONG_LONG) {
#if defined(PRINTF_SUPPORT_LONG_LONG)
idx = _ntoa_long_long(out, buffer, idx, maxlen, va_arg(va, unsigned long long), false, base, precision, width, flags);
#endif
}
else if (flags & FLAGS_LONG) {
idx = _ntoa_long(out, buffer, idx, maxlen, va_arg(va, unsigned long), false, base, precision, width, flags);
}
else {
const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned char)va_arg(va, unsigned int) : (flags & FLAGS_SHORT) ? (unsigned short int)va_arg(va, unsigned int) : va_arg(va, unsigned int);
idx = _ntoa_long(out, buffer, idx, maxlen, value, false, base, precision, width, flags);
}
}
format++;
break;
}
#if defined(PRINTF_SUPPORT_FLOAT)
case 'f' :
case 'F' :
if (*format == 'F') flags |= FLAGS_UPPERCASE;
idx = _ftoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags);
format++;
break;
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
case 'e':
case 'E':
case 'g':
case 'G':
if ((*format == 'g')||(*format == 'G')) flags |= FLAGS_ADAPT_EXP;
if ((*format == 'E')||(*format == 'G')) flags |= FLAGS_UPPERCASE;
idx = _etoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags);
format++;
break;
#endif // PRINTF_SUPPORT_EXPONENTIAL
#endif // PRINTF_SUPPORT_FLOAT
case 'c' : {
unsigned int l = 1U;
// pre padding
if (!(flags & FLAGS_LEFT)) {
while (l++ < width) {
out(' ', buffer, idx++, maxlen);
}
}
// char output
out((char)va_arg(va, int), buffer, idx++, maxlen);
// post padding
if (flags & FLAGS_LEFT) {
while (l++ < width) {
out(' ', buffer, idx++, maxlen);
}
}
format++;
break;
}
 
case 's' : {
const char* p = va_arg(va, char*);
unsigned int l = _strnlen_s(p, precision ? precision : (size_t)-1);
// pre padding
if (flags & FLAGS_PRECISION) {
l = (l < precision ? l : precision);
}
if (!(flags & FLAGS_LEFT)) {
while (l++ < width) {
out(' ', buffer, idx++, maxlen);
}
}
// string output
while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) {
out(*(p++), buffer, idx++, maxlen);
}
// post padding
if (flags & FLAGS_LEFT) {
while (l++ < width) {
out(' ', buffer, idx++, maxlen);
}
}
format++;
break;
}
 
case 'p' : {
width = sizeof(void*) * 2U;
flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE;
#if defined(PRINTF_SUPPORT_LONG_LONG)
const bool is_ll = sizeof(uintptr_t) == sizeof(long long);
if (is_ll) {
idx = _ntoa_long_long(out, buffer, idx, maxlen, (uintptr_t)va_arg(va, void*), false, 16U, precision, width, flags);
}
else {
#endif
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)((uintptr_t)va_arg(va, void*)), false, 16U, precision, width, flags);
#if defined(PRINTF_SUPPORT_LONG_LONG)
}
#endif
format++;
break;
}
 
case '%' :
out('%', buffer, idx++, maxlen);
format++;
break;
 
default :
out(*format, buffer, idx++, maxlen);
format++;
break;
}
}
 
// termination
out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen);
 
// return written chars without terminating \0
return (int)idx;
}
/contrib/kolibri-libc/source/stdio/format_print.h
0,0 → 1,12
#include <stddef.h>
#include <stdarg.h>
 
typedef struct {
void (*fct)(char character, void* arg);
void* arg;
} out_fct_wrap_type;
 
typedef void (*out_fct_type)(char character, void* buffer, size_t idx, size_t maxlen);
extern void _out_buffer(char character, void* buffer, size_t idx, size_t maxlen);
extern void _out_null(char character, void* buffer, size_t idx, size_t maxlen);
extern int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const char* format, va_list va);
/contrib/kolibri-libc/source/stdio/format_scan.c
0,0 → 1,403
/*
function for format read from any source
 
Siemargl formats as http://www.cplusplus.com/reference/cstdio/scanf/, no wchar though
http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap05.html is used too
 
todo:
[characters], [^characters]
-%n nothing scanned, filled only if good result
-%d, i, u, o, x, p read similar - detect base by prefix 0 or 0x
-%a
-can overflow unsigned as signed
-radix point always '.', no LOCALEs
*/
 
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <stdarg.h>
#include "format_scan.h"
 
static int __try_parse_real(long double *real, int ch, const void *src, void *save, virtual_getc vgetc, virtual_ungetc vungetc)
// returns 1 if OK, -1 == EOF, -2 parse broken
{
int sign = 1, have_digits = 0;
long long div;
 
if (ch == '+')
{
ch = vgetc(save, src);
if (ch == EOF) return EOF;
} else
if (ch == '-')
{
sign = -1;
ch = vgetc(save, src);
if (ch == EOF) return EOF;
};
*real = 0.0;
for (;;) // mantissa before point
{
// test ch is valid
if (isdigit(ch))
{
*real = *real * 10 + ch - '0';
have_digits++;
ch = vgetc(save, src);
if (ch == EOF || isspace(ch)) break; // ok, just finish num
} else
if (ch == '.' || ch == 'E' || ch == 'e')
{
break; // ok
}
else
{
vungetc(save, ch, src);
break;
}
}
if (ch != '.' && ch != 'E' && ch != 'e') // ok, just integer part
{
*real *= sign;
if (have_digits)
return 1;
else
return -2;
}
 
if(ch == '.')
{
ch = vgetc(save, src);
div = 10; // use as divisor
for (;;) // mantissa after point
{
// test ch is valid
if (isdigit(ch))
{
*real += (double)(ch - '0') / div;
div *= 10;
have_digits++;
ch = vgetc(save, src);
if (ch == EOF || isspace(ch)) break; // ok, just finish num
} else
if (ch == 'E' || ch == 'e')
{
break; // ok
}
else
{
vungetc(save, ch, src);
break;
}
}
if (ch != 'E' && ch != 'e') // ok, real as XX.YY
{
*real *= sign;
if (have_digits)
return 1;
else
return -2;
}
}
 
ch = vgetc(save, src);
*real *= sign;
// exponent
sign = 1;
if (ch == '+')
{
ch = vgetc(save, src);
if (ch == EOF) return EOF;
} else
if (ch == '-')
{
sign = -1;
ch = vgetc(save, src);
if (ch == EOF) return EOF;
};
div = 0;
for (;;)
{
// test ch is valid
if (isdigit(ch))
{
div = div * 10 + ch - '0';
ch = vgetc(save, src);
if (ch == EOF || isspace(ch)) break; // ok, just finish num
}
else
{
vungetc(save, ch, src);
break;
}
}
div *= sign;
*real *= pow(10, div);
 
return 1;
}
 
static int __try_parse_int(long long *digit, int ch, const void *src, void *save, virtual_getc vgetc, virtual_ungetc vungetc)
{
int sign = 1, base = 10, have_digits = 0;
 
if (ch == '+')
{
ch = vgetc(save, src);
if (ch == EOF) return EOF;
} else
if (ch == '-')
{
sign = -1;
ch = vgetc(save, src);
if (ch == EOF) return EOF;
};
 
if (ch == '0') // octal or hex, read next
{
base = 8;
ch = vgetc(save, src);
if (ch == EOF || isspace(ch))
have_digits++;
else
if (ch == 'x' || ch == 'X')
{
base = 16;
ch = vgetc(save, src);
if (ch == EOF) return EOF;
}
}
*digit = 0;
for (;;)
{
// test ch is valid
if ((isdigit(ch) && base == 10) ||
(isdigit(ch) && base == 8 && ch < '8') ||
(isxdigit(ch) && base == 16))
{
if (base == 16)
{
if (ch <= '9') ch-= '0';
else
if (ch <= 'F') ch = 10 + ch - 'A';
else
ch = 10 + ch - 'a';
}
else
ch -= '0';
*digit = *digit * base + ch;
have_digits++;
ch = vgetc(save, src);
if (ch == EOF || isspace(ch)) break; // ok, just finish num
}
else if (ch == EOF || isspace(ch))
break;
else
{
vungetc(save, ch, src);
break;
}
}
*digit *= sign;
if (have_digits)
return 1;
else
return -2;
}
 
 
 
int _format_scan(const void *src, const char *fmt, va_list argp, virtual_getc vgetc, virtual_ungetc vungetc)
{
int i;
int length;
int fmt1, fmt2; // width, precision
size_t pos, posc;
const char *fmtc; // first point to %, fmtc points to specifier
int ch;
int format_flag;
int flag_long; // 2 = long double or long long int or wchar
int *point_to_n = NULL, nread = 0;
int flags; // parsed flags
int save = 0;
char *arg_str;
int *arg_int;
long *arg_long;
long long *arg_longlong;
float *arg_float;
double *arg_double;
long double *arg_longdouble;
long long digit;
long double real;
 
 
pos = 0;
while(*fmt)
{
while (*fmt && isspace(*fmt)) fmt++; // skip paces in format str
 
if (*fmt != '%') // usual char
{
ch = vgetc(&save, src);
if (ch != *fmt++) // char not match format
{
vungetc(&save, ch, src);
break;
}
pos++;
continue;
}
 
if (*(fmt + 1) == '%') // %%
{
ch = vgetc(&save, src);
if (ch != '%') // char not match format
{
vungetc(&save, ch, src);
break;
}
pos++;
fmt += 2;
continue;
}
//checking to containg format in the string
fmtc = fmt;
posc = pos;
 
flags = 0;
format_flag = 0;
flag_long = 0; // 2 = long double or long long int or wchar
 
while(*fmtc != '\0' && !format_flag) // searching end of format
{
fmtc++; posc++;
switch( *fmtc )
{
case 'a':
format_flag = 1;
flags |= flag_unsigned;
break;
case 'c': case 'd': case 'i': case 'e': case 'f': case 'g': case 's': case 'n':
format_flag = 1;
break;
case 'l':
flag_long = flag_long ? 2 : 1; // ll.eq.L
break;
case 'L':
flag_long = 2;
break;
case 'o': case 'u': case 'x': case 'p':
format_flag = 1;
flags |= flag_unsigned;
break;
case '*': case '.': // just skip
break;
default:
if(isdigit(*fmtc)) break;
goto exit_me; // non format char found - user error
}
}
 
if (format_flag == 0)
{
goto exit_me; // format char not found - user error
}
 
fmt1 = 0;
fmt2 = 0;
if (posc - pos > 1) // try to read width, precision
{
fmt++;
for(i = pos + 1; i < posc; i++)
{
switch(*fmt)
{
case '0':
if(fmt1 == 0 && (flags & flag_point) == 0) flags |= flag_lead_zeros;
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
if ((flags & flag_point) == 0)
fmt1 = fmt1 * 10 + (*fmt -'0');
else
fmt2 = fmt2 * 10 + (*fmt -'0');
break;
case '*': // ignoring
break;
case '.':
flags |= flag_point;
break;
case 'l': case 'L': // valid chars - skip
break;
default: // must be error
goto exit_me; // format char not found - user error
}
fmt++;
}
}
 
// do real work - format arguments values
// skip input spaces
do {
ch = vgetc(&save, src);
if (ch == EOF) goto exit_me;
} while (isspace(ch));
 
switch(*fmtc)
{
case 'n':
point_to_n = va_arg(argp, int*);
vungetc(&save, ch, src);
break;
case 'c': // read width chars, ever spaces
arg_str = va_arg(argp, char*);
if (fmt1 == 0) length = 1;
else length = fmt1;
for (i = 0; i < length;)
{
*arg_str++ = ch; i++;
ch = vgetc(&save, src);
if (ch == EOF) break;
}
if (i < length) goto exit_me; // not enough chars
break;
case 's':
arg_str = va_arg(argp, char*);
if (fmt1 == 0) length = 4095; // max string scan 4096
else length = fmt1;
for (i = 0; i < length; i++)
{
*arg_str++ = ch;
ch = vgetc(&save, src);
if (ch == EOF || isspace(ch)) break; // ok, just finish string
}
*arg_str++ = '\0';
break;
case 'd': case 'i': case 'u':
case 'o': case 'p': case 'x':
i = __try_parse_int(&digit, ch, src, &save, vgetc, vungetc);
if (i < 0) goto exit_me;
 
if (flag_long == 0) { arg_int = va_arg(argp, int*); *arg_int = (int)digit; } else
if (flag_long == 1) { arg_long = va_arg(argp, long*); *arg_long = (long)digit; } else
if (flag_long == 2) { arg_longlong = va_arg(argp, long long*); *arg_longlong = digit; }
break;
case 'a': case 'A': case 'f': case 'F':
case 'e': case 'E':
case 'g': case 'G':
i = __try_parse_real(&real, ch, src, &save, vgetc, vungetc);
if (i < 0) goto exit_me;
 
if (flag_long == 0) { arg_float = va_arg(argp, float*); *arg_float = (float)real; } else
if (flag_long == 1) { arg_double = va_arg(argp, double*); *arg_double = (double)real; } else
if (flag_long == 2) { arg_longdouble = va_arg(argp, long double*); *arg_longdouble = real; }
break;
}
 
fmt = fmtc + 1;
nread++;
}
exit_me:
if (point_to_n) *point_to_n = nread;
return nread;
}
/contrib/kolibri-libc/source/stdio/format_scan.h
0,0 → 1,20
#include <stdio.h>
 
typedef int (*virtual_getc)(void *sp, const void *obj);
typedef void (*virtual_ungetc)(void *sp, int c, const void *obj);
 
enum flags_t
{
flag_unsigned = 0x02,
flag_register = 0x04,
flag_plus = 0x08,
flag_left_just = 0x10,
flag_lead_zeros = 0x20,
flag_space_plus = 0x40,
flag_hash_sign = 0x80,
flag_point = 0x100
};
 
extern char *__scanf_buffer;
 
int _format_scan(const void *src, const char *fmt, va_list argp, virtual_getc vgetc, virtual_ungetc vungetc);
/contrib/kolibri-libc/source/stdio/fputc.c
0,0 → 1,9
#include <stdio.h>
 
int fputc(int sym, FILE *stream)
{
if(!fwrite(&sym, sizeof(char), 1, stream)){
return EOF;
}
return sym;
}
/contrib/kolibri-libc/source/stdio/fputs.c
0,0 → 1,10
#include <stdio.h>
#include <string.h>
 
int fputs(const char *str, FILE *stream){
int s_code;
for(int i=0; i<strlen(str) && s_code!=EOF; i++){
s_code = fputc(str[i], stream);
}
return s_code;
}
/contrib/kolibri-libc/source/stdio/fread.c
0,0 → 1,16
#include <stdio.h>
 
size_t fread(void *restrict ptr, size_t size, size_t nmemb, FILE *restrict stream) {
unsigned bytes_read = 0;
unsigned bytes_count = size * nmemb;
_ksys_file_read_file(stream->name, stream->position, bytes_count, ptr, &bytes_read);
stream->position += bytes_read;
ksys_bdfe_t info;
// TODO: Handle _ksys_file_get_info error somehow
if (!_ksys_file_get_info(stream->name, &info)) {
if (stream->position >= info.size) {
stream->eof = 1;
}
}
return bytes_read / size;
}
/contrib/kolibri-libc/source/stdio/freopen.c
0,0 → 1,36
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
FILE *freopen(const char *restrict _name, const char *restrict _mode, FILE *restrict out) {
ksys_bdfe_t info;
if (_ksys_file_get_info(_name, &info)) {
return NULL;
}
 
if (!out) {
return NULL;
}
 
out->name = strdup(_name);
out->position = 0;
out->error = 0;
out->eof = 0;
out->kind = 0;
out->orientation = 0;
out->mode = 0;
 
if (strchr(_mode, 'b')) { out->mode |= _STDIO_F_B; }
if (strchr(_mode, 'x')) { out->mode |= _STDIO_F_X; }
if (strchr(_mode, 'a')) { out->mode |= _STDIO_F_A; }
if (strchr(_mode, 'r')) { out->mode |= _STDIO_F_R; }
if (strchr(_mode, 'w')) { out->mode |= _STDIO_F_W; }
if (strchr(_mode, '+')) { out->mode |= _STDIO_F_R | _STDIO_F_W; }
 
if (out->mode & _STDIO_F_A) {
out->position = info.size;
out->append_offset = info.size;
}
 
return out;
}
/contrib/kolibri-libc/source/stdio/fscanf.c
0,0 → 1,13
#include <stdio.h>
 
int fscanf(FILE* stream, const char* format, ...)
{
va_list arg;
int n;
va_start(arg, format);
n = vfscanf(stream, format, arg);
va_end(arg);
return n;
}
 
 
/contrib/kolibri-libc/source/stdio/fseek.c
0,0 → 1,17
#include <stdio.h>
#include <ksys.h>
 
int fseek(FILE *stream, long int offset, int whence) {
if (whence == SEEK_SET) {
stream->position = offset;
} else if (whence == SEEK_CUR) {
stream->position += offset;
} else if (whence == SEEK_END) {
ksys_bdfe_t info;
if (_ksys_file_get_info(stream->name, &info)) {
return -1;
}
stream->position = info.size + offset;
}
stream->eof = 0;
}
/contrib/kolibri-libc/source/stdio/fsetpos.c
0,0 → 1,7
#include <stdio.h>
 
int fsetpos(FILE *stream, const fpos_t *pos) {
stream->position = *pos;
stream->eof = 0;
return 0;
}
/contrib/kolibri-libc/source/stdio/ftell.c
0,0 → 1,5
#include <stdio.h>
 
long int ftell(FILE *stream) {
return stream->position;
}
/contrib/kolibri-libc/source/stdio/fwrite.c
0,0 → 1,16
#include <stdio.h>
 
size_t fwrite(const void * restrict ptr,size_t size, size_t nmemb,FILE * restrict stream) {
unsigned bytes_written = 0;
unsigned bytes_count = size * nmemb;
_ksys_file_write_file(stream->name, stream->position, bytes_count, ptr, &bytes_written);
stream->position += bytes_written;
ksys_bdfe_t info;
// TODO: Handle _ksys_file_get_info error somehow
if (!_ksys_file_get_info(stream->name, &info)) {
if (stream->position >= info.size) {
stream->eof = 1;
}
}
return bytes_written / size;
}
/contrib/kolibri-libc/source/stdio/getchar.c
0,0 → 1,10
#include <stdio.h>
#include "conio.h"
 
int getchar(void) {
int c = __con_getch();
if (c == 0) {
c = EOF;
}
return c;
}
/contrib/kolibri-libc/source/stdio/gets.c
0,0 → 1,15
#include <stdio.h>
#include <string.h>
#include "conio.h"
#include <errno.h>
 
char *gets(char* str)
{
__con_init();
if(__con_gets(str, 4096)==NULL){
errno = EIO;
return NULL;
}
str[strlen(str)-1]='\0';
return str;
}
/contrib/kolibri-libc/source/stdio/perror.c
0,0 → 1,5
#include <stdio.h>
 
void perror(const char *s) {
printf("%s: It's some error, maybe...", s);
}
/contrib/kolibri-libc/source/stdio/printf.c
0,0 → 1,13
/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */
 
#include <stdio.h>
#include <stdlib.h>
 
#include "format_print.h"
 
int printf(const char *format, ...)
{
va_list arg;
va_start(arg, format);
return vprintf(format, arg);
}
/contrib/kolibri-libc/source/stdio/puts.c
0,0 → 1,13
/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */
 
#include <stdio.h>
#include <string.h>
#include "conio.h"
 
int puts(const char *str)
{
__con_init();
__con_write_asciiz(str);
__con_write_asciiz("\n");
return strlen(str);
}
/contrib/kolibri-libc/source/stdio/remove.c
0,0 → 1,6
#include <stdio.h>
#include <ksys.h>
 
int remove(const char *name) {
return _ksys_file_delete(name);
}
/contrib/kolibri-libc/source/stdio/rename.c
0,0 → 1,6
#include <stdio.h>
#include <ksys.h>
 
int rename(const char *name, const char *new_name) {
return _ksys_file_rename(name, new_name);
}
/contrib/kolibri-libc/source/stdio/rewind.c
0,0 → 1,5
#include <stdio.h>
 
void rewind(FILE *stream) {
stream->position = 0;
}
/contrib/kolibri-libc/source/stdio/scanf.c
0,0 → 1,20
#include "format_scan.h"
#include <stdlib.h>
 
int scanf ( const char * format, ...)
{
va_list arg;
int n;
va_start(arg, format);
 
if(__scanf_buffer == NULL) __scanf_buffer = malloc(4096);
if(__scanf_buffer == NULL) return -3;
 
*__scanf_buffer = 0;
n = vscanf(format, arg);
 
va_end(arg);
return n;
}
 
 
/contrib/kolibri-libc/source/stdio/setbuf.c
0,0 → 1,5
#include <stdio.h>
 
void setbuf(FILE *restrict stream, char *restrict buf) {
return;
}
/contrib/kolibri-libc/source/stdio/setvbuf.c
0,0 → 1,5
#include <stdio.h>
 
int setvbuf(FILE *restrict stream, char *restrict buf, int mode, size_t size) {
return 0;
}
/contrib/kolibri-libc/source/stdio/snprintf.c
0,0 → 1,12
/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */
 
#include "format_print.h"
 
int snprintf(char* buffer, size_t count, const char* format, ...)
{
va_list va;
va_start(va, format);
const int ret = _vsnprintf(_out_buffer, buffer, count, format, va);
va_end(va);
return ret;
}
/contrib/kolibri-libc/source/stdio/sprintf.c
0,0 → 1,12
/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */
 
#include "format_print.h"
 
int sprintf(char* buffer, const char* format, ...)
{
va_list va;
va_start(va, format);
const int ret = _vsnprintf(_out_buffer, buffer, (size_t)-1, format, va);
va_end(va);
return ret;
}
/contrib/kolibri-libc/source/stdio/sscanf.c
0,0 → 1,12
#include <stdio.h>
 
int sscanf(const char * s, const char * format, ...)
{
va_list arg;
int n;
va_start(arg, format);
n = vsscanf(s, format, arg);
va_end(arg);
return n;
}
 
/contrib/kolibri-libc/source/stdio/tmpfile.c
0,0 → 1,11
#include <stdio.h>
 
FILE *tmpfile(void) {
char name[FILENAME_MAX + 1];
 
if (!tmpnam(name)) {
return NULL;
}
 
return fopen(name, "wb+");
}
/contrib/kolibri-libc/source/stdio/tmpnam.c
0,0 → 1,16
#include <stdio.h>
#include <ksys.h>
#include <string.h>
 
static char buf[FILENAME_MAX + 1];
static int static_index = 0;
 
char *tmpnam(char *name) {
ksys_proc_table_t table;
_ksys_process_info(&table, -1);
 
char *out = name ? name : buf;
// PID is also unique for each thread
sprintf(out, "/tmp0/1/%x_%x.tmp", table.pid, static_index++);
return out;
}
/contrib/kolibri-libc/source/stdio/vfscanf.c
0,0 → 1,55
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include "format_scan.h"
#include <errno.h>
 
// non standard realization - support for virtually change ONLY ONE char
 
static int __ungetc_emu(int c, FILE* stream)
{
unsigned res;
if(stream){
errno = EINVAL;
return EOF;
}
if ((stream->mode & 3) != _STDIO_F_R && (stream->mode & _STDIO_F_A) == 0){
errno = EACCES;
return EOF;
}
ksys_bdfe_t *file_info = malloc(sizeof(ksys_bdfe_t));
if(file_info==NULL){
errno = ENOMEM;
return EOF;
}
if(!_ksys_file_get_info(stream->name, file_info)){
errno = ENFILE;
return EOF;
}
if (stream->position > file_info->size || stream->position == 0 || c == EOF || stream->__ungetc_emu_buff != EOF){
errno = EOF;
return EOF;
}
stream->__ungetc_emu_buff = c;
stream->position --;
return c;
}
 
static int __virtual_getc_file(void *sp, const void *obj)
{
FILE *f = (FILE *)obj;
int ch = fgetc(f);
return ch;
}
 
static void __virtual_ungetc_file(void *sp, int c, const void *obj)
{
FILE *f = (FILE *)obj;
if (f) __ungetc_emu(c, f);
}
 
int vfscanf(FILE * stream, const char * format, va_list arg)
{
return _format_scan(stream, format, arg, &__virtual_getc_file, &__virtual_ungetc_file);
}
/contrib/kolibri-libc/source/stdio/vprintf.c
0,0 → 1,18
/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */
 
#include <stdio.h>
#include <stdlib.h>
 
#include "conio.h"
#include "format_print.h"
 
int vprintf ( const char * format, va_list arg )
{
int len = 0;
char s[4096];
 
__con_init();
len = vsnprintf(s, 4096, format, arg);
__con_write_string(s, len);
return(len);
}
/contrib/kolibri-libc/source/stdio/vscanf.c
0,0 → 1,44
#include "format_scan.h"
#include <string.h>
 
char *__scanf_buffer=NULL;
 
static int __virtual_getc_con(void *sp, const void *obj)
// get next chat from string obj, save point is ptr to string char ptr
{
int ch;
const char**spc= (const char**)sp;
if (!spc) return EOF; // error
if (!*spc) *spc = __scanf_buffer; // first call, init savepoint
 
while (!**spc) // need to read more
{
if(!gets(__scanf_buffer)) return EOF;
*spc = __scanf_buffer;
strcat(__scanf_buffer,"\n"); // imitate delimiter
}
if (**spc == 26 || **spc == 3) // ^C ^Z end of scan, clear buffer
{
*spc = __scanf_buffer;
*__scanf_buffer = 0;
return EOF; // ^C ^Z
}
 
ch = **spc; (*spc)++ ;
return ch;
}
 
static void __virtual_ungetc_con(void *sp, int c, const void *obj)
// if can, one step back savepoint in s
{
const char**spc= (const char**)sp;
 
if (spc && *spc > __scanf_buffer) (*spc)--;
//printf("Ungetc '%c'[%d];", c, c);
}
 
 
int vscanf(const char * format, va_list arg)
{
return _format_scan(NULL, format, arg, &__virtual_getc_con, &__virtual_ungetc_con);
}
/contrib/kolibri-libc/source/stdio/vsnprintf.c
0,0 → 1,6
#include "format_print.h"
 
int vsnprintf(char* buffer, size_t count, const char* format, va_list va)
{
return _vsnprintf(_out_buffer, buffer, count, format, va);
}
/contrib/kolibri-libc/source/stdio/vsscanf.c
0,0 → 1,32
#include "format_scan.h"
 
static int __virtual_getc_str(void *sp, const void *obj)
// get next chat from string obj, save point is ptr to string char ptr
{
int ch;
const char *s = (const char *)obj;
const char**spc= (const char**)sp;
if (!s || !spc) return EOF; // error
 
if (!*spc) *spc = s; // first call, init savepoint
 
if (!**spc) return EOF; // EOS
 
ch = **spc; (*spc)++ ;
 
return ch;
}
 
void __virtual_ungetc_str(void *sp, int c, const void *obj)
// if can, one step back savepoint in s
{
const char *s = (const char *)obj;
const char**spc= (const char**)sp;
 
if (s && spc && *spc > s) (*spc)--;
}
 
int vsscanf(const char * s, const char * format, va_list arg)
{
return _format_scan(s, format, arg, &__virtual_getc_str, &__virtual_ungetc_str);
};