
'Getting printf to operate in JIT mode
======================================

'Thanks to Mike Lobanovsky
'12:28 07/10/2014

#console

includepath "$\inc\"
'$filename "fprintf.exe"
'include "rtl32.inc"
'%NoConsole
%TryAttachConsole
include "Console.inc"

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]

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()
memcpy _iob + sizeof(FILE), hf, sizeof(FILE)
setvbuf _iob + sizeof(FILE), NULL, _IONBF, 0

fprintf @mystdout, "fprintf via mystdout: %s and his %s%d%s", "Charles", "O", 2, cr
fprintf _iob + sizeof(FILE), "fprintf via stdout  : %s and his %s%d%s", "Charles", "O", 2, cr
printf "printf  via stdout  : %s and his %s%d%s", "Charles", "O", 2, cr

waitkey
