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