1 /**
2  * D header file for C99 <stdio.h>
3  *
4  * $(C_HEADER_DESCRIPTION pubs.opengroup.org/onlinepubs/009695399/basedefs/_stdio.h.html, _stdio.h)
5  *
6  * Copyright: Copyright Sean Kelly 2005 - 2009.
7  * License: Distributed under the
8  *      $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
9  *    (See accompanying file LICENSE)
10  * Authors:   Sean Kelly,
11  *            Alex Rønne Petersen
12  * Source:    https://github.com/dlang/dmd/blob/master/druntime/src/core/stdc/stdio.d
13  * Standards: ISO/IEC 9899:1999 (E)
14  */
15 
16 module core.stdc.stdio;
17 
18 version (OSX)
19     version = Darwin;
20 else version (iOS)
21     version = Darwin;
22 else version (TVOS)
23     version = Darwin;
24 else version (WatchOS)
25     version = Darwin;
26 
27 private
28 {
29     import core.stdc.config;
30     import core.stdc.stdarg; // for va_list
31     import core.stdc.stdint : intptr_t;
32 
33   version (FreeBSD)
34   {
35     import core.sys.posix.sys.types;
36   }
37   else version (OpenBSD)
38   {
39     import core.sys.posix.sys.types;
40   }
41   version (NetBSD)
42   {
43     import core.sys.posix.sys.types;
44   }
45   version (DragonFlyBSD)
46   {
47     import core.sys.posix.sys.types;
48   }
49 }
50 
51 extern (C):
52 nothrow:
53 @nogc:
54 
55 version (CRuntime_DigitalMars)
56 {
57     enum
58     {
59         ///
60         BUFSIZ       = 0x4000,
61         ///
62         EOF          = -1,
63         ///
64         FOPEN_MAX    = 20,
65         ///
66         FILENAME_MAX = 256, // 255 plus NULL
67         ///
68         TMP_MAX      = 32767,
69         ///
70         SYS_OPEN     = 20,      // non-standard
71     }
72 
73     ///
74     enum int     _NFILE     = 60;       // non-standard
75     ///
76     enum string  _P_tmpdir  = "\\"; // non-standard
77     ///
78     enum wstring _wP_tmpdir = "\\"; // non-standard
79     ///
80     enum int     L_tmpnam   = _P_tmpdir.length + 12;
81 }
82 else version (CRuntime_Microsoft)
83 {
84     enum
85     {
86         ///
87         BUFSIZ       = 512,
88         ///
89         EOF          = -1,
90         ///
91         FOPEN_MAX    = 20,
92         ///
93         FILENAME_MAX = 260,
94         /// Actually int.max since Visual Studio 2015.
95         TMP_MAX      = 32767,
96         ///
97         _SYS_OPEN    = 20,      // non-standard
98     }
99 
100     ///
101     enum int     _NFILE     = 512;       // non-standard
102     /// Removed since Visual Studio 2015.
103     enum string  _P_tmpdir  = "\\"; // non-standard
104     /// Removed since Visual Studio 2015.
105     enum wstring _wP_tmpdir = "\\"; // non-standard
106     /// Actually 260 since Visual Studio 2015.
107     enum int     L_tmpnam   = _P_tmpdir.length + 12;
108 }
109 else version (CRuntime_Glibc)
110 {
111     enum
112     {
113         ///
114         BUFSIZ       = 8192,
115         ///
116         EOF          = -1,
117         ///
118         FOPEN_MAX    = 16,
119         ///
120         FILENAME_MAX = 4095,
121         ///
122         TMP_MAX      = 238328,
123         ///
124         L_tmpnam     = 20
125     }
126 }
127 else version (CRuntime_Musl)
128 {
129     enum
130     {
131         ///
132         BUFSIZ       = 1024,
133         ///
134         EOF          = -1,
135         ///
136         FOPEN_MAX    = 1000,
137         ///
138         FILENAME_MAX = 4096,
139         ///
140         TMP_MAX      = 10000,
141         ///
142         L_tmpnam     = 20
143     }
144 }
145 else version (Darwin)
146 {
147     enum
148     {
149         ///
150         BUFSIZ       = 1024,
151         ///
152         EOF          = -1,
153         ///
154         FOPEN_MAX    = 20,
155         ///
156         FILENAME_MAX = 1024,
157         ///
158         TMP_MAX      = 308915776,
159         ///
160         L_tmpnam     = 1024,
161     }
162 
163     private
164     {
165         struct __sbuf
166         {
167             ubyte*  _base;
168             int     _size;
169         }
170 
171         struct __sFILEX
172         {
173 
174         }
175     }
176 }
177 else version (FreeBSD)
178 {
179     enum
180     {
181         ///
182         BUFSIZ       = 1024,
183         ///
184         EOF          = -1,
185         ///
186         FOPEN_MAX    = 20,
187         ///
188         FILENAME_MAX = 1024,
189         ///
190         TMP_MAX      = 308915776,
191         ///
192         L_tmpnam     = 1024
193     }
194 
195     struct __sbuf
196     {
197         ubyte *_base;
198         int _size;
199     }
200 }
201 else version (NetBSD)
202 {
203     enum
204     {
205         ///
206         BUFSIZ       = 1024,
207         ///
208         EOF          = -1,
209         ///
210         FOPEN_MAX    = 20,
211         ///
212         FILENAME_MAX = 1024,
213         ///
214         TMP_MAX      = 308915776,
215         ///
216         L_tmpnam     = 1024
217     }
218 
219     struct __sbuf
220     {
221         ubyte *_base;
222         int _size;
223     }
224 }
225 else version (OpenBSD)
226 {
227     enum
228     {
229         ///
230         BUFSIZ       = 1024,
231         ///
232         EOF          = -1,
233         ///
234         FOPEN_MAX    = 20,
235         ///
236         FILENAME_MAX = 1024,
237         ///
238         TMP_MAX      = 0x7fffffff,
239         ///
240         L_tmpnam     = 1024
241     }
242 
243     struct __sbuf
244     {
245         ubyte *_base;
246         int _size;
247     }
248 }
249 else version (DragonFlyBSD)
250 {
251     enum
252     {
253         BUFSIZ       = 1024,
254         EOF          = -1,
255         FOPEN_MAX    = 20,
256         FILENAME_MAX = 1024,
257         TMP_MAX      = 308915776,
258         L_tmpnam     = 1024
259     }
260 
261     struct __sbuf {                     // <sys/sbuf.h>
262         byte*            s_buf;         // storage buffer
263         int function(void *, const char *, int) sbuf_drain_func;
264         void*            s_drain_arg;   // user-supplied drain argument
265         int              s_error;       // current error code
266         ssize_t          s_size;        // size of storage buffer
267         ssize_t          s_len;         // current length of string
268         int              s_flags;       // flags
269         ssize_t          s_sect_len;    // current length of section
270     }
271 
272     enum {
273         SBUF_FIXEDLEN   = 0x00000000,   // fixed length buffer (default)
274         SBUF_AUTOEXTEND = 0x00000001,   // automatically extend buffer
275         SBUF_USRFLAGMSK = 0x0000ffff,   // mask of flags the user may specify
276         SBUF_DYNAMIC    = 0x00010000,   // s_buf must be freed
277         SBUF_FINISHED   = 0x00020000,   // set by sbuf_finish()
278         SBUF_DYNSTRUCT  = 0x00080000,   // sbuf must be freed
279         SBUF_INSECTION  = 0x00100000,   // set by sbuf_start_section()
280     }
281 }
282 else version (Solaris)
283 {
284     enum
285     {
286         ///
287         BUFSIZ = 1024,
288         ///
289         EOF = -1,
290         ///
291         FOPEN_MAX = _NFILE,
292         ///
293         FILENAME_MAX = 1024,
294         ///
295         TMP_MAX = 17576,
296         ///
297         L_tmpnam = 25,
298     }
299 
300     version (X86)
301         ///
302         enum int _NFILE = 60;
303     else
304         ///
305         enum int _NFILE = 20;
306 }
307 else version (CRuntime_Bionic)
308 {
309     enum
310     {
311         ///
312         BUFSIZ       = 1024,
313         ///
314         EOF          = -1,
315         ///
316         FOPEN_MAX    = 20,
317         ///
318         FILENAME_MAX = 1024,
319         ///
320         TMP_MAX      = 308915776,
321         ///
322         L_tmpnam     = 1024
323     }
324 
325     struct __sbuf
326     {
327         ubyte* _base;
328         int _size;
329     }
330 }
331 else version (CRuntime_UClibc)
332 {
333     enum
334     {
335         ///
336         BUFSIZ       = 4096,
337         ///
338         EOF          = -1,
339         ///
340         FOPEN_MAX    = 16,
341         ///
342         FILENAME_MAX = 4095,
343         ///
344         TMP_MAX      = 238328,
345         ///
346         L_tmpnam     = 20
347     }
348 }
349 else version (WASI)
350 {
351     enum
352     {
353         ///
354         BUFSIZ       = 1024,
355         ///
356         EOF          = -1,
357         ///
358         FOPEN_MAX    = 1000,
359         ///
360         FILENAME_MAX = 4096,
361         ///
362         TMP_MAX      = 10000,
363         ///
364         L_tmpnam     = 20
365     }
366 }
367 else
368 {
369     static assert( false, "Unsupported platform" );
370 }
371 
372 enum
373 {
374     /// Offset is relative to the beginning
375     SEEK_SET,
376     /// Offset is relative to the current position
377     SEEK_CUR,
378     /// Offset is relative to the end
379     SEEK_END
380 }
381 
382 version (CRuntime_DigitalMars)
383 {
384     ///
385     alias c_long fpos_t;
386 
387     ///
388     struct _iobuf
389     {
390         char* _ptr;
391         int   _cnt;
392         char* _base;
393         int   _flag;
394         int   _file;
395         int   _charbuf;
396         int   _bufsiz;
397         char* __tmpnum;
398     }
399 
400     ///
401     alias shared(_iobuf) FILE;
402 }
403 else version (CRuntime_Microsoft)
404 {
405     ///
406     alias long fpos_t;
407 
408     ///
409     struct _iobuf
410     {
411         void* undefined;
412     }
413 
414     ///
415     alias shared(_iobuf) FILE;
416 }
417 else version (CRuntime_Glibc)
418 {
419     import core.stdc.wchar_ : mbstate_t;
420     ///
421     struct fpos_t
422     {
423         long __pos; // couldn't use off_t because of static if issue
424         mbstate_t __state;
425     }
426 
427     ///
428     struct _IO_FILE
429     {
430         int     _flags;
431         char*   _read_ptr;
432         char*   _read_end;
433         char*   _read_base;
434         char*   _write_base;
435         char*   _write_ptr;
436         char*   _write_end;
437         char*   _buf_base;
438         char*   _buf_end;
439         char*   _save_base;
440         char*   _backup_base;
441         char*   _save_end;
442         void*   _markers;
443         _IO_FILE* _chain;
444         int     _fileno;
445         int     _flags2;
446         ptrdiff_t _old_offset;
447         ushort  _cur_column;
448         byte    _vtable_offset;
449         char[1] _shortbuf = 0;
450         void*   _lock;
451 
452         ptrdiff_t _offset;
453 
454         /*_IO_codecvt*/ void* _codecvt;
455         /*_IO_wide_data*/ void* _wide_data;
456         _IO_FILE *_freeres_list;
457         void *_freeres_buf;
458         size_t __pad5;
459         int _mode;
460 
461         char[15 * int.sizeof - 4 * (void*).sizeof - size_t.sizeof] _unused2;
462     }
463 
464     ///
465     alias _IO_FILE _iobuf;
466     ///
467     alias shared(_IO_FILE) FILE;
468 }
469 else version (WASI)
470 {
471     union fpos_t
472     {
473         char[16] __opaque = 0;
474         double __align;
475     }
476     struct _IO_FILE;
477 
478     ///
479     alias _IO_FILE _iobuf; // needed for phobos
480     ///
481     alias shared(_IO_FILE) FILE;
482 }
483 else version (CRuntime_Musl)
484 {
485     union fpos_t
486     {
487         char[16] __opaque = 0;
488         double __align;
489     }
490     struct _IO_FILE;
491 
492     ///
493     alias _IO_FILE _iobuf; // needed for phobos
494     ///
495     alias shared(_IO_FILE) FILE;
496 }
497 else version (Darwin)
498 {
499     ///
500     alias long fpos_t;
501 
502     ///
503     struct __sFILE
504     {
505         ubyte*    _p;
506         int       _r;
507         int       _w;
508         short     _flags;
509         short     _file;
510         __sbuf    _bf;
511         int       _lbfsize;
512 
513         void*     _cookie;
514         int     function(void*)                    _close;
515         int     function(void*, char*, int)        _read;
516         fpos_t  function(void*, fpos_t, int)       _seek;
517         int     function(void*, char *, int)       _write;
518 
519         __sbuf    _ub;
520         __sFILEX* _extra;
521         int       _ur;
522 
523         ubyte[3]  _ubuf;
524         ubyte[1]  _nbuf;
525 
526         __sbuf    _lb;
527 
528         int       _blksize;
529         fpos_t    _offset;
530     }
531 
532     ///
533     alias __sFILE _iobuf;
534     ///
535     alias shared(__sFILE) FILE;
536 }
537 else version (FreeBSD)
538 {
539     // Need to import wchar_ now since __mbstate_t now resides there
540     import core.stdc.wchar_ : mbstate_t;
541 
542     ///
543     alias off_t fpos_t;
544 
545     ///
546     struct __sFILE
547     {
548         ubyte*          _p;
549         int             _r;
550         int             _w;
551         short           _flags;
552         short           _file;
553         __sbuf          _bf;
554         int             _lbfsize;
555 
556         void*           _cookie;
557         int     function(void*)                 _close;
558         int     function(void*, char*, int)     _read;
559         fpos_t  function(void*, fpos_t, int)    _seek;
560         int     function(void*, const scope char*, int)  _write;
561 
562         __sbuf          _ub;
563         ubyte*          _up;
564         int             _ur;
565 
566         ubyte[3]        _ubuf;
567         ubyte[1]        _nbuf;
568 
569         __sbuf          _lb;
570 
571         int             _blksize;
572         fpos_t          _offset;
573 
574         pthread_mutex_t _fl_mutex;
575         pthread_t       _fl_owner;
576         int             _fl_count;
577         int             _orientation;
578         mbstate_t       _mbstate;
579     }
580 
581     ///
582     alias __sFILE _iobuf;
583     ///
584     alias shared(__sFILE) FILE;
585 }
586 else version (NetBSD)
587 {
588     ///
589     alias off_t fpos_t;
590 
591     ///
592     struct __sFILE
593     {
594         ubyte*          _p;
595         int             _r;
596         int             _w;
597         ushort           _flags;
598         short           _file;
599         __sbuf          _bf;
600         int             _lbfsize;
601 
602         void*           _cookie;
603         int     function(void*)                 _close;
604         ssize_t     function(void*, char*, size_t)     _read;
605         fpos_t  function(void*, fpos_t, int)    _seek;
606         ssize_t     function(void*, const scope char*, size_t)  _write;
607 
608         __sbuf          _ub;
609         ubyte*          _up;
610         int             _ur;
611 
612         ubyte[3]        _ubuf;
613         ubyte[1]        _nbuf;
614 
615         int     function(void *)    _flush;
616         /* Formerly used by fgetln/fgetwln; kept for binary compatibility */
617         char[__sbuf.sizeof - _flush.sizeof]    _lb_unused = void;
618 
619 
620         int             _blksize;
621         off_t          _offset;
622         static assert(off_t.sizeof==8);
623     }
624 
625     ///
626     alias __sFILE _iobuf;
627     ///
628     alias shared(__sFILE) FILE;
629 }
630 else version (OpenBSD)
631 {
632     ///
633     alias fpos_t = off_t;
634 
635     ///
636     struct __sFILE
637     {
638         ubyte*          _p;
639         int             _r;
640         int             _w;
641         short           _flags;
642         short           _file;
643         __sbuf          _bf;
644         int             _lbfsize;
645 
646         void*           _cookie;
647         int     function(void*)                         _close;
648         int     function(void*, scope char*, int)       _read;
649         fpos_t  function(void*, fpos_t, int)            _seek;
650         int     function(void*, scope const char*, int) _write;
651 
652         __sbuf          _ext;
653         ubyte*          _up;
654         int             _ur;
655 
656         ubyte[3]        _ubuf;
657         ubyte[1]        _nbuf;
658 
659         __sbuf          _lb;
660 
661         int             _blksize;
662         fpos_t          _offset;
663     }
664 
665     ///
666     alias __sFILE _iobuf;
667     ///
668     alias shared(__sFILE) FILE;
669 }
670 else version (DragonFlyBSD)
671 {
672     alias off_t fpos_t;
673 
674     /// See /usr/include/stdio.h
675     struct __FILE_public
676     {
677         ubyte*          *_p;            /* current position in (some) buffer */
678         int             _flags;         /* flags, below; this FILE is free if 0 */
679         int             _fileno;        /* fileno, if Unix descriptor, else -1 */
680         ssize_t         _r;             /* read space left for getc() */
681         ssize_t         _w;             /* write space left for putc() */
682         ssize_t         _lbfsize;       /* 0 or -_bf._size, for inline putc */
683     }
684 
685     alias __FILE_public _iobuf;
686     alias shared(__FILE_public) FILE;
687 }
688 else version (Solaris)
689 {
690     import core.stdc.wchar_ : mbstate_t;
691 
692     ///
693     alias c_long fpos_t;
694 
695     version (D_LP64)
696     {
697         ///
698         struct _iobuf
699         {
700             char*      _ptr;   /* next character from/to here in buffer */
701             char*      _base;  /* the buffer */
702             char*      _end;   /* the end of the buffer */
703             size_t     _cnt;   /* number of available characters in buffer */
704             int        _file;  /* UNIX System file descriptor */
705             int        _flag;  /* the state of the stream */
706             ubyte[24]  _lock;  //rmutex_t   _lock; /* lock for this structure */
707             mbstate_t  _state; /* mbstate_t */
708             ubyte[32]  __fill; /* filler to bring size to 128 bytes */
709         }
710     }
711     else
712     {
713         ///
714         struct _iobuf
715         {
716             char* _ptr;
717             int _cnt;
718             char* _base;
719             char _flag = 0;
720             char _magic = 0;
721             ushort __flags; // __orientation:2
722                             // __ionolock:1
723                             // __seekable:1
724                             // __extendedfd:1
725                             // __xf_nocheck:1
726                             // __filler:10
727         }
728     }
729     ///
730     alias shared(_iobuf) FILE;
731 }
732 else version (CRuntime_Bionic)
733 {
734     ///
735     alias c_long fpos_t; // couldn't use off_t because of static if issue
736 
737     ///
738     struct __sFILE
739     {
740         ubyte*    _p;
741         int       _r;
742         int       _w;
743         short     _flags;
744         short     _file;
745         __sbuf    _bf;
746         int       _lbfsize;
747 
748         void*     _cookie;
749         int      function(void*)                          _close;
750         int      function(void*, scope char*, int)        _read;
751         fpos_t   function(void*, fpos_t, int)             _seek;
752         int      function(void*, scope const char*, int)  _write;
753 
754         __sbuf    _ext;
755         ubyte*    _up;
756         int       _ur;
757 
758         ubyte[3]  _ubuf;
759         ubyte[1]  _nbuf;
760 
761         __sbuf    _lb;
762 
763         int       _blksize;
764         fpos_t    _offset;
765     }
766 
767     ///
768     alias __sFILE _iobuf;
769     ///
770     alias shared(__sFILE) FILE;
771 }
772 else version (CRuntime_UClibc)
773 {
774     import core.stdc.wchar_ : mbstate_t;
775     import core.stdc.stddef : wchar_t;
776     import core.sys.posix.sys.types : ssize_t, pthread_mutex_t;
777 
778     ///
779     struct fpos_t
780     {
781         long __pos; // couldn't use off_t because of static if issue
782         mbstate_t __state;
783         int __mblen_pending;
784     }
785 
786     struct _IO_cookie_io_functions_t
787     {
788        ssize_t function(void* __cookie, char* __buf, size_t __bufsize)          read;
789        ssize_t function(void* __cookie, const char* __buf, size_t __bufsize)    write;
790        int function(void* __cookie, long* __pos, int __whence)                  seek;
791        int function(void* __cookie)                                             close;
792     }
793 
794     alias _IO_cookie_io_functions_t cookie_io_functions_t;
795 
796     ///
797     struct __STDIO_FILE_STRUCT
798     {
799         ushort __modeflags;
800         char[2] __ungot_width = 0;
801         int __filedes;
802         char* __bufstart;
803         char* __bufend;
804         char* __bufpos;
805         char* __bufread;
806         char* __bufgetc_u;
807         char*__bufputc_u;
808         __STDIO_FILE_STRUCT* __nextopen;
809         void *__cookie;
810         _IO_cookie_io_functions_t __gcs;
811         wchar_t[2] __ungot = 0;
812         mbstate_t __state;
813         void *__unused;
814         int __user_locking;
815         pthread_mutex_t __lock;
816     }
817 
818     ///
819     alias __STDIO_FILE_STRUCT _iobuf;
820     ///
821     alias shared(__STDIO_FILE_STRUCT) FILE;
822 }
823 else
824 {
825     static assert( false, "Unsupported platform" );
826 }
827 
828 enum
829 {
830     ///
831     _F_RDWR = 0x0003, // non-standard
832     ///
833     _F_READ = 0x0001, // non-standard
834     ///
835     _F_WRIT = 0x0002, // non-standard
836     ///
837     _F_BUF  = 0x0004, // non-standard
838     ///
839     _F_LBUF = 0x0008, // non-standard
840     ///
841     _F_ERR  = 0x0010, // non-standard
842     ///
843     _F_EOF  = 0x0020, // non-standard
844     ///
845     _F_BIN  = 0x0040, // non-standard
846     ///
847     _F_IN   = 0x0080, // non-standard
848     ///
849     _F_OUT  = 0x0100, // non-standard
850     ///
851     _F_TERM = 0x0200, // non-standard
852 }
853 
854 version (CRuntime_DigitalMars)
855 {
856     enum
857     {
858         ///
859         _IOFBF   = 0,
860         ///
861         _IOLBF   = 0x40,
862         ///
863         _IONBF   = 4,
864         ///
865         _IOREAD  = 1,     // non-standard
866         ///
867         _IOWRT   = 2,     // non-standard
868         ///
869         _IOMYBUF = 8,     // non-standard
870         ///
871         _IOEOF   = 0x10,  // non-standard
872         ///
873         _IOERR   = 0x20,  // non-standard
874         ///
875         _IOSTRG  = 0x40,  // non-standard
876         ///
877         _IORW    = 0x80,  // non-standard
878         ///
879         _IOTRAN  = 0x100, // non-standard
880         ///
881         _IOAPP   = 0x200, // non-standard
882     }
883 
884     extern shared void function() _fcloseallp;
885 
886     private extern shared FILE[_NFILE] _iob;
887 
888     ///
889     enum stdin  = &_iob[0];
890     ///
891     enum stdout = &_iob[1];
892     ///
893     enum stderr = &_iob[2];
894     ///
895     enum stdaux = &_iob[3];
896     ///
897     enum stdprn = &_iob[4];
898 }
899 else version (CRuntime_Microsoft)
900 {
901     enum
902     {
903         ///
904         _IOFBF   = 0,
905         ///
906         _IOLBF   = 0x40,
907         ///
908         _IONBF   = 4,
909         /// Removed since Visual Studio 2015.
910         _IOREAD  = 1,     // non-standard
911         /// Removed since Visual Studio 2015.
912         _IOWRT   = 2,     // non-standard
913         /// Removed since Visual Studio 2015.
914         _IOMYBUF = 8,     // non-standard
915         /// Removed since Visual Studio 2015.
916         _IOEOF   = 0x10,  // non-standard
917         /// Removed since Visual Studio 2015.
918         _IOERR   = 0x20,  // non-standard
919         /// Removed since Visual Studio 2015.
920         _IOSTRG  = 0x40,  // non-standard
921         /// Removed since Visual Studio 2015.
922         _IORW    = 0x80,  // non-standard
923         /// Removed since Visual Studio 2015.
924         _IOAPP   = 0x200, // non-standard
925         /// Removed since Visual Studio 2015.
926         _IOAPPEND = 0x200, // non-standard
927     }
928 
929     extern shared void function() _fcloseallp;
930 
931     FILE* __acrt_iob_func(int hnd);     // VS2015+, reimplemented in msvc.d for VS2013-
932 
933     ///
934     FILE* stdin()() { return __acrt_iob_func(0); }
935     ///
936     FILE* stdout()() { return __acrt_iob_func(1); }
937     ///
938     FILE* stderr()() { return __acrt_iob_func(2); }
939 }
940 else version (CRuntime_Glibc)
941 {
942     enum
943     {
944         ///
945         _IOFBF = 0,
946         ///
947         _IOLBF = 1,
948         ///
949         _IONBF = 2,
950     }
951 
952     ///
953     extern shared FILE* stdin;
954     ///
955     extern shared FILE* stdout;
956     ///
957     extern shared FILE* stderr;
958 }
959 else version (Darwin)
960 {
961     enum
962     {
963         ///
964         _IOFBF = 0,
965         ///
966         _IOLBF = 1,
967         ///
968         _IONBF = 2,
969     }
970 
971     private extern shared FILE* __stdinp;
972     private extern shared FILE* __stdoutp;
973     private extern shared FILE* __stderrp;
974 
975     ///
976     alias __stdinp  stdin;
977     ///
978     alias __stdoutp stdout;
979     ///
980     alias __stderrp stderr;
981 }
982 else version (FreeBSD)
983 {
984     enum
985     {
986         ///
987         _IOFBF = 0,
988         ///
989         _IOLBF = 1,
990         ///
991         _IONBF = 2,
992     }
993 
994     private extern shared FILE* __stdinp;
995     private extern shared FILE* __stdoutp;
996     private extern shared FILE* __stderrp;
997 
998     ///
999     alias __stdinp  stdin;
1000     ///
1001     alias __stdoutp stdout;
1002     ///
1003     alias __stderrp stderr;
1004 }
1005 else version (NetBSD)
1006 {
1007     enum
1008     {
1009         ///
1010         _IOFBF = 0,
1011         ///
1012         _IOLBF = 1,
1013         ///
1014         _IONBF = 2,
1015     }
1016 
1017     private extern shared FILE[3] __sF;
1018     @property auto __stdin()() { return &__sF[0]; }
1019     @property auto __stdout()() { return &__sF[1]; }
1020     @property auto __stderr()() { return &__sF[2]; }
1021     ///
1022     alias __stdin stdin;
1023     ///
1024     alias __stdout stdout;
1025     ///
1026     alias __stderr stderr;
1027 }
1028 else version (OpenBSD)
1029 {
1030     enum
1031     {
1032         ///
1033         _IOFBF = 0,
1034         ///
1035         _IOLBF = 1,
1036         ///
1037         _IONBF = 2,
1038     }
1039 
1040     private extern shared FILE[3] __sF;
1041     @property auto __stdin()() { return &__sF[0]; }
1042     @property auto __stdout()() { return &__sF[1]; }
1043     @property auto __stderr()() { return &__sF[2]; }
1044     ///
1045     alias __stdin stdin;
1046     ///
1047     alias __stdout stdout;
1048     ///
1049     alias __stderr stderr;
1050 }
1051 else version (DragonFlyBSD)
1052 {
1053     enum
1054     {
1055         _IOFBF = 0,
1056         _IOLBF = 1,
1057         _IONBF = 2,
1058     }
1059 
1060     private extern shared FILE* __stdinp;
1061     private extern shared FILE* __stdoutp;
1062     private extern shared FILE* __stderrp;
1063 
1064     alias __stdinp  stdin;
1065     alias __stdoutp stdout;
1066     alias __stderrp stderr;
1067 }
1068 else version (Solaris)
1069 {
1070     enum
1071     {
1072         ///
1073         _IOFBF = 0x00,
1074         ///
1075         _IOLBF = 0x40,
1076         ///
1077         _IONBF = 0x04,
1078         ///
1079         _IOEOF = 0x20,
1080         ///
1081         _IOERR = 0x40,
1082         ///
1083         _IOREAD = 0x01,
1084         ///
1085         _IOWRT = 0x02,
1086         ///
1087         _IORW = 0x80,
1088         ///
1089         _IOMYBUF = 0x08,
1090     }
1091 
1092     private extern shared FILE[_NFILE] __iob;
1093 
1094     ///
1095     @property auto stdin()() { return &__iob[0]; }
1096     ///
1097     @property auto stdout()() { return &__iob[1]; }
1098     ///
1099     @property auto stderr()() { return &__iob[2]; }
1100 }
1101 else version (CRuntime_Bionic)
1102 {
1103     enum
1104     {
1105         ///
1106         _IOFBF = 0,
1107         ///
1108         _IOLBF = 1,
1109         ///
1110         _IONBF = 2,
1111     }
1112 
1113     private extern shared FILE[3] __sF;
1114 
1115     ///
1116     @property auto stdin()() { return &__sF[0]; }
1117     ///
1118     @property auto stdout()() { return &__sF[1]; }
1119     ///
1120     @property auto stderr()() { return &__sF[2]; }
1121 }
1122 else version (CRuntime_Musl)
1123 {
1124     // needs tail const
1125     extern shared FILE* stdin;
1126     ///
1127     extern shared FILE* stdout;
1128     ///
1129     extern shared FILE* stderr;
1130     enum
1131     {
1132         ///
1133         _IOFBF = 0,
1134         ///
1135         _IOLBF = 1,
1136         ///
1137         _IONBF = 2,
1138     }
1139 }
1140 else version (CRuntime_UClibc)
1141 {
1142     enum
1143     {
1144         ///
1145         _IOFBF = 0,
1146         ///
1147         _IOLBF = 1,
1148         ///
1149         _IONBF = 2,
1150     }
1151 
1152     ///
1153     extern shared FILE* stdin;
1154     ///
1155     extern shared FILE* stdout;
1156     ///
1157     extern shared FILE* stderr;
1158 }
1159 else version (WASI)
1160 {
1161     // needs tail const
1162     extern shared FILE* stdin;
1163     ///
1164     extern shared FILE* stdout;
1165     ///
1166     extern shared FILE* stderr;
1167     enum
1168     {
1169         ///
1170         _IOFBF = 0,
1171         ///
1172         _IOLBF = 1,
1173         ///
1174         _IONBF = 2,
1175     }
1176 }
1177 else
1178 {
1179     static assert( false, "Unsupported platform" );
1180 }
1181 
1182 ///
1183 int remove(scope const char* filename);
1184 ///
1185 int rename(scope const char* from, scope const char* to);
1186 
1187 ///
1188 @trusted FILE* tmpfile(); // No unsafe pointer manipulation.
1189 ///
1190 char* tmpnam(char* s);
1191 
1192 ///
1193 int   fclose(FILE* stream);
1194 
1195 // No unsafe pointer manipulation.
1196 @trusted
1197 {
1198     ///
1199     int   fflush(FILE* stream);
1200 }
1201 
1202 ///
1203 FILE* fopen(scope const char* filename, scope const char* mode);
1204 ///
1205 FILE* freopen(scope const char* filename, scope const char* mode, FILE* stream);
1206 
1207 ///
1208 void setbuf(FILE* stream, char* buf);
1209 ///
1210 int  setvbuf(FILE* stream, char* buf, int mode, size_t size);
1211 
1212 version (MinGW)
1213 {
1214     // Prefer the MinGW versions over the MSVC ones, as the latter don't handle
1215     // reals at all.
1216     ///
1217     pragma(printf)
1218     int __mingw_fprintf(FILE* stream, scope const char* format, scope const ...);
1219     ///
1220     alias __mingw_fprintf fprintf;
1221 
1222     ///
1223     pragma(scanf)
1224     int __mingw_fscanf(FILE* stream, scope const char* format, scope ...);
1225     ///
1226     alias __mingw_fscanf fscanf;
1227 
1228     ///
1229     pragma(printf)
1230     int __mingw_sprintf(scope char* s, scope const char* format, scope const ...);
1231     ///
1232     alias __mingw_sprintf sprintf;
1233 
1234     ///
1235     pragma(scanf)
1236     int __mingw_sscanf(scope const char* s, scope const char* format, scope ...);
1237     ///
1238     alias __mingw_sscanf sscanf;
1239 
1240     ///
1241     pragma(printf)
1242     int __mingw_vfprintf(FILE* stream, scope const char* format, va_list arg);
1243     ///
1244     alias __mingw_vfprintf vfprintf;
1245 
1246     ///
1247     pragma(scanf)
1248     int __mingw_vfscanf(FILE* stream, scope const char* format, va_list arg);
1249     ///
1250     alias __mingw_vfscanf vfscanf;
1251 
1252     ///
1253     pragma(printf)
1254     int __mingw_vsprintf(scope char* s, scope const char* format, va_list arg);
1255     ///
1256     alias __mingw_vsprintf vsprintf;
1257 
1258     ///
1259     pragma(scanf)
1260     int __mingw_vsscanf(scope const char* s, scope const char* format, va_list arg);
1261     ///
1262     alias __mingw_vsscanf vsscanf;
1263 
1264     ///
1265     pragma(printf)
1266     int __mingw_vprintf(scope const char* format, va_list arg);
1267     ///
1268     alias __mingw_vprintf vprintf;
1269 
1270     ///
1271     pragma(scanf)
1272     int __mingw_vscanf(scope const char* format, va_list arg);
1273     ///
1274     alias __mingw_vscanf vscanf;
1275 
1276     ///
1277     pragma(printf)
1278     int __mingw_printf(scope const char* format, scope const ...);
1279     ///
1280     alias __mingw_printf printf;
1281 
1282     ///
1283     pragma(scanf)
1284     int __mingw_scanf(scope const char* format, scope ...);
1285     ///
1286     alias __mingw_scanf scanf;
1287 }
1288 else version (CRuntime_Glibc)
1289 {
1290     ///
1291     pragma(printf)
1292     int fprintf(FILE* stream, scope const char* format, scope const ...);
1293     ///
1294     pragma(scanf)
1295     int __isoc99_fscanf(FILE* stream, scope const char* format, scope ...);
1296     ///
1297     alias fscanf = __isoc99_fscanf;
1298     ///
1299     pragma(printf)
1300     int sprintf(scope char* s, scope const char* format, scope const ...);
1301     ///
1302     pragma(scanf)
1303     int __isoc99_sscanf(scope const char* s, scope const char* format, scope ...);
1304     ///
1305     alias sscanf = __isoc99_sscanf;
1306     ///
1307     pragma(printf)
1308     int vfprintf(FILE* stream, scope const char* format, va_list arg);
1309     ///
1310     pragma(scanf)
1311     int __isoc99_vfscanf(FILE* stream, scope const char* format, va_list arg);
1312     ///
1313     alias vfscanf = __isoc99_vfscanf;
1314     ///
1315     pragma(printf)
1316     int vsprintf(scope char* s, scope const char* format, va_list arg);
1317     ///
1318     pragma(scanf)
1319     int __isoc99_vsscanf(scope const char* s, scope const char* format, va_list arg);
1320     ///
1321     alias vsscanf = __isoc99_vsscanf;
1322     ///
1323     pragma(printf)
1324     int vprintf(scope const char* format, va_list arg);
1325     ///
1326     pragma(scanf)
1327     int __isoc99_vscanf(scope const char* format, va_list arg);
1328     ///
1329     alias vscanf = __isoc99_vscanf;
1330     ///
1331     pragma(printf)
1332     int printf(scope const char* format, scope const ...);
1333     ///
1334     pragma(scanf)
1335     int __isoc99_scanf(scope const char* format, scope ...);
1336     ///
1337     alias scanf = __isoc99_scanf;
1338 }
1339 else
1340 {
1341     ///
1342     pragma(printf)
1343     int fprintf(FILE* stream, scope const char* format, scope const ...);
1344     ///
1345     pragma(scanf)
1346     int fscanf(FILE* stream, scope const char* format, scope ...);
1347     ///
1348     pragma(printf)
1349     int sprintf(scope char* s, scope const char* format, scope const ...);
1350     ///
1351     pragma(scanf)
1352     int sscanf(scope const char* s, scope const char* format, scope ...);
1353     ///
1354     pragma(printf)
1355     int vfprintf(FILE* stream, scope const char* format, va_list arg);
1356     ///
1357     pragma(scanf)
1358     int vfscanf(FILE* stream, scope const char* format, va_list arg);
1359     ///
1360     pragma(printf)
1361     int vsprintf(scope char* s, scope const char* format, va_list arg);
1362     ///
1363     pragma(scanf)
1364     int vsscanf(scope const char* s, scope const char* format, va_list arg);
1365     ///
1366     pragma(printf)
1367     int vprintf(scope const char* format, va_list arg);
1368     ///
1369     pragma(scanf)
1370     int vscanf(scope const char* format, va_list arg);
1371     ///
1372     pragma(printf)
1373     int printf(scope const char* format, scope const ...);
1374     ///
1375     pragma(scanf)
1376     int scanf(scope const char* format, scope ...);
1377 }
1378 
1379 // No unsafe pointer manipulation.
1380 @trusted
1381 {
1382     ///
1383     int fgetc(FILE* stream);
1384     ///
1385     int fputc(int c, FILE* stream);
1386 }
1387 
1388 ///
1389 char* fgets(char* s, int n, FILE* stream);
1390 ///
1391 int   fputs(scope const char* s, FILE* stream);
1392 ///
1393 char* gets(char* s);
1394 ///
1395 int   puts(scope const char* s);
1396 
1397 // No unsafe pointer manipulation.
1398 extern (D) @trusted
1399 {
1400     ///
1401     int getchar()()                 { return getc(stdin);     }
1402     ///
1403     int putchar()(int c)            { return putc(c,stdout);  }
1404 }
1405 
1406 ///
1407 alias getc = fgetc;
1408 ///
1409 alias putc = fputc;
1410 
1411 ///
1412 @trusted int ungetc(int c, FILE* stream); // No unsafe pointer manipulation.
1413 
1414 ///
1415 size_t fread(scope void* ptr, size_t size, size_t nmemb, FILE* stream);
1416 ///
1417 size_t fwrite(scope const void* ptr, size_t size, size_t nmemb, FILE* stream);
1418 
1419 // No unsafe pointer manipulation.
1420 @trusted
1421 {
1422     ///
1423     int fgetpos(FILE* stream, scope fpos_t * pos);
1424     ///
1425     int fsetpos(FILE* stream, scope const fpos_t* pos);
1426 
1427     ///
1428     int    fseek(FILE* stream, c_long offset, int whence);
1429     ///
1430     c_long ftell(FILE* stream);
1431 }
1432 
1433 version (CRuntime_DigitalMars)
1434 {
1435   // No unsafe pointer manipulation.
1436   extern (D) @trusted
1437   {
1438     ///
1439     void rewind()(FILE* stream)   { fseek(stream,0L,SEEK_SET); stream._flag= stream._flag & ~_IOERR; }
1440     ///
1441     pure void clearerr()(FILE* stream) { stream._flag = stream._flag & ~(_IOERR|_IOEOF); }
1442     ///
1443     pure int  feof()(FILE* stream)     { return stream._flag&_IOEOF; }
1444     ///
1445     pure int  ferror()(FILE* stream)   { return stream._flag&_IOERR; }
1446     ///
1447     pure int  fileno()(FILE* stream)   { return stream._file; }
1448   }
1449     ///
1450     pragma(printf)
1451     int   _snprintf(scope char* s, size_t n, scope const char* fmt, scope const ...);
1452     ///
1453     alias _snprintf snprintf;
1454 
1455     ///
1456     pragma(printf)
1457     int   _vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
1458     ///
1459     alias _vsnprintf vsnprintf;
1460 
1461     //
1462     // Digital Mars under-the-hood C I/O functions. Uses _iobuf* for the
1463     // unshared version of FILE*, usable when the FILE is locked.
1464     //
1465 
1466     ///
1467     int _fputc_nlock(int c, _iobuf* fp);
1468     ///
1469     int _fputwc_nlock(int c, _iobuf* fp);
1470     ///
1471     int _fgetc_nlock(_iobuf* fp);
1472     ///
1473     int _fgetwc_nlock(_iobuf* fp);
1474     ///
1475     int __fp_lock(FILE* fp);
1476     ///
1477     void __fp_unlock(FILE* fp);
1478     ///
1479     int setmode(int fd, int mode);
1480 }
1481 else version (CRuntime_Microsoft)
1482 {
1483   // No unsafe pointer manipulation.
1484   @trusted
1485   {
1486     ///
1487     void rewind(FILE* stream);
1488     ///
1489     pure void clearerr(FILE* stream);
1490     ///
1491     pure int  feof(FILE* stream);
1492     ///
1493     pure int  ferror(FILE* stream);
1494     ///
1495     pure int  fileno(FILE* stream);
1496   }
1497 
1498   version (MinGW)
1499   {
1500     pragma(printf)
1501     int   __mingw_snprintf(scope char* s, size_t n, scope const char* fmt, scope const ...);
1502     ///
1503     alias __mingw_snprintf _snprintf;
1504     ///
1505     alias __mingw_snprintf snprintf;
1506 
1507     ///
1508     pragma(printf)
1509     int   __mingw_vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
1510     ///
1511     alias __mingw_vsnprintf _vsnprintf;
1512     ///
1513     alias __mingw_vsnprintf vsnprintf;
1514   }
1515   else
1516   {
1517     ///
1518     pragma(printf)
1519     int _snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
1520     ///
1521     pragma(printf)
1522     int  snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
1523 
1524     ///
1525     pragma(printf)
1526     int _vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
1527     ///
1528     pragma(printf)
1529     int  vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
1530   }
1531 
1532     //
1533     // Microsoft under-the-hood C I/O functions. Uses _iobuf* for the unshared
1534     // version of FILE*, usable when the FILE is locked.
1535     //
1536     import core.stdc.stddef : wchar_t;
1537     import core.stdc.wchar_ : wint_t;
1538 
1539     ///
1540     int _fputc_nolock(int c, _iobuf* fp);
1541     ///
1542     int _fgetc_nolock(_iobuf* fp);
1543     ///
1544     wint_t _fputwc_nolock(wchar_t c, _iobuf* fp);
1545     ///
1546     wint_t _fgetwc_nolock(_iobuf* fp);
1547     ///
1548     void _lock_file(FILE* fp);
1549     ///
1550     void _unlock_file(FILE* fp);
1551     ///
1552     int _setmode(int fd, int mode);
1553     ///
1554     int _fseeki64(FILE* stream, long offset, int origin);
1555     ///
1556     long _ftelli64(FILE* stream);
1557     ///
1558     intptr_t _get_osfhandle(int fd);
1559     ///
1560     int _open_osfhandle(intptr_t osfhandle, int flags);
1561 }
1562 else version (CRuntime_Glibc)
1563 {
1564   // No unsafe pointer manipulation.
1565   @trusted
1566   {
1567     ///
1568     void rewind(FILE* stream);
1569     ///
1570     pure void clearerr(FILE* stream);
1571     ///
1572     pure int  feof(FILE* stream);
1573     ///
1574     pure int  ferror(FILE* stream);
1575     ///
1576     int  fileno(FILE *);
1577   }
1578 
1579     ///
1580     pragma(printf)
1581     int  snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
1582     ///
1583     pragma(printf)
1584     int  vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
1585 
1586     //
1587     // Gnu under-the-hood C I/O functions. Uses _iobuf* for the unshared
1588     // version of FILE*, usable when the FILE is locked.
1589     // See http://gnu.org/software/libc/manual/html_node/I_002fO-on-Streams.html
1590     //
1591     import core.stdc.wchar_ : wint_t;
1592     import core.stdc.stddef : wchar_t;
1593 
1594     ///
1595     int fputc_unlocked(int c, _iobuf* stream);
1596     ///
1597     int fgetc_unlocked(_iobuf* stream);
1598     ///
1599     wint_t fputwc_unlocked(wchar_t wc, _iobuf* stream);
1600     ///
1601     wint_t fgetwc_unlocked(_iobuf* stream);
1602 }
1603 else version (Darwin)
1604 {
1605   // No unsafe pointer manipulation.
1606   @trusted
1607   {
1608     ///
1609     void rewind(FILE*);
1610     ///
1611     pure void clearerr(FILE*);
1612     ///
1613     pure int  feof(FILE*);
1614     ///
1615     pure int  ferror(FILE*);
1616     ///
1617     int  fileno(FILE*);
1618   }
1619 
1620     ///
1621     pragma(printf)
1622     int  snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
1623     ///
1624     pragma(printf)
1625     int  vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
1626 }
1627 else version (FreeBSD)
1628 {
1629   // No unsafe pointer manipulation.
1630   @trusted
1631   {
1632     ///
1633     void rewind(FILE*);
1634     ///
1635     pure void clearerr(FILE*);
1636     ///
1637     pure int  feof(FILE*);
1638     ///
1639     pure int  ferror(FILE*);
1640     ///
1641     int  fileno(FILE*);
1642   }
1643 
1644     ///
1645     pragma(printf)
1646     int  snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
1647     ///
1648     pragma(printf)
1649     int  vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
1650 }
1651 else version (NetBSD)
1652 {
1653   // No unsafe pointer manipulation.
1654   @trusted
1655   {
1656     ///
1657     void rewind(FILE*);
1658     ///
1659     pure void clearerr(FILE*);
1660     ///
1661     pure int  feof(FILE*);
1662     ///
1663     pure int  ferror(FILE*);
1664     ///
1665     int  fileno(FILE*);
1666   }
1667 
1668     ///
1669     pragma(printf)
1670     int  snprintf(char* s, size_t n, const scope char* format, scope const ...);
1671     ///
1672     pragma(printf)
1673     int  vsnprintf(char* s, size_t n, const scope char* format, va_list arg);
1674 }
1675 else version (OpenBSD)
1676 {
1677     // No unsafe pointer manipulation.
1678     @trusted
1679     {
1680         ///
1681         void rewind(FILE*);
1682     }
1683     @trusted private
1684     {
1685         ///
1686         pragma(mangle, "clearerr")
1687         pure void __clearerr(FILE*);
1688         ///
1689         pragma(mangle, "feof")
1690         pure int __feof(FILE*);
1691         ///
1692         pragma(mangle, "ferror")
1693         pure int __ferror(FILE*);
1694         ///
1695         pragma(mangle, "fileno")
1696         int __fileno(FILE*);
1697     }
1698 
1699     enum __SLBF = 0x0001;
1700     enum __SNBF = 0x0002;
1701     enum __SRD  = 0x0004;
1702     enum __SWR  = 0x0008;
1703     enum __SRW  = 0x0010;
1704     enum __SEOF = 0x0020;
1705     enum __SERR = 0x0040;
1706     enum __SMBF = 0x0080;
1707     enum __SAPP = 0x0100;
1708     enum __SSTR = 0x0200;
1709     enum __SOPT = 0x0400;
1710     enum __SNPT = 0x0800;
1711     enum __SOFF = 0x1000;
1712     enum __SMOD = 0x2000;
1713     enum __SALC = 0x4000;
1714     enum __SIGN = 0x8000;
1715 
1716     extern immutable __gshared int __isthreaded;
1717 
1718     extern (D) @trusted
1719     {
1720         void __sclearerr()(FILE* p)
1721         {
1722             p._flags = p._flags & ~(__SERR|__SEOF);
1723         }
1724 
1725         int __sfeof()(FILE* p)
1726         {
1727             return (p._flags & __SEOF) != 0;
1728         }
1729 
1730         int __sferror()(FILE* p)
1731         {
1732             return (p._flags & __SERR) != 0;
1733         }
1734 
1735         int __sfileno()(FILE* p)
1736         {
1737             return p._file;
1738         }
1739 
1740         pure void clearerr()(FILE* file)
1741         {
1742             !__isthreaded ? __sclearerr(file) : __clearerr(file);
1743         }
1744 
1745         pure int feof()(FILE* file)
1746         {
1747             return !__isthreaded ? __sfeof(file) : __feof(file);
1748         }
1749 
1750         pure int ferror()(FILE* file)
1751         {
1752             return !__isthreaded ? __sferror(file) : __ferror(file);
1753         }
1754 
1755         int fileno()(FILE* file)
1756         {
1757             return !__isthreaded ? __sfileno(file) : __fileno(file);
1758         }
1759     }
1760 
1761     ///
1762     pragma(printf)
1763     int  snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
1764     ///
1765     pragma(printf)
1766     int  vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
1767 }
1768 else version (DragonFlyBSD)
1769 {
1770   // No unsafe pointer manipulation.
1771   @trusted
1772   {
1773     void rewind(FILE*);
1774     pure void clearerr(FILE*);
1775     pure int  feof(FILE*);
1776     pure int  ferror(FILE*);
1777     int  fileno(FILE*);
1778   }
1779   enum __SLBF = 0x0001;
1780   enum __SNBF = 0x0002;
1781   enum __SRD  = 0x0004;
1782   enum __SWR  = 0x0008;
1783   enum __SRW  = 0x0010;
1784   enum __SEOF = 0x0020;
1785   enum __SERR = 0x0040;
1786   enum __SMBF = 0x0080;
1787   enum __SAPP = 0x0100;
1788   enum __SSTR = 0x0200;
1789   enum __SOPT = 0x0400;
1790   enum __SNPT = 0x0800;
1791   enum __SOFF = 0x1000;
1792   enum __SMOD = 0x2000;
1793   enum __SALC = 0x4000;
1794   enum __SIGN = 0x8000;
1795 
1796     pragma(printf)
1797     int  snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
1798     pragma(printf)
1799     int  vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
1800 }
1801 else version (Solaris)
1802 {
1803   // No unsafe pointer manipulation.
1804   @trusted
1805   {
1806     ///
1807     void rewind(FILE*);
1808     ///
1809     pure void clearerr(FILE*);
1810     ///
1811     pure int  feof(FILE*);
1812     ///
1813     pure int  ferror(FILE*);
1814     ///
1815     int  fileno(FILE*);
1816   }
1817 
1818     ///
1819     pragma(printf)
1820     int  snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
1821     ///
1822     pragma(printf)
1823     int  vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
1824 }
1825 else version (CRuntime_Bionic)
1826 {
1827   // No unsafe pointer manipulation.
1828   @trusted
1829   {
1830     ///
1831     void rewind(FILE*);
1832     ///
1833     pure void clearerr(FILE*);
1834     ///
1835     pure int  feof(FILE*);
1836     ///
1837     pure int  ferror(FILE*);
1838     ///
1839     int  fileno(FILE*);
1840   }
1841 
1842     ///
1843     pragma(printf)
1844     int  snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
1845     ///
1846     pragma(printf)
1847     int  vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
1848 }
1849 else version (CRuntime_Musl)
1850 {
1851     @trusted
1852     {
1853         ///
1854         void rewind(FILE* stream);
1855         ///
1856         pure void clearerr(FILE* stream);
1857         ///
1858         pure int  feof(FILE* stream);
1859         ///
1860         pure int  ferror(FILE* stream);
1861         ///
1862         int  fileno(FILE *);
1863     }
1864 
1865     ///
1866     pragma(printf)
1867     int snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
1868     ///
1869     pragma(printf)
1870     int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
1871 }
1872 else version (CRuntime_UClibc)
1873 {
1874   // No unsafe pointer manipulation.
1875   @trusted
1876   {
1877     ///
1878     void rewind(FILE* stream);
1879     ///
1880     pure void clearerr(FILE* stream);
1881     ///
1882     pure int  feof(FILE* stream);
1883     ///
1884     pure int  ferror(FILE* stream);
1885     ///
1886     int  fileno(FILE *);
1887   }
1888 
1889     ///
1890     pragma(printf)
1891     int  snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
1892     ///
1893     pragma(printf)
1894     int  vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
1895 }
1896 else version (WASI)
1897 {
1898     // No unsafe pointer manipulation.
1899     @trusted
1900     {
1901         ///
1902         void rewind(FILE* stream);
1903         ///
1904         pure void clearerr(FILE* stream);
1905         ///
1906         pure int  feof(FILE* stream);
1907         ///
1908         pure int  ferror(FILE* stream);
1909         ///
1910         int  fileno(FILE *);
1911     }
1912 
1913     ///
1914     int  snprintf(scope char* s, size_t n, scope const char* format, ...);
1915     ///
1916     int  vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
1917 }
1918 else
1919 {
1920     static assert( false, "Unsupported platform" );
1921 }
1922 
1923 ///
1924 void perror(scope const char* s);
1925 
1926 version (CRuntime_DigitalMars)
1927 {
1928     version (none)
1929         import core.sys.windows.windows : HANDLE, _WaitSemaphore, _ReleaseSemaphore;
1930     else
1931     {
1932         // too slow to import windows
1933         private alias void* HANDLE;
1934         private void _WaitSemaphore(int iSemaphore);
1935         private void _ReleaseSemaphore(int iSemaphore);
1936     }
1937 
1938     enum
1939     {
1940         ///
1941         FHND_APPEND     = 0x04,
1942         ///
1943         FHND_DEVICE     = 0x08,
1944         ///
1945         FHND_TEXT       = 0x10,
1946         ///
1947         FHND_BYTE       = 0x20,
1948         ///
1949         FHND_WCHAR      = 0x40,
1950     }
1951 
1952     private enum _MAX_SEMAPHORES = 10 + _NFILE;
1953     private enum _semIO = 3;
1954 
1955     private extern __gshared short[_MAX_SEMAPHORES] _iSemLockCtrs;
1956     private extern __gshared int[_MAX_SEMAPHORES] _iSemThreadIds;
1957     private extern __gshared int[_MAX_SEMAPHORES] _iSemNestCount;
1958     private extern __gshared HANDLE[_NFILE] _osfhnd;
1959     extern shared ubyte[_NFILE] __fhnd_info;
1960 
1961     // this is copied from semlock.h in DMC's runtime.
1962     private void LockSemaphore()(uint num)
1963     {
1964         asm nothrow @nogc
1965         {
1966             mov EDX, num;
1967             lock;
1968             inc _iSemLockCtrs[EDX * 2];
1969             jz lsDone;
1970             push EDX;
1971             call _WaitSemaphore;
1972             add ESP, 4;
1973         }
1974 
1975     lsDone: {}
1976     }
1977 
1978     // this is copied from semlock.h in DMC's runtime.
1979     private void UnlockSemaphore()(uint num)
1980     {
1981         asm nothrow @nogc
1982         {
1983             mov EDX, num;
1984             lock;
1985             dec _iSemLockCtrs[EDX * 2];
1986             js usDone;
1987             push EDX;
1988             call _ReleaseSemaphore;
1989             add ESP, 4;
1990         }
1991 
1992     usDone: {}
1993     }
1994 
1995     // This converts a HANDLE to a file descriptor in DMC's runtime
1996     ///
1997     int _handleToFD()(HANDLE h, int flags)
1998     {
1999         LockSemaphore(_semIO);
2000         scope(exit) UnlockSemaphore(_semIO);
2001 
2002         foreach (fd; 0 .. _NFILE)
2003         {
2004             if (!_osfhnd[fd])
2005             {
2006                 _osfhnd[fd] = h;
2007                 __fhnd_info[fd] = cast(ubyte)flags;
2008                 return fd;
2009             }
2010         }
2011 
2012         return -1;
2013     }
2014 
2015     ///
2016     HANDLE _fdToHandle()(int fd)
2017     {
2018         // no semaphore is required, once inserted, a file descriptor
2019         // doesn't change.
2020         if (fd < 0 || fd >= _NFILE)
2021             return null;
2022 
2023         return _osfhnd[fd];
2024     }
2025 
2026     enum
2027     {
2028         ///
2029         STDIN_FILENO  = 0,
2030         ///
2031         STDOUT_FILENO = 1,
2032         ///
2033         STDERR_FILENO = 2,
2034     }
2035 
2036     int open(scope const(char)* filename, int flags, ...); ///
2037     alias _open = open; ///
2038     int _wopen(scope const wchar* filename, int oflag, ...); ///
2039     int sopen(scope const char* filename, int oflag, int shflag, ...); ///
2040     alias _sopen = sopen; ///
2041     int _wsopen(scope const wchar* filename, int oflag, int shflag, ...); ///
2042     int close(int fd); ///
2043     alias _close = close; ///
2044     FILE *fdopen(int fd, scope const(char)* flags); ///
2045     alias _fdopen = fdopen; ///
2046     FILE *_wfdopen(int fd, scope const(wchar)* flags); ///
2047 
2048 }
2049 else version (CRuntime_Microsoft)
2050 {
2051     int _open(scope const char* filename, int oflag, ...); ///
2052     int _wopen(scope const wchar* filename, int oflag, ...); ///
2053     int _sopen(scope const char* filename, int oflag, int shflag, ...); ///
2054     int _wsopen(scope const wchar* filename, int oflag, int shflag, ...); ///
2055     int _close(int fd); ///
2056     FILE *_fdopen(int fd, scope const(char)* flags); ///
2057     FILE *_wfdopen(int fd, scope const(wchar)* flags); ///
2058 }
2059 
2060 version (Windows)
2061 {
2062     // file open flags
2063     enum
2064     {
2065         _O_RDONLY = 0x0000, ///
2066         O_RDONLY = _O_RDONLY, ///
2067         _O_WRONLY = 0x0001, ///
2068         O_WRONLY = _O_WRONLY, ///
2069         _O_RDWR   = 0x0002, ///
2070         O_RDWR = _O_RDWR, ///
2071         _O_APPEND = 0x0008, ///
2072         O_APPEND = _O_APPEND, ///
2073         _O_CREAT  = 0x0100, ///
2074         O_CREAT = _O_CREAT, ///
2075         _O_TRUNC  = 0x0200, ///
2076         O_TRUNC = _O_TRUNC, ///
2077         _O_EXCL   = 0x0400, ///
2078         O_EXCL = _O_EXCL, ///
2079         _O_TEXT   = 0x4000, ///
2080         O_TEXT = _O_TEXT, ///
2081         _O_BINARY = 0x8000, ///
2082         O_BINARY = _O_BINARY, ///
2083         _O_WTEXT = 0x10000, ///
2084         _O_U16TEXT = 0x20000, ///
2085         _O_U8TEXT = 0x40000, ///
2086         _O_ACCMODE = (_O_RDONLY|_O_WRONLY|_O_RDWR), ///
2087         O_ACCMODE = _O_ACCMODE, ///
2088         _O_RAW = _O_BINARY, ///
2089         O_RAW = _O_BINARY, ///
2090         _O_NOINHERIT = 0x0080, ///
2091         O_NOINHERIT = _O_NOINHERIT, ///
2092         _O_TEMPORARY = 0x0040, ///
2093         O_TEMPORARY = _O_TEMPORARY, ///
2094         _O_SHORT_LIVED = 0x1000, ///
2095         _O_SEQUENTIAL = 0x0020, ///
2096         O_SEQUENTIAL = _O_SEQUENTIAL, ///
2097         _O_RANDOM = 0x0010, ///
2098         O_RANDOM = _O_RANDOM, ///
2099     }
2100 
2101     enum
2102     {
2103         _S_IREAD  = 0x0100, /// read permission, owner
2104         S_IREAD = _S_IREAD, /// read permission, owner
2105         _S_IWRITE = 0x0080, /// write permission, owner
2106         S_IWRITE = _S_IWRITE, /// write permission, owner
2107     }
2108 
2109     enum
2110     {
2111         _SH_DENYRW = 0x10, /// deny read/write mode
2112         SH_DENYRW = _SH_DENYRW, /// deny read/write mode
2113         _SH_DENYWR = 0x20, /// deny write mode
2114         SH_DENYWR = _SH_DENYWR, /// deny write mode
2115         _SH_DENYRD = 0x30, /// deny read mode
2116         SH_DENYRD = _SH_DENYRD, /// deny read mode
2117         _SH_DENYNO = 0x40, /// deny none mode
2118         SH_DENYNO = _SH_DENYNO, /// deny none mode
2119     }
2120 }