$filename "printf.exe"
'uses rtl32
'uses rtl64
'Getting printf to operate in JIT mode
======================================
'Thanks to Mike Lobanovsky
'12:28 07/10/2014
#console
'%NoConsole
%TryAttachConsole
uses corewin
uses console
indexbase 0
' _iob[FOPEN_MAX] is msvcrt's internal file buffer array.
' _iob[] can be exported directly, or via cdecl __p__iob(), or via cdecl __iob_func().
' Reference:
' #define FOPEN_MAX 20
' #define STDIN_FILENO 0
' #define STDOUT_FILENO 1
' #define STDERR_FILENO 2
' #define stdin &_iob[STDIN_FILENO]
' #define stdout &_iob[STDOUT_FILENO]
' #define stderr &_iob[STDERR_FILENO]
% STDIN_FILENO 0
% STDOUT_FILENO 1
% STDERR_FILENO 2
type FILE
char* _ptr
int _cnt
char* _base
int _flag
int _file
int _charbuf
int _bufsiz
char* _tmpfname
end type
/*
extern cdecl lib "msvcrt.dll"
! __p__iob () as sys
! _open_osfhandle (sys a, b) as sys
! _fdopen (sys a, char* b) as sys
! setvbuf (sys a, char* b, sys c, d)
! fprintf '(sys a, char* b, ...)
! printf '(char* a, ...)
! memcpy (sys a, b, c)
end extern
*/
#define _O_TEXT 0x4000 // CRLF in file becomes LF in memory!
#define _IONBF 0x4
' same for ConsIn/"r", ConsErr/"w"
sys hCrt = _open_osfhandle(ConsOut, _O_TEXT)
sys hf = _fdopen(hCrt, "w")
' user-defined buffer (for fprintf() only!)
FILE mystdout at hf
setvbuf @mystdout, NULL, _IONBF, 0
' _iob's internals:
' stdin at _iob as "r",
' stdout at iob+sizeof(FILE) as "w"
' stderr at _iob+2*sizeof(FILE) as "w"
'sys _iob = __p__iob()
#ifndef mode64bit
FILE* _iob = __p__iob()
#else
FILE* _iob = __iob_func()
#endif
sys stdin = @_iob(STDIN_FILENO)
sys stdout = @_iob(STDOUT_FILENO)
sys stderr = @_iob(STDERR_FILENO)
memcpy stdout, hf, sizeof(FILE)
setvbuf stdout, NULL, _IONBF, 0
% lf = chr(10)
fprintf @mystdout, "fprintf via mystdout: %s and his %s%d" + lf, "Charles", "O", 2
fprintf stdout, "fprintf via stdout : %s and his %s%d" + lf, "Charles", "O", 2
printf "printf via stdout : %s and his %s%d" + lf, "Charles", "O", 2
waitkey