1 /* Copyright (C) 2001 by Alex Kompel <shurikk@pacbell.net> */
2 /* NetHack may be freely redistributed.  See license for details. */
3 
4 #define NEED_VARARGS
5 #include "hack.h"
6 #include <fcntl.h>
7 // #include "wceconf.h"
8 
9 static union {
10 	time_t t_val;
11 	struct time_pack {
12 		unsigned int ss:6;
13 		unsigned int mm:6;
14 		unsigned int dd:5;
15 		unsigned int hh:6;
16 		unsigned int mo:4;
17 		unsigned int yr:10;
18 		unsigned int wd:3;
19 	} tm_val;
20 } _t_cnv;
21 
22 #define IS_LEAP(yr) (((yr)%4==0 || (yr)%100==0) && !(yr)%400==0)
23 static char _day_mo_leap[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
24 static char _day_mo[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
25 
localtime(const time_t * ptime)26 struct tm * __cdecl localtime ( const time_t *ptime )
27 {
28 	static struct tm ptm;
29 	int i;
30 	if( !ptime ) return NULL;
31 
32 	_t_cnv.t_val = *ptime;
33 
34     ptm.tm_sec		= _t_cnv.tm_val.ss ;     /* seconds after the minute - [0,59] */
35     ptm.tm_min		= _t_cnv.tm_val.mm;     /* minutes after the hour - [0,59] */
36     ptm.tm_hour	= _t_cnv.tm_val.hh;    /* hours since midnight - [0,23] */
37     ptm.tm_mday	= _t_cnv.tm_val.dd;    /* day of the month - [1,31] */
38     ptm.tm_mon		= _t_cnv.tm_val.mo-1;     /* months since January - [0,11] */
39     ptm.tm_year	= _t_cnv.tm_val.yr;    /* years since 1900 */
40     ptm.tm_wday	= _t_cnv.tm_val.wd;    /* days since Sunday - [0,6] */
41 
42 	ptm.tm_yday = _t_cnv.tm_val.dd;    /* days since January 1 - [0,365] */
43 	for( i=0; i<ptm.tm_mon; i++ )
44 		ptm.tm_yday += IS_LEAP(_t_cnv.tm_val.yr+1900)?_day_mo_leap[i] : _day_mo[i] ;
45 
46 	ptm.tm_isdst = 0;   /* daylight savings time flag  - NOT IMPLEMENTED */
47 	return &ptm;
48 }
49 
time(time_t * timeptr)50 time_t __cdecl time(time_t * timeptr)
51 {
52 	SYSTEMTIME stm;
53 	GetLocalTime(&stm);
54 
55 	_t_cnv.tm_val.yr = stm.wYear-1900;
56 	_t_cnv.tm_val.mo = stm.wMonth;
57 	_t_cnv.tm_val.dd = stm.wDay;
58 	_t_cnv.tm_val.hh = stm.wHour;
59 	_t_cnv.tm_val.mm = stm.wMinute;
60 	_t_cnv.tm_val.ss = stm.wSecond;
61 	_t_cnv.tm_val.wd = stm.wDayOfWeek;
62 
63 	if( timeptr)
64 		*timeptr = _t_cnv.t_val;
65 	return _t_cnv.t_val;
66 }
67 
68 /*------------------------------------------------------------------------------*/
69 /* __io.h__ */
70 /* Hack io.h function with stdio.h functions */
71 /* ASSUMPTION : int can hold FILE* */
72 static TCHAR _nh_cwd[MAX_PATH];
73 const int MAGIC_OFFSET=5;
74 #define FILE_TABLE_SIZE  256
75 static HANDLE _nh_file_table[FILE_TABLE_SIZE];
76 static int file_pointer = -1;
77 
get_file_handle(int i)78 static HANDLE get_file_handle(int i)
79 {
80 	i -= MAGIC_OFFSET;
81 	if( i>=0 && i<FILE_TABLE_SIZE )
82 		return _nh_file_table[i];
83 	else
84 		return INVALID_HANDLE_VALUE;
85 }
86 
alloc_file_handle(HANDLE h)87 static int alloc_file_handle(HANDLE h)
88 {
89 	int i;
90 	if( file_pointer==-1 ) {
91 		file_pointer=0;
92 		for(i=0; i<FILE_TABLE_SIZE; i++ )
93 			_nh_file_table[i] = INVALID_HANDLE_VALUE;
94 	}
95 
96 	i = (file_pointer+1)%FILE_TABLE_SIZE;
97 	while(_nh_file_table[i]!=INVALID_HANDLE_VALUE ) {
98 		if( i==file_pointer ) {
99 			MessageBox(NULL, _T("Ran out of file handles."), _T("Fatal Error"), MB_OK);
100 			abort();
101 		}
102 		i = (i+1) % FILE_TABLE_SIZE;
103 	}
104 
105 	file_pointer = i;
106 	_nh_file_table[file_pointer] = h;
107 	return file_pointer+MAGIC_OFFSET;
108 }
109 
close(int f)110 int __cdecl close(int f) {
111 	int retval;
112 	f -= MAGIC_OFFSET;
113 	if( f<0 || f>=FILE_TABLE_SIZE )	return -1;
114 	retval = (CloseHandle(_nh_file_table[f])? 0 : -1);
115 	_nh_file_table[f] = INVALID_HANDLE_VALUE;
116 	return retval;
117 }
118 
creat(const char * fname,int mode)119 int __cdecl creat(const char *fname , int mode)
120 {
121 	HANDLE f;
122 	TCHAR wbuf[MAX_PATH+1];
123 	ZeroMemory(wbuf, sizeof(wbuf));
124 	NH_A2W(fname, wbuf, MAX_PATH);
125 
126 	f = CreateFile(
127 		wbuf,
128 		GENERIC_READ | GENERIC_WRITE,
129 		0,
130 		NULL,
131 		CREATE_ALWAYS,
132 		FILE_ATTRIBUTE_NORMAL,
133 		NULL);
134 
135 	if( f==INVALID_HANDLE_VALUE ) return -1;
136 	else     return alloc_file_handle(f);
137 }
138 
eof(int f)139 int __cdecl eof(int f)
140 {
141 	DWORD fpos, fsize;
142 	HANDLE p = get_file_handle(f);
143 
144 	if( f==-1 ) return -1;
145 
146 	fpos = SetFilePointer(p, 0, NULL, FILE_CURRENT);
147 	fsize = SetFilePointer(p, 0, NULL, FILE_END);
148 	if( fpos==0xFFFFFFFF || fsize==0xFFFFFFFF ) return -1;
149 	if( fpos==fsize ) return 1;
150 	else {
151 		SetFilePointer(p, fpos, NULL, FILE_BEGIN);
152 		return 0;
153 	}
154 }
155 
lseek(int f,long offset,int origin)156 long __cdecl lseek( int f, long offset, int origin )
157 {
158 	HANDLE p = get_file_handle(f);
159 	DWORD fpos;
160 	switch(origin) {
161 	case SEEK_SET:
162 		fpos = SetFilePointer(p, offset, NULL, FILE_BEGIN);
163 		break;
164 	case SEEK_CUR:
165 		fpos = SetFilePointer(p, offset, NULL, FILE_CURRENT);
166 		break;
167 	case SEEK_END:
168 		fpos = SetFilePointer(p, offset, NULL, FILE_END);
169 		break;
170 	default:
171 		fpos = 0xFFFFFFFF;
172 		break;
173 	}
174 	if( fpos==0xFFFFFFFF ) return -1;
175 	else return (long)fpos;
176 }
177 
open(const char * filename,int oflag,...)178 int __cdecl open( const char *filename, int oflag, ... )
179 {
180 	TCHAR fname[MAX_PATH+1];
181 	TCHAR path[MAX_PATH+1];
182     HANDLE f;
183     DWORD fileaccess;
184     DWORD filecreate;
185 
186 	/* O_TEXT is not supported */
187 
188     /*
189      * decode the access flags
190      */
191     switch( oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR) ) {
192 
193         case _O_RDONLY:         /* read access */
194                 fileaccess = GENERIC_READ;
195                 break;
196         case _O_WRONLY:         /* write access */
197                 fileaccess = GENERIC_READ | GENERIC_WRITE;
198                 break;
199         case _O_RDWR:           /* read and write access */
200                 fileaccess = GENERIC_READ | GENERIC_WRITE;
201                 break;
202         default:                /* error, bad oflag */
203                 return -1;
204     }
205 
206     /*
207      * decode open/create method flags
208      */
209     switch ( oflag & (_O_CREAT | _O_EXCL | _O_TRUNC) ) {
210         case 0:
211         case _O_EXCL:                   // ignore EXCL w/o CREAT
212             filecreate = OPEN_EXISTING;
213             break;
214 
215         case _O_CREAT:
216             filecreate = OPEN_ALWAYS;
217             break;
218 
219         case _O_CREAT | _O_EXCL:
220         case _O_CREAT | _O_TRUNC | _O_EXCL:
221             filecreate = CREATE_NEW;
222             break;
223 
224         case _O_TRUNC:
225         case _O_TRUNC | _O_EXCL:        // ignore EXCL w/o CREAT
226             filecreate = TRUNCATE_EXISTING;
227             break;
228 
229         case _O_CREAT | _O_TRUNC:
230             filecreate = CREATE_ALWAYS;
231             break;
232 
233         default:
234             return -1;
235     }
236 
237 	/* assemple the file name */
238 	ZeroMemory(fname, sizeof(fname));
239 	ZeroMemory(path, sizeof(path));
240 	NH_A2W(filename, fname, MAX_PATH);
241 	if( *filename!='\\' && *filename!='/' ) {
242 		_tcscpy(path, _nh_cwd);
243 		_tcsncat(path, _T("\\"), MAX_PATH - _tcslen(path));
244 	}
245 	_tcsncat(path, fname, MAX_PATH - _tcslen(path));
246 
247     /*
248      * try to open/create the file
249      */
250     if ( (f = CreateFile( path,
251                          fileaccess,
252                          0,
253                          NULL,
254                          filecreate,
255                          FILE_ATTRIBUTE_NORMAL,
256                          NULL ))
257          == INVALID_HANDLE_VALUE )
258     {
259         return -1;
260     }
261 
262 	if( !(oflag & O_APPEND) ) SetFilePointer(f, 0, NULL, FILE_BEGIN);
263 	return alloc_file_handle(f);
264 }
265 
read(int f,void * buffer,unsigned int count)266 int __cdecl read( int f, void *buffer, unsigned int count )
267 {
268 	HANDLE p = get_file_handle(f);
269 	DWORD bytes_read;
270 	if( !ReadFile(p, buffer, count, &bytes_read, NULL) )
271 		return -1;
272 	else
273 		return (int)bytes_read;
274 }
275 
unlink(const char * filename)276 int __cdecl unlink(const char * filename)
277 {
278 	TCHAR wbuf[MAX_PATH+1];
279 	TCHAR fname[MAX_PATH+1];
280 
281 	ZeroMemory(wbuf, sizeof(wbuf));
282 	ZeroMemory(fname, sizeof(fname));
283 	NH_A2W(filename, wbuf, MAX_PATH);
284 	if( *filename!='\\' && *filename!='/' ) {
285 		_tcscpy(fname, _nh_cwd);
286 		_tcsncat(fname, _T("\\"), MAX_PATH - _tcslen(fname));
287 	}
288 	_tcsncat(fname, wbuf, MAX_PATH - _tcslen(fname));
289 
290 	return !DeleteFileW(fname);
291 }
292 
write(int f,const void * buffer,unsigned int count)293 int __cdecl write( int f, const void *buffer, unsigned int count )
294 {
295 	HANDLE p = get_file_handle(f);
296 	DWORD bytes_written;
297 	if( !WriteFile(p, buffer, count, &bytes_written, NULL) )
298 		return -1;
299 	else
300 		return (int)bytes_written;
301 }
302 
rename(const char * oldname,const char * newname)303 int __cdecl rename( const char *oldname, const char *newname )
304 {
305 	WCHAR f1[MAX_PATH+1];
306 	WCHAR f2[MAX_PATH+1];
307 	ZeroMemory(f1, sizeof(f1));
308 	ZeroMemory(f2, sizeof(f2));
309 	MultiByteToWideChar(CP_ACP, 0, oldname, -1, f1, MAX_PATH);
310 	MultiByteToWideChar(CP_ACP, 0, newname, -1, f2, MAX_PATH);
311 	return !MoveFile(f1, f2);
312 }
313 
access(const char * path,int mode)314 int __cdecl access( const char *path, int mode )
315 {
316 	DWORD attr;
317 	WCHAR f[MAX_PATH+1];
318 	ZeroMemory(f, sizeof(f));
319 	MultiByteToWideChar(CP_ACP, 0, path, -1, f, MAX_PATH);
320 
321 	attr = GetFileAttributes(f);
322 	if( attr == (DWORD)-1 )	return -1;
323 
324 	if ( (attr & FILE_ATTRIBUTE_READONLY) && (mode & 2) )
325 		return -1;
326 	else
327         return 0;
328 }
329 
chdir(const char * dirname)330 int chdir( const char *dirname )
331 {
332 	ZeroMemory(_nh_cwd, sizeof(_nh_cwd));
333 	NH_A2W(dirname, _nh_cwd, MAX_PATH);
334 	return 0;
335 }
336 
getcwd(char * buffer,int maxlen)337 char *getcwd( char *buffer, int maxlen )
338 {
339 	if( maxlen<(int)_tcslen(_nh_cwd) ) return NULL;
340 	else return NH_W2A(_nh_cwd, buffer, maxlen);
341 }
342 
343 /*------------------------------------------------------------------------------*/
344 /* __errno.h__ */
345 int errno;
346 
347 /*------------------------------------------------------------------------------*/
348 /*
349  * Chdrive() changes the default drive.
350  */
351 void
chdrive(char * str)352 chdrive(char *str)
353 {
354 	return;
355 }
356 
357 /*
358  * This is used in nhlan.c to implement some of the LAN_FEATURES.
359  */
get_username(lan_username_size)360 char *get_username(lan_username_size)
361 int *lan_username_size;
362 {
363 	static char username_buffer[BUFSZ];
364 	strcpy(username_buffer, "nhsave");
365 	return username_buffer;
366 }
367 
Delay(int ms)368 void Delay(int ms)
369 {
370 	(void)Sleep(ms);
371 }
372 
more()373 void more()
374 {
375 
376 }
377 
isatty(int f)378 int isatty(int f)
379 {
380 	return 0;
381 }
382 
383 
384 #if defined(WIN_CE_PS2xx) || defined(WIN32_PLATFORM_HPCPRO)
isupper(int c)385 int __cdecl isupper(int c)
386 {
387 	char str[2];
388 	WCHAR wstr[2];
389 	str[0] = c;
390 	str[1] = 0;
391 
392 	NH_A2W(str, wstr, 1);
393 	return iswupper(wstr[0]);
394 }
395 
isdigit(int c)396 int __cdecl isdigit(int c)
397 {
398 	return  ('0' <= c && c <= '9');
399 }
400 
isxdigit(int c)401 int __cdecl isxdigit(int c)
402 {
403 	return  (('0' <= c && c <= '9') ||
404 		     ('a' <= c && c <= 'f') ||
405 			 ('A' <= c && c <= 'F'));
406 }
407 
isspace(int c)408 int __cdecl isspace(int c)
409 {
410 	char str[2];
411 	WCHAR wstr[2];
412 	str[0] = c;
413 	str[1] = 0;
414 
415 	NH_A2W(str, wstr, 1);
416 	return iswspace(wstr[0]);
417 }
418 
isprint(int c)419 int __cdecl isprint(int c)
420 {
421 	char str[2];
422 	WCHAR wstr[2];
423 	str[0] = c;
424 	str[1] = 0;
425 
426 	NH_A2W(str, wstr, 1);
427 	return iswprint(wstr[0]);
428 }
429 
_strdup(const char * s)430 char* __cdecl _strdup(const char* s)
431 {
432 	char* p;
433 	p = malloc(strlen(s)+1);
434 	return strcpy(p, s);
435 }
436 
strrchr(const char * s,int c)437 char* __cdecl strrchr( const char *s, int c )
438 {
439 	WCHAR wstr[1024];
440 	WCHAR *w;
441 	w = wcsrchr(NH_A2W(s, wstr, 1024), c);
442 	if(w) return (char*)(s + (w - wstr));
443 	else return NULL;
444 }
445 
_stricmp(const char * a,const char * b)446 int   __cdecl _stricmp(const char* a, const char* b)
447 {
448 	 return strncmpi(a, b, 65535u);
449 }
450 
451 #endif
452 
453 #if defined(WIN_CE_PS2xx)
454 /* stdio.h functions are missing from PAlm Size PC SDK 1.2 (SH3 and MIPS) */
455 
456 #pragma warning(disable:4273)
457 
fopen(const char * filename,const char * mode)458 FILE * __cdecl fopen(const char* filename, const char *mode)
459 {
460     int modeflag;
461     int whileflag;
462     int filedes;
463 
464     /* First mode character must be 'r', 'w', or 'a'. */
465     switch (*mode) {
466     case 'r':
467             modeflag = _O_RDONLY;
468             break;
469     case 'w':
470             modeflag = _O_WRONLY | _O_CREAT | _O_TRUNC;
471             break;
472     case 'a':
473             modeflag = _O_WRONLY | _O_CREAT | _O_APPEND;
474             break;
475     default:
476             return NULL;
477     }
478 
479     whileflag=1;
480     while(*++mode && whileflag)
481             switch(*mode) {
482 
483             case '+':
484                     if (modeflag & _O_RDWR)
485                             whileflag=0;
486                     else {
487                             modeflag |= _O_RDWR;
488                             modeflag &= ~(_O_RDONLY | _O_WRONLY);
489                     }
490                     break;
491 
492             case 'b':
493                     if (modeflag & (_O_TEXT | _O_BINARY))
494                             whileflag=0;
495                     else
496                             modeflag |= _O_BINARY;
497                     break;
498 
499             case 't': /* not supported */
500 					whileflag=0;
501                     break;
502 
503 	        default:
504                     whileflag=0;
505                     break;
506             }
507 
508     if ((filedes = open(filename, modeflag))==-1) return NULL;
509 
510     return (FILE*)filedes;
511 }
512 
fscanf(FILE * f,const char * format,...)513 int    __cdecl fscanf(FILE *f , const char *format, ...)
514 {
515 	/* Format spec:  %[*] [width] [l] type ] */
516 	int ch;
517 	int sch;
518 	int matched = 0;
519 	int width = 65535;
520 	int modifier = -1;
521 	int skip_flag = 0;
522 	int n_read = 0;
523 	char buf[BUFSZ];
524 	TCHAR wbuf[BUFSZ];
525 	char* p;
526 	va_list args;
527 
528 #define RETURN_SCANF(i) { va_end(args); return i; }
529 #define NEXT_CHAR(f) (n_read++, fgetc(f))
530 
531 	va_start(args, format);
532 
533 	ch = *format++;
534 	sch = NEXT_CHAR(f);
535 	while( ch && sch!=EOF ) {
536 		if( isspace(ch) ) {
537 			while( ch && isspace(ch) ) ch = *format++;
538 			while( sch!=EOF && isspace(sch) ) sch = NEXT_CHAR(f);
539 			format--;
540 			goto next_spec;
541 		}
542 
543 		/* read % */
544 		if( ch!='%' ) {
545 			if( sch!=ch ) RETURN_SCANF(matched);
546 			sch = NEXT_CHAR(f);
547 			goto next_spec;
548 		} else {
549 			/* process '%%' */
550 			ch = *format++;
551 			if( ch=='%' ) {
552 				if( sch!='%' ) RETURN_SCANF(matched);
553 				sch = NEXT_CHAR(f);
554 				goto next_spec;
555 			}
556 
557 			if( ch=='*' ) {
558 				/* read skip flag - '*' */
559 				skip_flag=1;
560 				ch = *format++;
561 			}
562 
563 			/* get width */
564 			if( isdigit(ch) ) {
565 				width = 0;
566 				while(ch && isdigit(ch)) {
567 					width = width*10 + (ch-'0');
568 					ch = *format++;
569 				}
570 			}
571 
572 			/* get modifier */
573 			if( ch=='l' ) {
574 				modifier = 'l';
575 				ch = *format++;
576 			}
577 
578 			/* get type */
579 			switch(ch) {
580 			case 'c':
581 				if( !skip_flag ) {
582 					*(va_arg(args, char*))=sch;
583 					matched++;
584 				}
585 				sch = NEXT_CHAR(f);
586 				goto next_spec;
587 			case 'd':
588 				p = buf;
589 				/* skip space */
590 				while(sch!=EOF && isspace(sch)) sch=NEXT_CHAR(f);
591 				while(sch!=EOF && isdigit(sch) && --width>=0) { *p++ = sch; sch=NEXT_CHAR(f); }
592 				*p = '\x0';
593 				if( !skip_flag ) {
594 					matched++;
595 					if( modifier=='l' ) {
596 						*(va_arg(args, long*))=wcstol(NH_A2W(buf, wbuf, BUFSZ), NULL, 10);
597 					} else {
598 						*(va_arg(args, int*))=wcstol(NH_A2W(buf, wbuf, BUFSZ), NULL, 10);
599 					}
600 				}
601 				goto next_spec;
602 			case 'x':
603 				p = buf;
604 				while(sch!=EOF && isspace(sch)) sch=NEXT_CHAR(f);
605 				while(sch!=EOF && isxdigit(sch) && --width>=0) { *p++ = sch; sch=NEXT_CHAR(f); }
606 				*p = '\x0';
607 				if( !skip_flag ) {
608 					matched++;
609 					if( modifier=='l' ) {
610 						*(va_arg(args, long*))=wcstol(NH_A2W(buf, wbuf, BUFSZ), NULL, 16);
611 					} else {
612 						*(va_arg(args, int*))=wcstol(NH_A2W(buf, wbuf, BUFSZ), NULL, 16);
613 					}
614 				}
615 				goto next_spec;
616 			case 'n':
617 				*(va_arg(args, int*)) = n_read;
618 				matched++;
619 				goto next_spec;
620 			case 's':
621 				if( skip_flag ) {
622 					while(sch!=EOF && !isspace(sch) && --width>=0) { sch=NEXT_CHAR(f); }
623 				} else {
624 					p = va_arg(args, char*);
625 					while(sch!=EOF && !isspace(sch) && --width>=0) { *p++ = sch; sch=NEXT_CHAR(f); }
626 					*p = '\x0';
627 					matched++;
628 				}
629 				goto next_spec;
630 			case '[': {
631 					char pattern[256];
632 					int start, end;
633 					int negate;
634 
635 					ZeroMemory(pattern, sizeof(pattern));
636 					p = pattern;
637 
638 					/* try to parse '^' modifier */
639 					ch = *format++;
640 					if( ch=='^' ) { negate=1; ch=*format++; }
641 					else		  { negate=0; }
642 					if( ch==0 ) RETURN_SCANF(EOF);
643 
644 					for( ; ch && ch!=']'; ch = *format++ ) {
645 						/* try to parse range: a-z */
646 						if( format[0]=='-' &&
647 							format[1] && format[1]!=']' ) {
648 							start = ch;
649 							format++;
650 							end = *format++;
651 							while(start<=end) {
652 								if(!strchr(pattern, (char)start))
653 									*p++ = (char)start;
654 								start++;
655 							}
656 						} else {
657 							if(!strchr(pattern, (char)ch)) *p++ = (char)ch;
658 						}
659 					}
660 
661 					if( skip_flag ) {
662 						while(sch!=EOF && strchr(pattern, sch) && --width>=0) { sch=NEXT_CHAR(f); }
663 					} else {
664 						p = va_arg(args, char*);
665 						if( negate )
666 							while(sch!=EOF && !strchr(pattern, sch) && --width>=0) { *p++ = sch; sch=NEXT_CHAR(f); }
667 						else
668 							while(sch!=EOF && strchr(pattern, sch) && --width>=0) { *p++ = sch; sch=NEXT_CHAR(f); }
669 						*p = '\x0';
670 						matched++;
671 					}
672 				  } goto next_spec;
673 			default:
674 				RETURN_SCANF(EOF);
675 			}
676 		}
677 
678 next_spec:
679 		width = 65535;
680 		modifier = -1;
681 		skip_flag = 0;
682 		ch = *format++;
683 	}
684 	fseek(f, -1, SEEK_CUR);
685 	RETURN_SCANF(matched);
686 
687 #undef RETURN_SCANF
688 #undef NEXT_CHAR
689 }
690 
fprintf(FILE * f,const char * format,...)691 int __cdecl fprintf(FILE *f , const char *format, ...)
692 {
693 	int retval;
694 	va_list args;
695 
696 	if( !f || !format ) return 0;
697 
698 	va_start(args, format);
699 	retval = vfprintf(f, format, args);
700 	va_end(args);
701 
702 	return retval;
703 }
704 
vfprintf(FILE * f,const char * format,va_list args)705 int    __cdecl vfprintf(FILE* f, const char *format, va_list args)
706 {
707 	char buf[4096];
708 	int retval;
709 
710 	if( !f || !format ) return 0;
711 
712 	retval = vsprintf(buf, format, args);
713 
714 	write((int)f, buf, strlen(buf));
715 
716 	return retval;
717 }
718 
fgetc(FILE * f)719 int __cdecl fgetc(FILE * f)
720 {
721 	char c;
722 	int fh = (int)f;
723 
724 	if( !f ) return EOF;
725 	if( read(fh, &c, 1)==1 ) return c;
726 	else					 return EOF;
727 }
728 
fgets(char * s,int size,FILE * f)729 char * __cdecl fgets(char *s, int size, FILE *f)
730 {
731 	/* not the best performance but it will do for now...*/
732 	char c;
733 	if( !f || !s || size==0 ) return NULL;
734 	while( --size>0 ) {
735 		if( (c = fgetc(f))==EOF ) return NULL;
736 
737 		*s++ = c;
738 		if( c=='\n' ) break;
739 	}
740 	*s = '\x0';
741 	return s;
742 }
743 
printf(const char * format,...)744 int    __cdecl printf(const char *format, ...)
745 {
746 	int retval;
747 	va_list args;
748 
749 	if( !format ) return 0;
750 
751 	va_start(args, format);
752 	retval = vprintf(format, args);
753 	va_end(args);
754 
755 	return retval;
756 }
757 
vprintf(const char * format,va_list args)758 int    __cdecl vprintf(const char *format, va_list args)
759 {
760 	char buf[4096];
761 	int retval;
762 
763 	retval = vsprintf(buf, format, args);
764 	puts(buf);
765 	return retval;
766 }
767 
768 // int    __cdecl putchar(int);
puts(const char * s)769 int    __cdecl puts(const char * s)
770 {
771 	TCHAR wbuf[4096];
772 	NH_A2W(s, wbuf, 4096);
773 	MessageBox(NULL, wbuf, _T("stdout"), MB_OK);
774 	return 0;
775 }
776 
_getstdfilex(int desc)777 FILE*  __cdecl _getstdfilex(int desc)
778 {
779 	return NULL;
780 }
781 
fclose(FILE * f)782 int __cdecl fclose(FILE * f)
783 {
784 	if(!f) return EOF;
785 	return close((int)f)==-1? EOF : 0;
786 }
787 
fread(void * p,size_t size,size_t count,FILE * f)788 size_t __cdecl fread(void *p, size_t size, size_t count, FILE *f)
789 {
790 	int read_bytes;
791 	if(!f || !p || size==0 || count==0) return 0;
792 	read_bytes = read((int)f, p, size*count);
793 	return read_bytes>0? (read_bytes/size) : 0;
794 }
795 
fwrite(const void * p,size_t size,size_t count,FILE * f)796 size_t __cdecl fwrite(const void *p, size_t size, size_t count, FILE * f)
797 {
798 	int write_bytes;
799 	if(!f || !p || size==0 || count==0) return 0;
800 	write_bytes = write((int)f, p, size*count);
801 	return write_bytes>0? write_bytes/size : 0;
802 }
803 
fflush(FILE * f)804 int    __cdecl fflush(FILE *f)
805 {
806 	return 0;
807 }
808 
feof(FILE * f)809 int    __cdecl feof(FILE *f)
810 {
811 	return (f && eof((int)f)==0)? 0 : 1;
812 }
813 
fseek(FILE * f,long offset,int from)814 int    __cdecl fseek(FILE *f, long offset, int from)
815 {
816 	return (f && lseek((int)f, offset, from)>=0)? 0 : 1;
817 }
818 
ftell(FILE * f)819 long   __cdecl ftell(FILE * f)
820 {
821 	return f? lseek((int)f, 0, SEEK_CUR) : -1;
822 }
823 
824 #endif
825