1
/* ``The contents of this file are subject to the Erlang Public License,
2
* Version 1.1, (the "License"); you may not use this file except in
3
* compliance with the License. You should have received a copy of the
4
* Erlang Public License along with this software. If not, it can be
5
* retrieved via the world wide web at http://www.erlang.org/.
7
* Software distributed under the License is distributed on an "AS IS"
8
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
9
* the License for the specific language governing rights and limitations
12
* The Initial Developer of the Original Code is Ericsson Utvecklings AB.
13
* Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
14
* AB. All Rights Reserved.''
19
/* Without this, variable argument lists break on VxWorks */
35
#include "erl_printf.h"
36
#include "erl_printf_format.h"
40
#define ASSERT(X) assert(X)
45
#if defined(__WIN32__) && !defined(__GNUC__)
49
int (*erts_printf_stdout_func)(char *, va_list) = NULL;
50
int (*erts_printf_stderr_func)(char *, va_list) = NULL;
52
int erts_printf_add_cr_to_stdout = 0;
53
int erts_printf_add_cr_to_stderr = 0;
59
#undef PUTC_ON_SMALL_WRITES
61
#if defined(USE_THREADS) && defined(HAVE_FLOCKFILE)
62
# define FLOCKFILE(FP) flockfile(FP)
63
# define FUNLOCKFILE(FP) funlockfile(FP)
64
# ifdef HAVE_PUTC_UNLOCKED
65
# define PUTC putc_unlocked
66
# define PUTC_ON_SMALL_WRITES
68
# ifdef HAVE_FWRITE_UNLOCKED
69
# define FWRITE fwrite_unlocked
72
#if !defined(USE_THREADS) && defined(putc) && !defined(fwrite)
73
# define PUTC_ON_SMALL_WRITES
75
#if !defined(FLOCKFILE) || !defined(FUNLOCKFILE)
76
# define FLOCKFILE(FP)
77
# define FUNLOCKFILE(FP)
83
# define FWRITE fwrite
87
get_error_result(void)
97
write_f_add_cr(void *vfp, char* buf, size_t len)
101
for (i = 0; i < len; i++) {
102
if (buf[i] == '\n' && PUTC('\r', (FILE *) vfp) == EOF)
103
return get_error_result();
104
if (PUTC(buf[i], (FILE *) vfp) == EOF)
105
return get_error_result();
111
write_f(void *vfp, char* buf, size_t len)
114
#ifdef PUTC_ON_SMALL_WRITES
115
if (len <= 64) { /* Try to optimize writes of small bufs. */
117
for (i = 0; i < len; i++)
118
if (PUTC(buf[i], (FILE *) vfp) == EOF)
119
return get_error_result();
123
if (FWRITE((void *) buf, sizeof(char), len, (FILE *) vfp) != len)
124
return get_error_result();
129
write_fd(void *vfdp, char* buf, size_t len)
135
size = write(*((int *) vfdp), (void *) buf, len);
141
return get_error_result();
152
write_s(void *vwbufpp, char* bufp, size_t len)
154
char **wbufpp = (char **) vwbufpp;
155
ASSERT(wbufpp && *wbufpp);
157
memcpy((void *) *wbufpp, (void *) bufp, len);
169
write_sn(void *vwsnap, char* buf, size_t len)
171
write_sn_arg_t *wsnap = (write_sn_arg_t *) vwsnap;
174
if (wsnap->len > 0) {
176
if (sz >= wsnap->len)
178
memcpy((void *) wsnap->buf, (void *) buf, sz);
186
write_ds(void *vdsbufp, char* buf, size_t len)
188
erts_dsprintf_buf_t *dsbufp = (erts_dsprintf_buf_t *) vdsbufp;
189
size_t need_len = len + 1; /* Also trailing '\0' */
192
ASSERT(dsbufp->str_len <= dsbufp->size);
193
if (need_len > dsbufp->size - dsbufp->str_len) {
194
dsbufp = (*dsbufp->grow)(dsbufp, need_len);
198
memcpy((void *) (dsbufp->str + dsbufp->str_len), (void *) buf, len);
199
dsbufp->str_len += len;
204
erts_printf(const char *format, ...)
208
va_start(arglist, format);
210
if (erts_printf_stdout_func)
211
res = (*erts_printf_stdout_func)((char *) format, arglist);
214
res = erts_printf_format(erts_printf_add_cr_to_stdout
227
erts_fprintf(FILE *filep, const char *format, ...)
231
va_start(arglist, format);
233
if (erts_printf_stdout_func && filep == stdout)
234
res = (*erts_printf_stdout_func)((char *) format, arglist);
235
else if (erts_printf_stderr_func && filep == stderr)
236
res = (*erts_printf_stderr_func)((char *) format, arglist);
238
int (*fmt_f)(void*, char*, size_t);
239
if (erts_printf_add_cr_to_stdout && filep == stdout)
240
fmt_f = write_f_add_cr;
241
else if (erts_printf_add_cr_to_stderr && filep == stderr)
242
fmt_f = write_f_add_cr;
246
res = erts_printf_format(fmt_f,(void *)filep,(char *)format,arglist);
254
erts_fdprintf(int fd, const char *format, ...)
258
va_start(arglist, format);
260
res = erts_printf_format(write_fd,(void *)&fd,(char *)format,arglist);
266
erts_sprintf(char *buf, const char *format, ...)
271
va_start(arglist, format);
273
res = erts_printf_format(write_s, (void *) &p, (char *) format, arglist);
283
erts_snprintf(char *buf, size_t size, const char *format, ...)
285
write_sn_arg_t wsnap;
291
wsnap.len = size-1; /* Always need room for trailing '\0' */
292
va_start(arglist, format);
294
res = erts_printf_format(write_sn, (void *)&wsnap, (char *)format, arglist);
306
erts_dsprintf(erts_dsprintf_buf_t *dsbufp, const char *format, ...)
312
va_start(arglist, format);
314
res = erts_printf_format(write_ds, (void *)dsbufp, (char *)format, arglist);
317
dsbufp->str[0] = '\0';
319
dsbufp->str[dsbufp->str_len] = '\0';
326
erts_vprintf(const char *format, va_list arglist)
329
if (erts_printf_stdout_func)
330
res = (*erts_printf_stdout_func)((char *) format, arglist);
333
res = erts_printf_format(erts_printf_add_cr_to_stdout
344
erts_vfprintf(FILE *filep, const char *format, va_list arglist)
347
if (erts_printf_stdout_func && filep == stdout)
348
res = (*erts_printf_stdout_func)((char *) format, arglist);
349
else if (erts_printf_stderr_func && filep == stderr)
350
res = (*erts_printf_stderr_func)((char *) format, arglist);
352
int (*fmt_f)(void*, char*, size_t);
354
if (erts_printf_add_cr_to_stdout && filep == stdout)
355
fmt_f = write_f_add_cr;
356
else if (erts_printf_add_cr_to_stderr && filep == stderr)
357
fmt_f = write_f_add_cr;
360
res = erts_printf_format(fmt_f,(void *)filep,(char *)format,arglist);
366
erts_vfdprintf(int fd, const char *format, va_list arglist)
370
res = erts_printf_format(write_fd,(void *)&fd,(char *)format,arglist);
375
erts_vsprintf(char *buf, const char *format, va_list arglist)
380
res = erts_printf_format(write_s, (void *) &p, (char *) format, arglist);
389
erts_vsnprintf(char *buf, size_t size, const char *format, va_list arglist)
391
write_sn_arg_t wsnap;
396
wsnap.len = size-1; /* Always need room for trailing '\0' */
398
res = erts_printf_format(write_sn, (void *)&wsnap, (char *)format, arglist);
409
erts_vdsprintf(erts_dsprintf_buf_t *dsbufp, const char *format, va_list arglist)
415
res = erts_printf_format(write_ds, (void *)dsbufp, (char *)format, arglist);
418
dsbufp->str[0] = '\0';
420
dsbufp->str[dsbufp->str_len] = '\0';