OSDN Git Service

Initial Import
[nethackexpress/trunk.git] / sys / wince / celib.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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  */
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
368 void Delay(int ms)
369 {
370         (void)Sleep(ms);
371 }
372
373 void more()
374 {
375
376 }
377
378 int isatty(int f)
379 {
380         return 0;
381 }
382
383
384 #if defined(WIN_CE_PS2xx) || defined(WIN32_PLATFORM_HPCPRO)
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
396 int __cdecl isdigit(int c)
397 {
398         return  ('0' <= c && c <= '9');
399 }
400
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
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
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
430 char* __cdecl _strdup(const char* s)
431 {
432         char* p;
433         p = malloc(strlen(s)+1);
434         return strcpy(p, s);
435 }
436
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
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
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
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
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
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
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
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
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
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);
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
777 FILE*  __cdecl _getstdfilex(int desc)
778 {
779         return NULL;
780 }
781
782 int __cdecl fclose(FILE * f)
783 {
784         if(!f) return EOF;
785         return close((int)f)==-1? EOF : 0;
786 }
787
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
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
804 int    __cdecl fflush(FILE *f)
805
806         return 0;
807 }
808
809 int    __cdecl feof(FILE *f)
810 {
811         return (f && eof((int)f)==0)? 0 : 1;
812 }
813
814 int    __cdecl fseek(FILE *f, long offset, int from)
815 {
816         return (f && lseek((int)f, offset, from)>=0)? 0 : 1;
817 }
818
819 long   __cdecl ftell(FILE * f)
820 {
821         return f? lseek((int)f, 0, SEEK_CUR) : -1;
822 }
823
824 #endif