mirror of
				https://gitlab.com/sortix/sortix.git
				synced 2023-02-13 20:55:38 -05:00 
			
		
		
		
	Add cbprintf(3) and vcbprintf(3).
Thanks to Owen Shepherd of the Public Domain C Library for helping design and formalize these interfaces.
This commit is contained in:
		
							parent
							
								
									2dffa408ad
								
							
						
					
					
						commit
						ec7e0cc9a6
					
				
					 10 changed files with 98 additions and 55 deletions
				
			
		| 
						 | 
				
			
			@ -153,7 +153,7 @@ void Print(const char* format, ...)
 | 
			
		|||
{
 | 
			
		||||
	va_list ap;
 | 
			
		||||
	va_start(ap, format);
 | 
			
		||||
	vprintf_callback(PrintCallback, NULL, format, ap);
 | 
			
		||||
	vcbprintf(NULL, PrintCallback, format, ap);
 | 
			
		||||
	va_end(ap);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,6 +28,7 @@
 | 
			
		|||
#include <stdarg.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
namespace Sortix {
 | 
			
		||||
| 
						 | 
				
			
			@ -95,15 +96,20 @@ inline size_t PrintF(const char* format, ...)
 | 
			
		|||
{
 | 
			
		||||
	va_list list;
 | 
			
		||||
	va_start(list, format);
 | 
			
		||||
	size_t result = vprintf_callback(device_callback, device_pointer, format, list);
 | 
			
		||||
	int result = vcbprintf(device_pointer, device_callback, format, list);
 | 
			
		||||
	va_end(list);
 | 
			
		||||
	return result;
 | 
			
		||||
	if ( result < 0 )
 | 
			
		||||
		return SIZE_MAX;
 | 
			
		||||
	return (size_t) result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__((format(printf, 1, 0)))
 | 
			
		||||
inline size_t PrintFV(const char* format, va_list list)
 | 
			
		||||
{
 | 
			
		||||
	return vprintf_callback(device_callback, device_pointer, format, list);
 | 
			
		||||
	int result = vcbprintf(device_pointer, device_callback, format, list);
 | 
			
		||||
	if ( result < 0 )
 | 
			
		||||
		return SIZE_MAX;
 | 
			
		||||
	return (size_t) result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace Log
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,6 +67,7 @@ signal/sigorset.o \
 | 
			
		|||
stdio/asprintf.o \
 | 
			
		||||
stdio/clearerr.o \
 | 
			
		||||
stdio/clearerr_unlocked.o \
 | 
			
		||||
stdio/cbprintf.o \
 | 
			
		||||
stdio/dprintf.o \
 | 
			
		||||
stdio/fbufsize.o \
 | 
			
		||||
stdio/fbufsize_unlocked.o \
 | 
			
		||||
| 
						 | 
				
			
			@ -142,11 +143,11 @@ stdio/sscanf.o \
 | 
			
		|||
stdio/ungetc.o \
 | 
			
		||||
stdio/ungetc_unlocked.o \
 | 
			
		||||
stdio/vasprintf.o \
 | 
			
		||||
stdio/vcbprintf.o \
 | 
			
		||||
stdio/vdprintf.o \
 | 
			
		||||
stdio/vfprintf_unlocked.o \
 | 
			
		||||
stdio/vfscanf.o \
 | 
			
		||||
stdio/vfscanf_unlocked.o \
 | 
			
		||||
stdio/vprintf_callback.o \
 | 
			
		||||
stdio/vscanf_callback.o \
 | 
			
		||||
stdio/vsnprintf.o \
 | 
			
		||||
stdio/vsprintf.o \
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -320,12 +320,11 @@ void fpurge_unlocked(FILE* fp);
 | 
			
		|||
size_t fpending_unlocked(FILE* fp);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* The Sortix backends for *printf and *scanf. */
 | 
			
		||||
/* The backends for printf and scanf. */
 | 
			
		||||
#if __USE_SORTIX
 | 
			
		||||
size_t vprintf_callback(size_t (*callback)(void*, const char*, size_t),
 | 
			
		||||
                        void* user,
 | 
			
		||||
                        const char* __restrict format,
 | 
			
		||||
                        __gnuc_va_list ap)
 | 
			
		||||
int cbprintf(void*, size_t (*)(void*, const char*, size_t), const char*, ...)
 | 
			
		||||
	__attribute__((__format__ (printf, 3, 4)));
 | 
			
		||||
int vcbprintf(void*, size_t (*)(void*, const char*, size_t), const char*, __gnuc_va_list ap)
 | 
			
		||||
	__attribute__((__format__ (printf, 3, 0)));
 | 
			
		||||
int vscanf_callback(void* fp,
 | 
			
		||||
                    int (*fgetc)(void*),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										39
									
								
								libc/stdio/cbprintf.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								libc/stdio/cbprintf.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,39 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2014.
 | 
			
		||||
 | 
			
		||||
    This file is part of the Sortix C Library.
 | 
			
		||||
 | 
			
		||||
    The Sortix C Library is free software: you can redistribute it and/or modify
 | 
			
		||||
    it under the terms of the GNU Lesser General Public License as published by
 | 
			
		||||
    the Free Software Foundation, either version 3 of the License, or (at your
 | 
			
		||||
    option) any later version.
 | 
			
		||||
 | 
			
		||||
    The Sortix C Library is distributed in the hope that it will be useful, but
 | 
			
		||||
    WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 | 
			
		||||
    or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
 | 
			
		||||
    License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    stdio/cbprintf.cpp
 | 
			
		||||
    Formats text and outputs it via callback functions.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
extern "C"
 | 
			
		||||
int cbprintf(void* user,
 | 
			
		||||
             size_t (*callback)(void*, const char*, size_t),
 | 
			
		||||
             const char* format,
 | 
			
		||||
             ...)
 | 
			
		||||
{
 | 
			
		||||
	va_list ap;
 | 
			
		||||
	va_start(ap, format);
 | 
			
		||||
	int result = vcbprintf(user, callback, format, ap);
 | 
			
		||||
	va_end(ap);
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -72,9 +72,9 @@ int vasprintf(char** restrict result_ptr,
 | 
			
		|||
	state.string_used = 0;
 | 
			
		||||
	if ( !(state.string = (char*) malloc(state.string_length * sizeof(char))) )
 | 
			
		||||
		return *result_ptr = NULL, -1;
 | 
			
		||||
	vprintf_callback(vasprintf_callback, &state, format, list);
 | 
			
		||||
	int result = vcbprintf(&state, vasprintf_callback, format, list);
 | 
			
		||||
	if ( !state.string )
 | 
			
		||||
		return *result_ptr = NULL, -1;
 | 
			
		||||
	state.string[state.string_used] = '\0';
 | 
			
		||||
	return *result_ptr = state.string, (int) state.string_used;
 | 
			
		||||
	return *result_ptr = state.string, result;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,15 +17,13 @@
 | 
			
		|||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    stdio/vprintf_callback.cpp
 | 
			
		||||
    Provides printf formatting functions that uses callbacks.
 | 
			
		||||
    stdio/vcbprintf.cpp
 | 
			
		||||
    Formats text and outputs it via callback functions.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
// Number of bugs seemingly unrelated bugs that have been traced to here:
 | 
			
		||||
// Countless + 2
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -51,19 +49,19 @@ static size_t noop_callback(void*, const char*, size_t amount)
 | 
			
		|||
	return amount;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
size_t callback_character(size_t (*callback)(void*, const char*, size_t),
 | 
			
		||||
                          void* user,
 | 
			
		||||
static inline
 | 
			
		||||
size_t callback_character(void* user,
 | 
			
		||||
                          size_t (*callback)(void*, const char*, size_t),
 | 
			
		||||
                          char c)
 | 
			
		||||
{
 | 
			
		||||
	return callback(user, &c, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "C"
 | 
			
		||||
size_t vprintf_callback(size_t (*callback)(void*, const char*, size_t),
 | 
			
		||||
                        void* user,
 | 
			
		||||
                        const char* restrict format,
 | 
			
		||||
                        va_list parameters)
 | 
			
		||||
int vcbprintf(void* user,
 | 
			
		||||
              size_t (*callback)(void*, const char*, size_t),
 | 
			
		||||
              const char* format,
 | 
			
		||||
              va_list parameters)
 | 
			
		||||
{
 | 
			
		||||
	if ( !callback )
 | 
			
		||||
		callback = noop_callback;
 | 
			
		||||
| 
						 | 
				
			
			@ -80,7 +78,7 @@ size_t vprintf_callback(size_t (*callback)(void*, const char*, size_t),
 | 
			
		|||
			while ( format[amount] && format[amount] != '%' )
 | 
			
		||||
				amount++;
 | 
			
		||||
			if ( callback(user, format, amount) != amount )
 | 
			
		||||
				return SIZE_MAX;
 | 
			
		||||
				return -1;
 | 
			
		||||
			format += amount;
 | 
			
		||||
			written += amount;
 | 
			
		||||
			continue;
 | 
			
		||||
| 
						 | 
				
			
			@ -311,32 +309,32 @@ size_t vprintf_callback(size_t (*callback)(void*, const char*, size_t),
 | 
			
		|||
 | 
			
		||||
			if ( use_left_pad )
 | 
			
		||||
				for ( size_t i = length_with_precision; i < abs_field_width; i++ )
 | 
			
		||||
					if ( callback_character(callback, user, ' ') != 1 )
 | 
			
		||||
						return SIZE_MAX;
 | 
			
		||||
					if ( callback_character(user, callback, ' ') != 1 )
 | 
			
		||||
						return -1;
 | 
			
		||||
					else
 | 
			
		||||
						written++;
 | 
			
		||||
			if ( callback(user, prefix, prefix_length) != prefix_length )
 | 
			
		||||
				return SIZE_MAX;
 | 
			
		||||
				return -1;
 | 
			
		||||
			written += prefix_length;
 | 
			
		||||
			if ( use_zero_pad )
 | 
			
		||||
				for ( size_t i = normal_length; i < abs_field_width; i++ )
 | 
			
		||||
					if ( callback_character(callback, user, '0') != 1 )
 | 
			
		||||
						return SIZE_MAX;
 | 
			
		||||
					if ( callback_character(user, callback, '0') != 1 )
 | 
			
		||||
						return -1;
 | 
			
		||||
					else
 | 
			
		||||
						written++;
 | 
			
		||||
			if ( use_precision )
 | 
			
		||||
				for ( size_t i = digits_length; i < precision; i++ )
 | 
			
		||||
					if ( callback_character(callback, user, '0') != 1 )
 | 
			
		||||
						return SIZE_MAX;
 | 
			
		||||
					if ( callback_character(user, callback, '0') != 1 )
 | 
			
		||||
						return -1;
 | 
			
		||||
					else
 | 
			
		||||
						written++;
 | 
			
		||||
			if ( callback(user, output, output_length) != output_length )
 | 
			
		||||
				return SIZE_MAX;
 | 
			
		||||
				return -1;
 | 
			
		||||
			written += output_length;
 | 
			
		||||
			if ( use_right_pad )
 | 
			
		||||
				for ( size_t i = length_with_precision; i < abs_field_width; i++ )
 | 
			
		||||
					if ( callback_character(callback, user, ' ') != 1 )
 | 
			
		||||
						return SIZE_MAX;
 | 
			
		||||
					if ( callback_character(user, callback, ' ') != 1 )
 | 
			
		||||
						return -1;
 | 
			
		||||
					else
 | 
			
		||||
						written++;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -379,19 +377,19 @@ size_t vprintf_callback(size_t (*callback)(void*, const char*, size_t),
 | 
			
		|||
 | 
			
		||||
			if ( !field_width_is_negative && 1 < abs_field_width )
 | 
			
		||||
				for ( size_t i = 1; i < abs_field_width; i++ )
 | 
			
		||||
					if ( callback_character(callback, user, ' ') != 1 )
 | 
			
		||||
						return SIZE_MAX;
 | 
			
		||||
					if ( callback_character(user, callback, ' ') != 1 )
 | 
			
		||||
						return -1;
 | 
			
		||||
					else
 | 
			
		||||
						written++;
 | 
			
		||||
 | 
			
		||||
			if ( callback(user, &c, 1) != 1 )
 | 
			
		||||
				return SIZE_MAX;
 | 
			
		||||
				return -1;
 | 
			
		||||
			written++;
 | 
			
		||||
 | 
			
		||||
			if ( field_width_is_negative && 1 < abs_field_width )
 | 
			
		||||
				for ( size_t i = 1; i < abs_field_width; i++ )
 | 
			
		||||
					if ( callback_character(callback, user, ' ') != 1 )
 | 
			
		||||
						return SIZE_MAX;
 | 
			
		||||
					if ( callback_character(user, callback, ' ') != 1 )
 | 
			
		||||
						return -1;
 | 
			
		||||
					else
 | 
			
		||||
						written++;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -422,19 +420,19 @@ size_t vprintf_callback(size_t (*callback)(void*, const char*, size_t),
 | 
			
		|||
 | 
			
		||||
			if ( !field_width_is_negative && string_length < abs_field_width )
 | 
			
		||||
				for ( size_t i = string_length; i < abs_field_width; i++ )
 | 
			
		||||
					if ( callback_character(callback, user, ' ') != 1 )
 | 
			
		||||
						return SIZE_MAX;
 | 
			
		||||
					if ( callback_character(user, callback, ' ') != 1 )
 | 
			
		||||
						return -1;
 | 
			
		||||
					else
 | 
			
		||||
						written++;
 | 
			
		||||
 | 
			
		||||
			if ( callback(user, string, string_length) != string_length )
 | 
			
		||||
				return SIZE_MAX;
 | 
			
		||||
				return -1;
 | 
			
		||||
			written += string_length;
 | 
			
		||||
 | 
			
		||||
			if ( field_width_is_negative && string_length < abs_field_width )
 | 
			
		||||
				for ( size_t i = string_length; i < abs_field_width; i++ )
 | 
			
		||||
					if ( callback_character(callback, user, ' ') != 1 )
 | 
			
		||||
						return SIZE_MAX;
 | 
			
		||||
					if ( callback_character(user, callback, ' ') != 1 )
 | 
			
		||||
						return -1;
 | 
			
		||||
					else
 | 
			
		||||
						written++;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -464,5 +462,8 @@ size_t vprintf_callback(size_t (*callback)(void*, const char*, size_t),
 | 
			
		|||
			goto incomprehensible_conversion;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ( INT_MAX < written )
 | 
			
		||||
		return INT_MAX;
 | 
			
		||||
 | 
			
		||||
	return written;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2013.
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2013, 2014.
 | 
			
		||||
 | 
			
		||||
    This file is part of the Sortix C Library.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -30,10 +30,10 @@
 | 
			
		|||
 | 
			
		||||
static size_t write_callback(void* user, const char* string, size_t stringlen)
 | 
			
		||||
{
 | 
			
		||||
	return writeall((int) (uintptr_t) user, string, stringlen * sizeof(char));
 | 
			
		||||
	return writeall((int) (uintptr_t) user, string, stringlen);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "C" int vdprintf(int fd, const char* restrict format, va_list list)
 | 
			
		||||
{
 | 
			
		||||
	return vprintf_callback(write_callback, (void*) (uintptr_t) fd, format, list);
 | 
			
		||||
	return vcbprintf((void*) (uintptr_t) fd, write_callback, format, list);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,8 +38,5 @@ int vfprintf_unlocked(FILE* fp, const char* restrict format, va_list list)
 | 
			
		|||
	if ( !(fp->flags & _FILE_WRITABLE) )
 | 
			
		||||
		return errno = EBADF, fp->flags |= _FILE_STATUS_ERROR, EOF;
 | 
			
		||||
 | 
			
		||||
	size_t result = vprintf_callback(FileWriteCallback, fp, format, list);
 | 
			
		||||
	if ( result == SIZE_MAX )
 | 
			
		||||
		return -1;
 | 
			
		||||
	return (int) result;
 | 
			
		||||
	return vcbprintf(fp, FileWriteCallback, format, list);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013.
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014.
 | 
			
		||||
 | 
			
		||||
    This file is part of the Sortix C Library.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -58,8 +58,8 @@ int vsnprintf(char* restrict str, size_t size, const char* restrict format,
 | 
			
		|||
	info.size = size ? size-1 : 0;
 | 
			
		||||
	info.produced = 0;
 | 
			
		||||
	info.written = 0;
 | 
			
		||||
	vprintf_callback(StringPrintCallback, &info, format, list);
 | 
			
		||||
	int result = vcbprintf(&info, StringPrintCallback, format, list);
 | 
			
		||||
	if ( size )
 | 
			
		||||
		info.str[info.written] = '\0';
 | 
			
		||||
	return (int) info.produced;
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue