#define MAX_FILES 2048
#define FD_BLOCK_SIZE 64
+#define MSVCRT_INTERNAL_BUFSIZ 4096
+
/* ioinfo structure size is different in msvcrXX.dll's */
typedef struct {
HANDLE handle;
*_errno() = EBADF;
return -1;
}
- memset(file, 0, sizeof(*file));
+ file->_ptr = file->_base = NULL;
+ file->_cnt = 0;
file->_file = fd;
file->_flag = stream_flags;
+ file->_tmpfname = NULL;
if(file<_iob || file>=_iob+_IOB_ENTRIES)
InitializeCriticalSection(&((file_crit*)file)->crit);
/* INTERNAL: Flush stdio file buffer */
static int flush_buffer(FILE* file)
{
- if(file->_bufsiz) {
+ if(file->_flag & (_IOMYBUF | _USERBUF)) {
int cnt=file->_ptr-file->_base;
if(cnt>0 && _write(file->_file, file->_base, cnt) != cnt) {
file->_flag |= _IOERR;
return EOF;
}
file->_ptr=file->_base;
- file->_cnt=file->_bufsiz;
+ file->_cnt=0;
}
return 0;
}
&& _isatty(file->_file))
return FALSE;
- file->_base = calloc(BUFSIZ,1);
+ file->_base = calloc(MSVCRT_INTERNAL_BUFSIZ,1);
if(file->_base) {
- file->_bufsiz = BUFSIZ;
+ file->_bufsiz = MSVCRT_INTERNAL_BUFSIZ;
file->_flag |= _IOMYBUF;
} else {
file->_base = (char*)(&file->_charbuf);
- /* put here 2 ??? */
- file->_bufsiz = sizeof(file->_charbuf);
+ file->_bufsiz = 2;
+ file->_flag |= _IONBF;
}
file->_ptr = file->_base;
file->_cnt = 0;
return TRUE;
}
+/* INTERNAL: Allocate temporary buffer for stdout and stderr */
+static BOOL add_std_buffer(FILE *file)
+{
+ static char buffers[2][BUFSIZ];
+
+ if((file->_file!=STDOUT_FILENO && file->_file!=STDERR_FILENO)
+ || !_isatty(file->_file) || file->_bufsiz)
+ return FALSE;
+
+ file->_ptr = file->_base = buffers[file->_file == STDOUT_FILENO ? 0 : 1];
+ file->_bufsiz = file->_cnt = BUFSIZ;
+ return TRUE;
+}
+
+/* INTERNAL: Removes temporary buffer from stdout or stderr */
+/* Only call this function when add_std_buffer returned TRUE */
+static void remove_std_buffer(FILE *file)
+{
+ flush_buffer(file);
+ file->_ptr = file->_base = NULL;
+ file->_bufsiz = file->_cnt = 0;
+}
+
/* INTERNAL: Convert integer to base32 string (0-9a-v), 0 becomes "" */
static int int_to_base32(int num, char *str)
{
FILE *file;
LOCK_FILES();
- for (i = 3; i < stream_idx; i++) {
+ for (i = 0; i < stream_idx; i++) {
file = get_file(i);
if (file->_flag)
{
if(file->_flag & mask) {
- fflush(file);
+ fflush(file);
num_flushed++;
}
}
}
/* Allocate buffer if needed */
- if(file->_bufsiz == 0 && !(file->_flag & _IONBF))
+ if(!(file->_flag & (_IONBF | _IOMYBUF | _USERBUF)))
alloc_buffer(file);
if(!(file->_flag & _IOREAD)) {
}
}
- if(file->_flag & _IONBF) {
+ if(!(file->_flag & (_IOMYBUF | _USERBUF))) {
int r;
if ((r = read_i(file->_file,&c,1)) != 1) {
file->_flag |= (r == 0) ? _IOEOF : _IOERR;
{
size_t rcnt=size * nmemb;
size_t read=0;
- int pread=0;
+ size_t pread=0;
if(!rcnt)
return 0;
/* first buffered data */
if(file->_cnt>0) {
- int pcnt= (rcnt>(unsigned int)file->_cnt)? file->_cnt:rcnt;
+ int pcnt= (rcnt>file->_cnt)? file->_cnt:rcnt;
memcpy(ptr, file->_ptr, pcnt);
file->_cnt -= pcnt;
file->_ptr += pcnt;
return 0;
}
}
+
+ if(rcnt>0 && !(file->_flag & (_IONBF | _IOMYBUF | _USERBUF)))
+ alloc_buffer(file);
+
while(rcnt>0)
{
int i;
- if (!file->_cnt && rcnt<BUFSIZ && !(file->_flag & _IONBF)
- && (file->_bufsiz != 0 || alloc_buffer(file))) {
+ if (!file->_cnt && rcnt<BUFSIZ && (file->_flag & (_IOMYBUF | _USERBUF))) {
file->_cnt = _read(file->_file, file->_base, file->_bufsiz);
file->_ptr = file->_base;
- i = ((unsigned int)file->_cnt<rcnt) ? file->_cnt : rcnt;
+ i = (file->_cnt<rcnt) ? file->_cnt : rcnt;
/* If the buffer fill reaches eof but fread wouldn't, clear eof. */
if (i > 0 && i < file->_cnt) {
get_ioinfo(file->_file)->wxflag &= ~WX_ATEOF;
file->_cnt -= i;
file->_ptr += i;
}
- } else if (rcnt > UINT_MAX) {
- i = _read(file->_file, ptr, UINT_MAX);
+ } else if (rcnt > INT_MAX) {
+ i = _read(file->_file, ptr, INT_MAX);
} else if (rcnt < BUFSIZ) {
i = _read(file->_file, ptr, rcnt);
} else {
_unlock_file(file);
return -1;
}
- if(file->_bufsiz) {
+ if(file->_flag & (_IOMYBUF | _USERBUF)) {
if(file->_flag & _IOWRT) {
pos += file->_ptr - file->_base;
*/
int CDECL fgetpos(FILE* file, fpos_t *pos)
{
- int off=0;
-
- _lock_file(file);
- *pos = _lseeki64(file->_file,0,SEEK_CUR);
- if(*pos == -1) {
- _unlock_file(file);
+ *pos = _ftelli64(file);
+ if(*pos == -1)
return -1;
- }
- if(file->_bufsiz) {
- if( file->_flag & _IOWRT ) {
- off = file->_ptr - file->_base;
- } else {
- off = -file->_cnt;
- if (get_ioinfo(file->_file)->wxflag & WX_TEXT) {
- /* Black magic correction for CR removal */
- int i;
- for (i=0; i<file->_cnt; i++) {
- if (file->_ptr[i] == '\n')
- off--;
- }
- /* Black magic when reading CR at buffer boundary*/
- if(get_ioinfo(file->_file)->wxflag & WX_READCR)
- off--;
- }
- }
- }
- *pos += off;
- _unlock_file(file);
return 0;
}
*/
int CDECL fputs(const char *s, FILE* file)
{
- size_t i, len = strlen(s);
+ size_t len = strlen(s);
int ret;
_lock_file(file);
- if (!(get_ioinfo(file->_file)->wxflag & WX_TEXT)) {
- ret = fwrite(s,sizeof(*s),len,file) == len ? 0 : EOF;
- _unlock_file(file);
- return ret;
- }
- for (i=0; i<len; i++)
- if (fputc(s[i], file) == EOF) {
- _unlock_file(file);
- return EOF;
- }
-
+ ret = fwrite(s, sizeof(*s), len, file) == len ? 0 : EOF;
_unlock_file(file);
- return 0;
+ return ret;
}
/*********************************************************************
int CDECL fputws(const wchar_t *s, FILE* file)
{
size_t i, len = strlenW(s);
+ BOOL tmp_buf;
int ret;
_lock_file(file);
_unlock_file(file);
return ret;
}
+
+ tmp_buf = add_std_buffer(file);
for (i=0; i<len; i++) {
- if (((s[i] == '\n') && (fputc('\r', file) == EOF))
- || fputwc(s[i], file) == WEOF) {
+ if(fputwc(s[i], file) == WEOF) {
+ if(tmp_buf) remove_std_buffer(file);
_unlock_file(file);
return WEOF;
}
}
+ if(tmp_buf) remove_std_buffer(file);
_unlock_file(file);
return 0;
}
{
size = int_to_base32(tmpnam_unique++, tmpstr);
memcpy(p, tmpstr, size);
+ p[size] = '\0';
if (GetFileAttributesA(s) == INVALID_FILE_ATTRIBUTES &&
GetLastError() == ERROR_FILE_NOT_FOUND)
break;
{
size = int_to_base32_w(tmpnam_unique++, tmpstr);
memcpy(p, tmpstr, size*sizeof(wchar_t));
+ p[size] = '\0';
if (GetFileAttributesW(s) == INVALID_FILE_ATTRIBUTES &&
GetLastError() == ERROR_FILE_NOT_FOUND)
break;
wint_t CDECL ungetwc(wint_t wc, FILE * file)
{
wchar_t mwc = wc;
- char * pp = (char *)&mwc;
- int i;
+
+ if (wc == WEOF)
+ return WEOF;
_lock_file(file);
- for(i=sizeof(wchar_t)-1;i>=0;i--) {
- if(pp[i] != ungetc(pp[i],file)) {
+
+ if((get_ioinfo(file->_file)->exflag & (EF_UTF8 | EF_UTF16))
+ || !(get_ioinfo(file->_file)->wxflag & WX_TEXT)) {
+ unsigned char * pp = (unsigned char *)&mwc;
+ int i;
+
+ for(i=sizeof(wchar_t)-1;i>=0;i--) {
+ if(pp[i] != ungetc(pp[i],file)) {
+ _unlock_file(file);
+ return WEOF;
+ }
+ }
+ }else {
+ char mbs[MB_LEN_MAX];
+ int len;
+
+ len = wctomb(mbs, mwc);
+ if(len == -1) {
_unlock_file(file);
return WEOF;
}
+
+ for(len--; len>=0; len--) {
+ if(mbs[len] != ungetc(mbs[len], file)) {
+ _unlock_file(file);
+ return WEOF;
+ }
+ }
}
_unlock_file(file);