Skip to content

Commit c0840d5

Browse files
committed
Added asprintf and fprintf along with ti_sprintf macros
1 parent 5833aa0 commit c0840d5

File tree

8 files changed

+171
-36
lines changed

8 files changed

+171
-36
lines changed

src/ce/include/ti_sprintf.h

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#ifndef TI_SPRINTF_H
2+
#define TI_SPRINTF_H
3+
4+
#include <stddef.h>
5+
#include <stdlib.h>
6+
7+
#ifdef __cplusplus
8+
extern "C" {
9+
#endif
10+
11+
/**
12+
* @brief C89 `sprintf`. `long` arguments and width specifiers are unsupported.
13+
* @note `%s` will write up to 255 characters.
14+
*/
15+
int ti_sprintf(
16+
char *__restrict buffer, const char *__restrict format, ...
17+
) __attribute__((format (__printf__, 2, 3)));
18+
19+
/**
20+
* @brief Returns an empty string if the output from sprintf does not fit.
21+
* @warning `__VA_ARGS__` is evaluated twice.
22+
* @note Undefined behaviour if the output is longer than ~258000 characters.
23+
*/
24+
#define ti_snprintf(buffer, count, ...)\
25+
({\
26+
char * const __buffer = buffer;\
27+
const int __count = count;\
28+
int __ret = -1;\
29+
int __str_len = ti_sprintf((char*)0xFC1000, __VA_ARGS__);\
30+
if (__buffer == NULL || __count == 0) {\
31+
__ret = __str_len;\
32+
} else if ((size_t)__str_len > __count) {\
33+
*__buffer = '\0'; /* won't fit or invalid formatting */\
34+
} else {\
35+
__ret = ti_sprintf(__buffer, __VA_ARGS__);\
36+
}\
37+
__ret;\
38+
})
39+
40+
/**
41+
* @brief Allocates a null terminated string containing the output of sprintf.
42+
* The returned pointer shall be deallocated with `free`.
43+
* @warning `__VA_ARGS__` is evaluated twice.
44+
* @note Undefined behaviour if the output is longer than ~258000 characters.
45+
*/
46+
#define ti_asprintf(p_buffer, ...)\
47+
({\
48+
char** const __p_buffer = p_buffer;\
49+
int __ret = -1;\
50+
int __str_len = ti_sprintf((char*)0xFC1000, __VA_ARGS__);\
51+
if (__str_len >= 0) {\
52+
size_t __buffer_size = (size_t)__str_len + 1;\
53+
*__p_buffer = (char*)malloc(__buffer_size);\
54+
if (*__p_buffer != NULL) {\
55+
__ret = ti_sprintf(*__p_buffer, __VA_ARGS__);\
56+
}\
57+
}\
58+
__ret;\
59+
})
60+
61+
#ifdef __cplusplus
62+
}
63+
#endif
64+
65+
#endif /* TI_SPRINTF_H */
Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
assume adl=1
2-
3-
section .text
4-
5-
; to reduce binary size (or performance in the case of sprintf), ti's routines
6-
; can be linked instead of the toolchain's routines
7-
8-
public __ti_sprintf
9-
__ti_sprintf := 0000BCh
1+
assume adl=1
2+
3+
section .text
4+
5+
; to reduce binary size (or performance in the case of sprintf), ti's routines
6+
; can be linked instead of the toolchain's routines
7+
8+
public _ti_sprintf
9+
_ti_sprintf := 0000BCh

src/libc/errno_str.c

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@
22
#include <errno.h>
33
#include <stdio.h>
44
#include <string.h>
5-
6-
int _ti_sprintf(
7-
char *__restrict buffer, const char *__restrict format, ...
8-
) __attribute__ ((format (__printf__, 2, 3)));
5+
#include <ti_sprintf.h>
96

107
static char const * const errno_strings[] = {
118
"no error",
@@ -32,7 +29,7 @@ static_assert(
3229

3330
char* strerror(int errnum) {
3431
if ((unsigned int)errnum >= errno_strings_count) {
35-
_ti_sprintf(&(unknown_errno_string[unknown_errno_number_offset]), "%d", errnum);
32+
ti_sprintf(&(unknown_errno_string[unknown_errno_number_offset]), "%d", errnum);
3633
return (char*)unknown_errno_string;
3734
}
3835
return (char*)errno_strings[errnum];
@@ -48,8 +45,7 @@ size_t strerrorlen_s(errno_t errnum) {
4845
void perror(const char *str) {
4946
if (str != NULL && *str != '\0') {
5047
fputs(str, stderr);
51-
fputc(':', stderr);
52-
fputc(' ', stderr);
48+
fputs(": ", stderr);
5349
}
5450
fputs(strerror(errno), stderr);
5551
fputc('\n', stderr);

src/libc/include/stdio.h

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -89,20 +89,29 @@ int printf(const char *__restrict format, ...)
8989
int vprintf(const char *__restrict format, va_list va)
9090
__attribute__((format(__printf__, 1, 0)));
9191

92-
int vsprintf(char *__restrict buffer, const char *__restrict format,
93-
va_list va)
94-
__attribute__((format(__printf__, 1, 0)));
92+
int sprintf(char *__restrict buffer, const char *__restrict format, ...)
93+
__attribute__((format (__printf__, 2, 3)));
94+
95+
int vsprintf(char *__restrict buffer, const char *__restrict format, va_list va)
96+
__attribute__((format(__printf__, 2, 0)));
9597

9698
int snprintf(char* buffer, size_t count, const char *__restrict format, ...)
9799
__attribute__((format(__printf__, 3, 4)));
98100

99-
int vsnprintf(char* buffer, size_t count, const char *__restrict format,
100-
va_list va)
101+
int vsnprintf(char* buffer, size_t count, const char *__restrict format, va_list va)
101102
__attribute__((format(__printf__, 3, 0)));
102103

103-
int sprintf(char *__restrict buffer,
104-
const char *__restrict format, ...)
105-
__attribute__ ((format (__printf__, 2, 3)));
104+
int fprintf(FILE* __restrict stream, const char* __restrict format, ...)
105+
__attribute__((format (__printf__, 2, 3)));
106+
107+
int vfprintf(FILE* __restrict stream, const char* __restrict format, va_list va)
108+
__attribute__((format(__printf__, 2, 0)));
109+
110+
int asprintf(char **__restrict p_buffer, const char *__restrict format, ...)
111+
__attribute__((format (__printf__, 2, 3)));
112+
113+
int vasprintf(char **__restrict p_buffer, const char *__restrict format, va_list va)
114+
__attribute__((format(__printf__, 2, 0)));
106115

107116
void perror(const char* str);
108117

src/libc/include/time.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ char *asctime(const struct tm *tmp);
4545

4646
char *ctime(const time_t *timer);
4747

48-
size_t strftime(char* ptr, size_t maxsize, const char* format, const struct tm* timeptr);
48+
size_t strftime(char* ptr, size_t maxsize, const char* format, const struct tm* timeptr)
49+
__attribute__((format(__strftime__, 3, 0)));
4950

5051
__END_DECLS
5152

src/libc/nanoprintf.c

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#include <stddef.h>
4949
#include <stdio.h>
5050
#include <limits.h>
51+
#include <stdlib.h> /* malloc */
5152

5253
// Pick reasonable defaults if nothing's been configured.
5354
#if !defined(NANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS) && \
@@ -640,6 +641,10 @@ static void npf_putc_std(int c, void *ctx) {
640641
outchar(c);
641642
}
642643

644+
static void npf_fputc_std(int c, void *ctx) {
645+
fputc(c, (FILE*)ctx);
646+
}
647+
643648
typedef struct npf_cnt_putc_ctx {
644649
npf_putc pc;
645650
void *ctx;
@@ -978,10 +983,10 @@ int npf_vpprintf(npf_putc pc, void *pc_ctx, char const *format, va_list args) {
978983
#undef NPF_WRITEBACK
979984

980985
int _printf_c(char const *format, ...) {
981-
va_list val;
982-
va_start(val, format);
983-
int const rv = vprintf(format, val);
984-
va_end(val);
986+
va_list va;
987+
va_start(va, format);
988+
int const rv = vprintf(format, va);
989+
va_end(va);
985990
return rv;
986991
}
987992

@@ -1005,10 +1010,10 @@ int _vsnprintf_c(char *buffer, size_t bufsz, char const *format, va_list vlist)
10051010
}
10061011

10071012
int _snprintf_c(char *buffer, size_t bufsz, const char *format, ...) {
1008-
va_list val;
1009-
va_start(val, format);
1010-
int const rv = vsnprintf(buffer, bufsz, format, val);
1011-
va_end(val);
1013+
va_list va;
1014+
va_start(va, format);
1015+
int const rv = vsnprintf(buffer, bufsz, format, va);
1016+
va_end(va);
10121017
return rv;
10131018
}
10141019

@@ -1031,6 +1036,49 @@ int _sprintf_c(char *buffer, const char *format, ...)
10311036
return ret;
10321037
}
10331038

1039+
int _vasprintf_c(char **__restrict p_str, const char *__restrict format, va_list vlist) {
1040+
*p_str = NULL;
1041+
int str_len = vsnprintf(NULL, 0, format, vlist);
1042+
if (str_len <= 0) {
1043+
return str_len;
1044+
}
1045+
size_t buf_len = (size_t)str_len + 1;
1046+
char* buf = (char*)malloc(buf_len);
1047+
if (buf == NULL) {
1048+
// malloc failure
1049+
return -1;
1050+
}
1051+
int ret = vsnprintf(buf, buf_len, format, vlist);
1052+
if (ret <= 0) {
1053+
free(buf);
1054+
return ret;
1055+
}
1056+
*p_str = buf;
1057+
return ret;
1058+
}
1059+
1060+
int _asprintf_c(char **__restrict p_str, const char *__restrict format, ...) {
1061+
va_list va;
1062+
va_start(va, format);
1063+
const int ret = vasprintf(p_str, format, va);
1064+
va_end(va);
1065+
return ret;
1066+
}
1067+
1068+
int _vfprintf_c(FILE* __restrict stream, const char* __restrict format, va_list vlist)
1069+
{
1070+
return npf_vpprintf(npf_fputc_std, (void*)stream, format, vlist);
1071+
}
1072+
1073+
int _fprintf_c(FILE* __restrict stream, const char* __restrict format, ...)
1074+
{
1075+
va_list va;
1076+
va_start(va, format);
1077+
const int ret = vfprintf(stream, format, va);
1078+
va_end(va);
1079+
return ret;
1080+
}
1081+
10341082
#if NANOPRINTF_HAVE_GCC_WARNING_PRAGMAS
10351083
#pragma GCC diagnostic pop
10361084
#endif

src/libc/printf.src

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,32 @@ if HAS_PRINTF
1010
public _vsprintf
1111
public _snprintf
1212
public _vsnprintf
13+
public _asprintf
14+
public _vasprintf
15+
public _fprintf
16+
public _vfprintf
1317

1418
_printf := __printf_c
1519
_vprintf := __vprintf_c
20+
_sprintf := __sprintf_c
1621
_vsprintf := __vsprintf_c
1722
_snprintf := __snprintf_c
1823
_vsnprintf := __vsnprintf_c
19-
_sprintf := __sprintf_c
24+
_asprintf := __asprintf_c
25+
_vasprintf := __vasprintf_c
26+
_fprintf := __fprintf_c
27+
_vfprintf := __vfprintf_c
2028

2129
extern __printf_c
2230
extern __vprintf_c
31+
extern __sprintf_c
2332
extern __vsprintf_c
2433
extern __snprintf_c
2534
extern __vsnprintf_c
26-
extern __sprintf_c
35+
extern __asprintf_c
36+
extern __vasprintf_c
37+
extern __fprintf_c
38+
extern __vfprintf_c
2739

2840
else
2941

src/libcxx/include/cstdio

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,14 @@ using ::putchar;
3131
using ::puts;
3232
using ::printf;
3333
using ::vprintf;
34+
using ::sprintf;
3435
using ::vsprintf;
3536
using ::snprintf;
3637
using ::vsnprintf;
37-
using ::sprintf;
38+
using ::fprintf;
39+
using ::vfprintf;
40+
using ::asprintf;
41+
using ::vasprintf;
3842
using ::perror;
3943
} // namespace std
4044

0 commit comments

Comments
 (0)