The OpenD Programming Language

1 /**
2  * D header file for POSIX.
3  *
4  * Copyright: Copyright Sean Kelly 2005 - 2009.
5  * License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
6  * Authors:   Sean Kelly
7  * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
8  */
9 
10 /*          Copyright Sean Kelly 2005 - 2009.
11  * Distributed under the Boost Software License, Version 1.0.
12  *    (See accompanying file LICENSE or copy at
13  *          http://www.boost.org/LICENSE_1_0.txt)
14  */
15 module core.sys.posix.stdio;
16 
17 import core.sys.posix.config;
18 public import core.stdc.stdio;
19 public import core.sys.posix.sys.types; // for off_t
20 
21 version (OSX)
22     version = Darwin;
23 else version (iOS)
24     version = Darwin;
25 else version (TVOS)
26     version = Darwin;
27 else version (WatchOS)
28     version = Darwin;
29 
30 version (Posix):
31 extern (C):
32 
33 nothrow:
34 @nogc:
35 
36 //
37 // Required (defined in core.stdc.stdio)
38 //
39 /*
40 BUFSIZ
41 _IOFBF
42 _IOLBF
43 _IONBF
44 L_tmpnam
45 SEEK_CUR
46 SEEK_END
47 SEEK_SET
48 FILENAME_MAX
49 FOPEN_MAX
50 TMP_MAX
51 EOF
52 NULL
53 stderr
54 stdin
55 stdout
56 FILE
57 fpos_t
58 size_t
59 
60 void   clearerr(FILE*);
61 int    fclose(FILE*);
62 int    feof(FILE*);
63 int    ferror(FILE*);
64 int    fflush(FILE*);
65 int    fgetc(FILE*);
66 int    fgetpos(FILE*, fpos_t *);
67 char*  fgets(char*, int, FILE*);
68 FILE*  fopen(const scope char*, const scope char*);
69 int    fprintf(FILE*, const scope char*, ...);
70 int    fputc(int, FILE*);
71 int    fputs(const scope char*, FILE*);
72 size_t fread(void *, size_t, size_t, FILE*);
73 FILE*  freopen(const scope char*, const scope char*, FILE*);
74 int    fscanf(FILE*, const scope char*, ...);
75 int    fseek(FILE*, c_long, int);
76 int    fsetpos(FILE*, const scope fpos_t*);
77 c_long ftell(FILE*);
78 size_t fwrite(in void *, size_t, size_t, FILE*);
79 int    getc(FILE*);
80 int    getchar();
81 char*  gets(char*);
82 void   perror(const scope char*);
83 int    printf(const scope char*, ...);
84 int    putc(int, FILE*);
85 int    putchar(int);
86 int    puts(const scope char*);
87 int    remove(const scope char*);
88 int    rename(const scope char*, const scope char*);
89 void   rewind(FILE*);
90 int    scanf(const scope char*, ...);
91 void   setbuf(FILE*, char*);
92 int    setvbuf(FILE*, char*, int, size_t);
93 int    snprintf(char*, size_t, const scope char*, ...);
94 int    sprintf(char*, const scope char*, ...);
95 int    sscanf(const scope char*, const scope char*, int ...);
96 FILE*  tmpfile();
97 char*  tmpnam(char*);
98 int    ungetc(int, FILE*);
99 int    vfprintf(FILE*, const scope char*, va_list);
100 int    vfscanf(FILE*, const scope char*, va_list);
101 int    vprintf(const scope char*, va_list);
102 int    vscanf(const scope char*, va_list);
103 int    vsnprintf(char*, size_t, const scope char*, va_list);
104 int    vsprintf(char*, const scope char*, va_list);
105 int    vsscanf(const scope char*, const scope char*, va_list arg);
106 */
107 
108 version (CRuntime_Glibc)
109 {
110     /*
111      * actually, if __USE_FILE_OFFSET64 && !_LARGEFILE64_SOURCE
112      * the *64 functions shouldn't be visible, but the aliases should
113      * still be supported
114      */
115     static if ( __USE_FILE_OFFSET64 )
116     {
117         int   fgetpos64(FILE*, fpos_t *);
118         alias fgetpos64 fgetpos;
119 
120         FILE* fopen64(const scope char*, const scope char*);
121         alias fopen64 fopen;
122 
123         FILE* freopen64(const scope char*, const scope char*, FILE*);
124         alias freopen64 freopen;
125 
126         int   fseek(FILE*, c_long, int);
127 
128         int   fsetpos64(FILE*, const scope fpos_t*);
129         alias fsetpos64 fsetpos;
130 
131         FILE* tmpfile64();
132         alias tmpfile64 tmpfile;
133     }
134     else
135     {
136         int   fgetpos(FILE*, fpos_t *);
137         FILE* fopen(const scope char*, const scope char*);
138         FILE* freopen(const scope char*, const scope char*, FILE*);
139         int   fseek(FILE*, c_long, int);
140         int   fsetpos(FILE*, const scope fpos_t*);
141         FILE* tmpfile();
142     }
143 }
144 else version (CRuntime_Bionic)
145 {
146     int   fgetpos(FILE*, fpos_t *);
147     FILE* fopen(const scope char*, const scope char*);
148     FILE* freopen(const scope char*, const scope char*, FILE*);
149     int   fseek(FILE*, c_long, int);
150     int   fsetpos(FILE*, const scope fpos_t*);
151 }
152 else version (CRuntime_UClibc)
153 {
154     static if ( __USE_FILE_OFFSET64 )
155     {
156         int   fgetpos64(FILE*, fpos_t *);
157         alias fgetpos64 fgetpos;
158 
159         FILE* fopen64(const scope char*, const scope char*);
160         alias fopen64 fopen;
161 
162         FILE* freopen64(const scope char*, const scope char*, FILE*);
163         alias freopen64 freopen;
164 
165         int   fseek(FILE*, c_long, int);
166 
167         int   fsetpos64(FILE*, const scope fpos_t*);
168         alias fsetpos64 fsetpos;
169 
170         FILE* tmpfile64();
171         alias tmpfile64 tmpfile;
172     }
173     else
174     {
175         int   fgetpos(FILE*, fpos_t *);
176         FILE* fopen(const scope char*, const scope char*);
177         FILE* freopen(const scope char*, const scope char*, FILE*);
178         int   fseek(FILE*, c_long, int);
179         int   fsetpos(FILE*, const scope fpos_t*);
180         FILE* tmpfile();
181     }
182 }
183 else version (CRuntime_Musl)
184 {
185     int   fgetpos(FILE*, fpos_t *);
186     FILE* fopen(const scope char*, const scope char*);
187     FILE* freopen(const scope char*, const scope char*, FILE*);
188     int   fseek(FILE*, c_long, int);
189     int   fsetpos(FILE*, const scope fpos_t*);
190     FILE* tmpfile();
191     
192     alias fgetpos64 = fgetpos;
193     alias fopen64 = fopen;
194     alias freopen64 = freopen;
195     alias fsetpos64 = fsetpos;
196     alias tmpfile64 = tmpfile;
197 }
198 else version (Solaris)
199 {
200     static if (__USE_FILE_OFFSET64 && __WORDSIZE != 64)
201     {
202         int   fgetpos64(FILE*, fpos_t *);
203         alias fgetpos = fgetpos64;
204 
205         FILE* fopen64(const scope char*, const scope char*);
206         alias fopen = fopen64;
207 
208         FILE* freopen64(const scope char*, const scope char*, FILE*);
209         alias freopen = freopen64;
210 
211         int   fseek(FILE*, c_long, int);
212 
213         int   fsetpos64(FILE*, const scope fpos_t*);
214         alias fsetpos = fsetpos64;
215 
216         FILE* tmpfile64();
217         alias tmpfile = tmpfile64;
218     }
219     else
220     {
221         int   fgetpos(FILE*, fpos_t *);
222         FILE* fopen(const scope char*, const scope char*);
223         FILE* freopen(const scope char*, const scope char*, FILE*);
224         int   fseek(FILE*, c_long, int);
225         int   fsetpos(FILE*, const scope fpos_t*);
226         FILE* tmpfile();
227     }
228 }
229 
230 //
231 // C Extension (CX)
232 //
233 /*
234 L_ctermid
235 
236 char*   ctermid(char*);
237 FILE*   fdopen(int, const scope char*);
238 int     fileno(FILE*);
239 int     fseeko(FILE*, off_t, int);
240 off_t   ftello(FILE*);
241 ssize_t getdelim(char**, size_t*, int, FILE*);
242 ssize_t getline(char**, size_t*, FILE*);
243 char*   gets(char*);
244 int     pclose(FILE*);
245 FILE*   popen(const scope char*, const scope char*);
246 */
247 
248 version (CRuntime_Glibc)
249 {
250     enum L_ctermid = 9;
251 
252     static if ( __USE_FILE_OFFSET64 )
253     {
254         int   fseeko64(FILE*, off_t, int);
255         alias fseeko64 fseeko;
256     }
257     else
258     {
259         int   fseeko(FILE*, off_t, int);
260     }
261 
262     static if ( __USE_FILE_OFFSET64 )
263     {
264         off_t ftello64(FILE*);
265         alias ftello64 ftello;
266     }
267     else
268     {
269         off_t ftello(FILE*);
270     }
271 
272     ssize_t getdelim(char**, size_t*, int, FILE*);
273     ssize_t getline(char**, size_t*, FILE*);
274 }
275 else version (CRuntime_UClibc)
276 {
277     enum L_ctermid = 9;
278     enum L_cuserid = 9;
279 
280     static if ( __USE_FILE_OFFSET64 )
281     {
282         int   fseeko64(FILE*, off_t, int);
283         alias fseeko64 fseeko;
284     }
285     else
286     {
287         int   fseeko(FILE*, off_t, int);
288     }
289 
290     static if ( __USE_FILE_OFFSET64 )
291     {
292         off_t ftello64(FILE*);
293         alias ftello64 ftello;
294     }
295     else
296     {
297         off_t ftello(FILE*);
298     }
299 
300     ssize_t getdelim(char**, size_t*, int, FILE*);
301     ssize_t getline(char**, size_t*, FILE*);
302 }
303 else version (CRuntime_Musl)
304 {
305     enum L_ctermid = 20;
306 
307     int   fseeko(FILE*, off_t, int);
308     alias fseeko64 = fseeko;
309 
310     off_t ftello(FILE*);
311     alias ftello64 = ftello;
312 
313     ssize_t getdelim(char**, size_t*, int, FILE*);
314     ssize_t getline(char**, size_t*, FILE*);
315 }
316 else version (CRuntime_Bionic)
317 {
318     enum L_ctermid = 1024;
319 
320     static if ( __USE_FILE_OFFSET64 )
321     {
322         int   fseeko64(FILE*, off_t, int);
323         alias fseeko64 fseeko;
324     }
325     else
326     {
327         int   fseeko(FILE*, off_t, int);
328     }
329 
330     static if ( __USE_FILE_OFFSET64 )
331     {
332         off_t ftello64(FILE*);
333         alias ftello64 ftello;
334     }
335     else
336     {
337         off_t ftello(FILE*);
338     }
339 
340     ssize_t getdelim(char**, size_t*, int, FILE*);
341     ssize_t getline(char**, size_t*, FILE*);
342 }
343 else version (Darwin)
344 {
345     enum L_ctermid = 1024;
346 
347     int   fseeko(FILE*, off_t, int);
348     off_t ftello(FILE*);
349 
350     ssize_t getdelim(char**, size_t*, int, FILE*);
351     ssize_t getline(char**, size_t*, FILE*);
352 }
353 else version (FreeBSD)
354 {
355     import core.sys.freebsd.config;
356 
357     enum L_ctermid = 1024;
358 
359     int   fseeko(FILE*, off_t, int);
360     off_t ftello(FILE*);
361 
362     static if (__FreeBSD_version >= 800000)
363     {
364         ssize_t getdelim(char**, size_t*, int, FILE*);
365         ssize_t getline(char**, size_t*, FILE*);
366     }
367 }
368 else version (NetBSD)
369 {
370     enum L_ctermid = 1024;
371 
372     int   fseeko(FILE*, off_t, int);
373     off_t ftello(FILE*);
374 
375     ssize_t getdelim(char**, size_t*, int, FILE*);
376     ssize_t getline(char**, size_t*, FILE*);
377 }
378 else version (OpenBSD)
379 {
380     enum L_ctermid = 1024;
381 
382     int   fseeko(FILE*, off_t, int);
383     off_t ftello(FILE*);
384 
385     ssize_t getdelim(char**, size_t*, int, FILE*);
386     ssize_t getline(char**, size_t*, FILE*);
387 }
388 else version (DragonFlyBSD)
389 {
390     enum L_ctermid = 1024;
391 
392     int   fseeko(FILE*, off_t, int);
393     off_t ftello(FILE*);
394 
395     ssize_t getdelim(char**, size_t*, int, FILE*);
396     ssize_t getline(char**, size_t*, FILE*);
397 }
398 else version (Solaris)
399 {
400     enum L_ctermid = 9;
401     enum L_cuserid = 9;
402 
403     static if (__USE_FILE_OFFSET64 && __WORDSIZE != 64)
404     {
405         int   fseeko64(FILE*, off_t, int);
406         alias fseeko = fseeko64;
407     }
408     else
409     {
410         int   fseeko(FILE*, off_t, int);
411     }
412 
413     static if (__USE_FILE_OFFSET64 && __WORDSIZE != 64)
414     {
415         off_t ftello64(FILE*);
416         alias ftello = ftello64;
417     }
418     else
419     {
420         off_t ftello(FILE*);
421     }
422 
423     ssize_t getdelim(char**, size_t*, int, FILE*);
424     ssize_t getline(char**, size_t*, FILE*);
425 }
426 else version (Posix)
427 {
428     int   fseeko(FILE*, off_t, int);
429     off_t ftello(FILE*);
430 }
431 
432 char*  ctermid(char*);
433 FILE*  fdopen(int, const scope char*);
434 int    fileno(FILE*);
435 char*  gets(char*);
436 int    pclose(FILE*);
437 FILE*  popen(const scope char*, const scope char*);
438 
439 
440 // memstream functions are conforming to POSIX.1-2008.  These functions are
441 // not specified in POSIX.1-2001 and are not widely available on other
442 // systems.
443 version (CRuntime_Glibc)                     // as of glibc 1.0x
444     version = HaveMemstream;
445 else version (FreeBSD)                      // as of FreeBSD 9.2
446     version = HaveMemstream;
447 else version (DragonFlyBSD)                 // for DragonFlyBSD
448     version = HaveMemstream;
449 else version (OpenBSD)                      // as of OpenBSD 5.4
450     version = HaveMemstream;
451 else version (CRuntime_UClibc)
452     version = HaveMemstream;
453 // http://git.musl-libc.org/cgit/musl/commit/src/stdio/open_memstream.c?id=b158b32a44d56ef20407d4285b58180447ffff1f
454 else version (CRuntime_Musl)
455     version = HaveMemstream;
456 
457 version (HaveMemstream)
458 {
459     FILE*  fmemopen(const scope void* buf, size_t size, const scope char* mode);
460     FILE*  open_memstream(char** ptr, size_t* sizeloc);
461     version (CRuntime_UClibc) {} else
462     FILE*  open_wmemstream(wchar_t** ptr, size_t* sizeloc);
463 }
464 
465 //
466 // Thread-Safe Functions (TSF)
467 //
468 /*
469 void   flockfile(FILE*);
470 int    ftrylockfile(FILE*);
471 void   funlockfile(FILE*);
472 int    getc_unlocked(FILE*);
473 int    getchar_unlocked();
474 int    putc_unlocked(int, FILE*);
475 int    putchar_unlocked(int);
476 */
477 
478 version (CRuntime_Glibc)
479 {
480     void   flockfile(FILE*);
481     int    ftrylockfile(FILE*);
482     void   funlockfile(FILE*);
483     int    getc_unlocked(FILE*);
484     int    getchar_unlocked();
485     int    putc_unlocked(int, FILE*);
486     int    putchar_unlocked(int);
487 }
488 else version (CRuntime_Musl)
489 {
490     void   flockfile(FILE*);
491     int    ftrylockfile(FILE*);
492     void   funlockfile(FILE*);
493     int    getc_unlocked(FILE*);
494     int    getchar_unlocked();
495     int    putc_unlocked(int, FILE*);
496     int    putchar_unlocked(int);
497 }
498 else version (CRuntime_Bionic)
499 {
500     void   flockfile(FILE*);
501     int    ftrylockfile(FILE*);
502     void   funlockfile(FILE*);
503     int    getc_unlocked(FILE*);
504     int    getchar_unlocked();
505     int    putc_unlocked(int, FILE*);
506     int    putchar_unlocked(int);
507 }
508 else version (Darwin)
509 {
510     void   flockfile(FILE*);
511     int    ftrylockfile(FILE*);
512     void   funlockfile(FILE*);
513     int    getc_unlocked(FILE*);
514     int    getchar_unlocked();
515     int    putc_unlocked(int, FILE*);
516     int    putchar_unlocked(int);
517 }
518 else version (FreeBSD)
519 {
520     void   flockfile(FILE*);
521     int    ftrylockfile(FILE*);
522     void   funlockfile(FILE*);
523     int    getc_unlocked(FILE*);
524     int    getchar_unlocked();
525     int    putc_unlocked(int, FILE*);
526     int    putchar_unlocked(int);
527 }
528 else version (NetBSD)
529 {
530     void   flockfile(FILE*);
531     int    ftrylockfile(FILE*);
532     void   funlockfile(FILE*);
533     int    getc_unlocked(FILE*);
534     int    getchar_unlocked();
535     int    putc_unlocked(int, FILE*);
536     int    putchar_unlocked(int);
537 }
538 else version (OpenBSD)
539 {
540     void   flockfile(FILE*);
541     int    ftrylockfile(FILE*);
542     void   funlockfile(FILE*);
543     int    getc_unlocked(FILE*);
544     int    getchar_unlocked();
545     int    putc_unlocked(int, FILE*);
546     int    putchar_unlocked(int);
547 }
548 else version (DragonFlyBSD)
549 {
550     void   flockfile(FILE*);
551     int    ftrylockfile(FILE*);
552     void   funlockfile(FILE*);
553     int    getc_unlocked(FILE*);
554     int    getchar_unlocked();
555     int    putc_unlocked(int, FILE*);
556     int    putchar_unlocked(int);
557 }
558 else version (Solaris)
559 {
560     void   flockfile(FILE*);
561     int    ftrylockfile(FILE*);
562     void   funlockfile(FILE*);
563     int    getc_unlocked(FILE*);
564     int    getchar_unlocked();
565     int    putc_unlocked(int, FILE*);
566     int    putchar_unlocked(int);
567 }
568 else version (CRuntime_UClibc)
569 {
570     void   flockfile(FILE*);
571     int    ftrylockfile(FILE*);
572     void   funlockfile(FILE*);
573     int    getc_unlocked(FILE*);
574     int    getchar_unlocked();
575     int    putc_unlocked(int, FILE*);
576     int    putchar_unlocked(int);
577 }
578 
579 //
580 // XOpen (XSI)
581 //
582 /*
583 P_tmpdir
584 va_list (defined in core.stdc.stdarg)
585 
586 char*  tempnam(const scope char*, const scope char*);
587 */
588 
589 char*  tempnam(const scope char*, const scope char*);
590 
591 version (CRuntime_Glibc)
592 {
593     enum P_tmpdir  = "/tmp";
594 }
595 else version (CRuntime_Musl)
596 {
597     enum P_tmpdir  = "/tmp";
598 }
599 else version (Darwin)
600 {
601     enum P_tmpdir  = "/var/tmp";
602 }
603 else version (FreeBSD)
604 {
605     enum P_tmpdir  = "/var/tmp/";
606 }
607 else version (NetBSD)
608 {
609     enum P_tmpdir  = "/var/tmp/";
610 }
611 else version (OpenBSD)
612 {
613     enum P_tmpdir  = "/tmp/";
614 }
615 else version (DragonFlyBSD)
616 {
617     enum P_tmpdir  = "/var/tmp/";
618 }
619 else version (Solaris)
620 {
621     enum P_tmpdir  = "/var/tmp/";
622 }
623 else version (CRuntime_UClibc)
624 {
625     enum P_tmpdir  = "/tmp";
626 }
627 
628 version (HaveMemstream)
629 unittest
630 { /* fmemopen */
631     import core.stdc.string : memcmp;
632     byte[10] buf;
633     auto f = fmemopen(buf.ptr, 10, "w");
634     assert(f !is null);
635     assert(fprintf(f, "hello") == "hello".length);
636     assert(fflush(f) == 0);
637     assert(memcmp(buf.ptr, "hello".ptr, "hello".length) == 0);
638     //assert(buf
639     assert(fclose(f) == 0);
640 }
641 
642 version (HaveMemstream)
643 unittest
644 { /* Note: open_memstream is only useful for writing */
645     import core.stdc.string : memcmp;
646     char* ptr = null;
647     char[6] testdata = ['h', 'e', 'l', 'l', 'o', 0];
648     size_t sz = 0;
649     auto f = open_memstream(&ptr, &sz);
650     assert(f !is null);
651     assert(fprintf(f, "%s", testdata.ptr) == 5);
652     assert(fflush(f) == 0);
653     assert(memcmp(ptr, testdata.ptr, testdata.length) == 0);
654     assert(fclose(f) == 0);
655 }
656 
657 version (CRuntime_UClibc) {} else
658 version (HaveMemstream)
659 unittest
660 { /* Note: open_wmemstream is only useful for writing */
661     import core.stdc.string : memcmp;
662     import core.stdc.wchar_ : fwprintf;
663     wchar_t* ptr = null;
664     wchar_t[6] testdata = ['h', 'e', 'l', 'l', 'o', 0];
665     size_t sz = 0;
666     auto f = open_wmemstream(&ptr, &sz);
667     assert(f !is null);
668     assert(fwprintf(f, testdata.ptr) == 5);
669     assert(fflush(f) == 0);
670     assert(memcmp(ptr, testdata.ptr, testdata.length*wchar_t.sizeof) == 0);
671     assert(fclose(f) == 0);
672 }