/src/core/stdc/stdio.d
D | 821 lines | 682 code | 101 blank | 38 comment | 26 complexity | bbd5e3a9e42b79b9070e13ba62074c53 MD5 | raw file
1/** 2 * D header file for C99. 3 * 4 * Copyright: Copyright Sean Kelly 2005 - 2009. 5 * License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>. 6 * Authors: Sean Kelly, 7 Alex Rønne Petersen 8 * Standards: ISO/IEC 9899:1999 (E) 9 */ 10 11/* Copyright Sean Kelly 2005 - 2009. 12 * Distributed under the Boost Software License, Version 1.0. 13 * (See accompanying file LICENSE or copy at 14 * http://www.boost.org/LICENSE_1_0.txt) 15 */ 16module core.stdc.stdio; 17 18private 19{ 20 import core.stdc.config; 21 import core.stdc.stddef; // for size_t 22 import core.stdc.stdarg; // for va_list 23 24 version (FreeBSD) 25 { 26 import core.sys.posix.sys.types; 27 } 28} 29 30extern (C): 31@system: 32nothrow: 33 34version( Win32 ) 35{ 36 enum 37 { 38 BUFSIZ = 0x4000, 39 EOF = -1, 40 FOPEN_MAX = 20, 41 FILENAME_MAX = 256, // 255 plus NULL 42 TMP_MAX = 32767, 43 SYS_OPEN = 20, // non-standard 44 } 45 46 enum int _NFILE = 60; // non-standard 47 enum string _P_tmpdir = "\\"; // non-standard 48 enum wstring _wP_tmpdir = "\\"; // non-standard 49 enum int L_tmpnam = _P_tmpdir.length + 12; 50} 51else version( Win64 ) 52{ 53 enum 54 { 55 BUFSIZ = 512, 56 EOF = -1, 57 FOPEN_MAX = 20, 58 FILENAME_MAX = 260, 59 TMP_MAX = 32767, 60 _SYS_OPEN = 20, // non-standard 61 } 62 63 enum int _NFILE = 512; // non-standard 64 enum string _P_tmpdir = "\\"; // non-standard 65 enum wstring _wP_tmpdir = "\\"; // non-standard 66 enum int L_tmpnam = _P_tmpdir.length + 12; 67} 68else version( linux ) 69{ 70 enum 71 { 72 BUFSIZ = 8192, 73 EOF = -1, 74 FOPEN_MAX = 16, 75 FILENAME_MAX = 4095, 76 TMP_MAX = 238328, 77 L_tmpnam = 20 78 } 79} 80else version( OSX ) 81{ 82 enum 83 { 84 BUFSIZ = 1024, 85 EOF = -1, 86 FOPEN_MAX = 20, 87 FILENAME_MAX = 1024, 88 TMP_MAX = 308915776, 89 L_tmpnam = 1024, 90 } 91 92 private 93 { 94 struct __sbuf 95 { 96 ubyte* _base; 97 int _size; 98 } 99 100 struct __sFILEX 101 { 102 103 } 104 } 105} 106else version ( FreeBSD ) 107{ 108 enum 109 { 110 BUFSIZ = 1024, 111 EOF = -1, 112 FOPEN_MAX = 20, 113 FILENAME_MAX = 1024, 114 TMP_MAX = 308915776, 115 L_tmpnam = 1024 116 } 117 118 struct __sbuf 119 { 120 ubyte *_base; 121 int _size; 122 } 123 alias _iobuf __sFILE; 124 125 union __mbstate_t // <sys/_types.h> 126 { 127 char[128] _mbstate8; 128 long _mbstateL; 129 } 130} 131else version (Solaris) 132{ 133 enum 134 { 135 BUFSIZ = 1024, 136 EOF = -1, 137 FOPEN_MAX = _NFILE, 138 FILENAME_MAX = 1024, 139 TMP_MAX = 17576, 140 L_tmpnam = 25, 141 } 142 143 version (X86) 144 enum int _NFILE = 60; 145 else 146 enum int _NFILE = 20; 147} 148else 149{ 150 static assert( false, "Unsupported platform" ); 151} 152 153enum 154{ 155 SEEK_SET, 156 SEEK_CUR, 157 SEEK_END 158} 159 160version( Win32 ) 161{ 162 struct _iobuf 163 { 164 char* _ptr; 165 int _cnt; 166 char* _base; 167 int _flag; 168 int _file; 169 int _charbuf; 170 int _bufsiz; 171 char* __tmpnum; 172 } 173} 174else version( Win64 ) 175{ 176 struct _iobuf 177 { 178 char* _ptr; 179 int _cnt; 180 char* _base; 181 int _flag; 182 int _file; 183 int _charbuf; 184 int _bufsiz; 185 char* _tmpfname; 186 } 187} 188else version( linux ) 189{ 190 align(1) struct _iobuf 191 { 192 int _flags; 193 char* _read_ptr; 194 char* _read_end; 195 char* _read_base; 196 char* _write_base; 197 char* _write_ptr; 198 char* _write_end; 199 char* _buf_base; 200 char* _buf_end; 201 char* _save_base; 202 char* _backup_base; 203 char* _save_end; 204 void* _markers; 205 _iobuf* _chain; 206 int _fileno; 207 int _blksize; 208 int _old_offset; 209 ushort _cur_column; 210 byte _vtable_offset; 211 char[1] _shortbuf; 212 void* _lock; 213 } 214} 215else version( OSX ) 216{ 217 align (1) struct _iobuf 218 { 219 ubyte* _p; 220 int _r; 221 int _w; 222 short _flags; 223 short _file; 224 __sbuf _bf; 225 int _lbfsize; 226 227 int* function(void*) _close; 228 int* function(void*, char*, int) _read; 229 fpos_t* function(void*, fpos_t, int) _seek; 230 int* function(void*, char *, int) _write; 231 232 __sbuf _ub; 233 __sFILEX* _extra; 234 int _ur; 235 236 ubyte[3] _ubuf; 237 ubyte[1] _nbuf; 238 239 __sbuf _lb; 240 241 int _blksize; 242 fpos_t _offset; 243 } 244} 245else version( FreeBSD ) 246{ 247 align (1) struct _iobuf 248 { 249 ubyte* _p; 250 int _r; 251 int _w; 252 short _flags; 253 short _file; 254 __sbuf _bf; 255 int _lbfsize; 256 257 void* _cookie; 258 int function(void*) _close; 259 int function(void*, char*, int) _read; 260 fpos_t function(void*, fpos_t, int) _seek; 261 int function(void*, in char*, int) _write; 262 263 __sbuf _ub; 264 ubyte* _up; 265 int _ur; 266 267 ubyte[3] _ubuf; 268 ubyte[1] _nbuf; 269 270 __sbuf _lb; 271 272 int _blksize; 273 fpos_t _offset; 274 275 pthread_mutex_t _fl_mutex; 276 pthread_t _fl_owner; 277 int _fl_count; 278 int _orientation; 279 __mbstate_t _mbstate; 280 } 281} 282else version (Solaris) 283{ 284 align (1) struct _iobuf 285 { 286 char* _ptr; 287 int _cnt; 288 char* _base; 289 char _flag; 290 char _magic; 291 ushort __flags; // __orientation:2 292 // __ionolock:1 293 // __seekable:1 294 // __extendedfd:1 295 // __xf_nocheck:1 296 // __filler:10 297 } 298} 299else 300{ 301 static assert( false, "Unsupported platform" ); 302} 303 304 305alias shared(_iobuf) FILE; 306 307enum 308{ 309 _F_RDWR = 0x0003, // non-standard 310 _F_READ = 0x0001, // non-standard 311 _F_WRIT = 0x0002, // non-standard 312 _F_BUF = 0x0004, // non-standard 313 _F_LBUF = 0x0008, // non-standard 314 _F_ERR = 0x0010, // non-standard 315 _F_EOF = 0x0020, // non-standard 316 _F_BIN = 0x0040, // non-standard 317 _F_IN = 0x0080, // non-standard 318 _F_OUT = 0x0100, // non-standard 319 _F_TERM = 0x0200, // non-standard 320} 321 322version( Win32 ) 323{ 324 enum 325 { 326 _IOFBF = 0, 327 _IOLBF = 0x40, 328 _IONBF = 4, 329 _IOREAD = 1, // non-standard 330 _IOWRT = 2, // non-standard 331 _IOMYBUF = 8, // non-standard 332 _IOEOF = 0x10, // non-standard 333 _IOERR = 0x20, // non-standard 334 _IOSTRG = 0x40, // non-standard 335 _IORW = 0x80, // non-standard 336 _IOTRAN = 0x100, // non-standard 337 _IOAPP = 0x200, // non-standard 338 } 339 340 extern shared void function() _fcloseallp; 341 342 private extern shared FILE[_NFILE] _iob; 343 344 shared stdin = &_iob[0]; 345 shared stdout = &_iob[1]; 346 shared stderr = &_iob[2]; 347 shared stdaux = &_iob[3]; 348 shared stdprn = &_iob[4]; 349} 350else version( Win64 ) 351{ 352 enum 353 { 354 _IOFBF = 0, 355 _IOLBF = 0x40, 356 _IONBF = 4, 357 _IOREAD = 1, // non-standard 358 _IOWRT = 2, // non-standard 359 _IOMYBUF = 8, // non-standard 360 _IOEOF = 0x10, // non-standard 361 _IOERR = 0x20, // non-standard 362 _IOSTRG = 0x40, // non-standard 363 _IORW = 0x80, // non-standard 364 _IOAPP = 0x200, // non-standard 365 _IOAPPEND = 0x200, // non-standard 366 } 367 368 extern shared void function() _fcloseallp; 369 370 private extern shared FILE[_NFILE] _iob; 371 372 shared(FILE)* __iob_func(); 373 374 shared FILE* stdin; // = &__iob_func()[0]; 375 shared FILE* stdout; // = &__iob_func()[1]; 376 shared FILE* stderr; // = &__iob_func()[2]; 377} 378else version( linux ) 379{ 380 enum 381 { 382 _IOFBF = 0, 383 _IOLBF = 1, 384 _IONBF = 2, 385 } 386 387 extern shared FILE* stdin; 388 extern shared FILE* stdout; 389 extern shared FILE* stderr; 390} 391else version( OSX ) 392{ 393 enum 394 { 395 _IOFBF = 0, 396 _IOLBF = 1, 397 _IONBF = 2, 398 } 399 400 private extern shared FILE* __stdinp; 401 private extern shared FILE* __stdoutp; 402 private extern shared FILE* __stderrp; 403 404 alias __stdinp stdin; 405 alias __stdoutp stdout; 406 alias __stderrp stderr; 407} 408else version( FreeBSD ) 409{ 410 enum 411 { 412 _IOFBF = 0, 413 _IOLBF = 1, 414 _IONBF = 2, 415 } 416 417 private extern shared FILE* __stdinp; 418 private extern shared FILE* __stdoutp; 419 private extern shared FILE* __stderrp; 420 421 alias __stdinp stdin; 422 alias __stdoutp stdout; 423 alias __stderrp stderr; 424} 425else version (Solaris) 426{ 427 enum 428 { 429 _IOFBF = 0x00, 430 _IOLBF = 0x40, 431 _IONBF = 0x04, 432 _IOEOF = 0x20, 433 _IOERR = 0x40, 434 _IOREAD = 0x01, 435 _IOWRT = 0x02, 436 _IORW = 0x80, 437 _IOMYBUF = 0x08, 438 } 439 440 private extern shared FILE[_NFILE] __iob; 441 442 shared stdin = &__iob[0]; 443 shared stdout = &__iob[1]; 444 shared stderr = &__iob[2]; 445} 446else 447{ 448 static assert( false, "Unsupported platform" ); 449} 450 451alias int fpos_t; 452 453int remove(in char* filename); 454int rename(in char* from, in char* to); 455 456@trusted FILE* tmpfile(); // No unsafe pointer manipulation. 457char* tmpnam(char* s); 458 459int fclose(FILE* stream); 460 461// No unsafe pointer manipulation. 462@trusted 463{ 464 int fflush(FILE* stream); 465} 466 467FILE* fopen(in char* filename, in char* mode); 468FILE* freopen(in char* filename, in char* mode, FILE* stream); 469 470void setbuf(FILE* stream, char* buf); 471int setvbuf(FILE* stream, char* buf, int mode, size_t size); 472 473version (MinGW) 474{ 475 // Prefer the MinGW versions over the MSVC ones, as the latter don't handle 476 // reals at all. 477 int __mingw_fprintf(FILE* stream, in char* format, ...); 478 alias __mingw_fprintf fprintf; 479 480 int __mingw_fscanf(FILE* stream, in char* format, ...); 481 alias __mingw_fscanf fscanf; 482 483 int __mingw_sprintf(char* s, in char* format, ...); 484 alias __mingw_sprintf sprintf; 485 486 int __mingw_sscanf(in char* s, in char* format, ...); 487 alias __mingw_sscanf sscanf; 488 489 int __mingw_vfprintf(FILE* stream, in char* format, va_list arg); 490 alias __mingw_vfprintf vfprintf; 491 492 int __mingw_vfscanf(FILE* stream, in char* format, va_list arg); 493 alias __mingw_vfscanf vfscanf; 494 495 int __mingw_vsprintf(char* s, in char* format, va_list arg); 496 alias __mingw_vsprintf vsprintf; 497 498 int __mingw_vsscanf(in char* s, in char* format, va_list arg); 499 alias __mingw_vsscanf vsscanf; 500 501 int __mingw_vprintf(in char* format, va_list arg); 502 alias __mingw_vprintf vprintf; 503 504 int __mingw_vscanf(in char* format, va_list arg); 505 alias __mingw_vscanf vscanf; 506 507 int __mingw_printf(in char* format, ...); 508 alias __mingw_printf printf; 509 510 int __mingw_scanf(in char* format, ...); 511 alias __mingw_scanf scanf; 512} 513else 514{ 515 int fprintf(FILE* stream, in char* format, ...); 516 int fscanf(FILE* stream, in char* format, ...); 517 int sprintf(char* s, in char* format, ...); 518 int sscanf(in char* s, in char* format, ...); 519 int vfprintf(FILE* stream, in char* format, va_list arg); 520 int vfscanf(FILE* stream, in char* format, va_list arg); 521 int vsprintf(char* s, in char* format, va_list arg); 522 int vsscanf(in char* s, in char* format, va_list arg); 523 int vprintf(in char* format, va_list arg); 524 int vscanf(in char* format, va_list arg); 525 int printf(in char* format, ...); 526 int scanf(in char* format, ...); 527} 528 529// No usafe pointer manipulation. 530@trusted 531{ 532 int fgetc(FILE* stream); 533 int fputc(int c, FILE* stream); 534} 535 536char* fgets(char* s, int n, FILE* stream); 537int fputs(in char* s, FILE* stream); 538char* gets(char* s); 539int puts(in char* s); 540 541// No unsafe pointer manipulation. 542extern (D) @trusted 543{ 544 int getchar() { return getc(stdin); } 545 int putchar(int c) { return putc(c,stdout); } 546 int getc(FILE* stream) { return fgetc(stream); } 547 int putc(int c, FILE* stream) { return fputc(c,stream); } 548} 549 550@trusted int ungetc(int c, FILE* stream); // No unsafe pointer manipulation. 551 552size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream); 553size_t fwrite(in void* ptr, size_t size, size_t nmemb, FILE* stream); 554 555// No unsafe pointer manipulation. 556@trusted 557{ 558 int fgetpos(FILE* stream, fpos_t * pos); 559 int fsetpos(FILE* stream, in fpos_t* pos); 560 561 int fseek(FILE* stream, c_long offset, int whence); 562 c_long ftell(FILE* stream); 563} 564 565version( MinGW ) 566{ 567 // No unsafe pointer manipulation. 568 extern (D) @trusted 569 { 570 // TODO: Check if this is correct. 571 void rewind(FILE* stream) { fseek(stream,0L,SEEK_SET); stream._flag&=~_IOERR; } 572 pure void clearerr(FILE* stream) { stream._flag &= ~(_IOERR|_IOEOF); } 573 pure int feof(FILE* stream) { return stream._flag&_IOEOF; } 574 pure int ferror(FILE* stream) { return stream._flag&_IOERR; } 575 } 576 int __mingw_snprintf(char* s, size_t n, in char* fmt, ...); 577 alias __mingw_snprintf _snprintf; 578 alias __mingw_snprintf snprintf; 579 580 int __mingw_vsnprintf(char* s, size_t n, in char* format, va_list arg); 581 alias __mingw_vsnprintf _vsnprintf; 582 alias __mingw_vsnprintf vsnprintf; 583} 584else version( Win32 ) 585{ 586 // No unsafe pointer manipulation. 587 extern (D) @trusted 588 { 589 void rewind(FILE* stream) { fseek(stream,0L,SEEK_SET); stream._flag&=~_IOERR; } 590 pure void clearerr(FILE* stream) { stream._flag &= ~(_IOERR|_IOEOF); } 591 pure int feof(FILE* stream) { return stream._flag&_IOEOF; } 592 pure int ferror(FILE* stream) { return stream._flag&_IOERR; } 593 } 594 int _snprintf(char* s, size_t n, in char* fmt, ...); 595 alias _snprintf snprintf; 596 597 int _vsnprintf(char* s, size_t n, in char* format, va_list arg); 598 alias _vsnprintf vsnprintf; 599} 600else version( Win64 ) 601{ 602 // No unsafe pointer manipulation. 603 extern (D) @trusted 604 { 605 void rewind(FILE* stream) { fseek(stream,0L,SEEK_SET); stream._flag&=~_IOERR; } 606 pure void clearerr(FILE* stream) { stream._flag &= ~(_IOERR|_IOEOF); } 607 pure int feof(FILE* stream) { return stream._flag&_IOEOF; } 608 pure int ferror(FILE* stream) { return stream._flag&_IOERR; } 609 pure int fileno(FILE* stream) { return stream._file; } 610 } 611 int _snprintf(char* s, size_t n, in char* fmt, ...); 612 alias _snprintf snprintf; 613 614 int _vsnprintf(char* s, size_t n, in char* format, va_list arg); 615 alias _vsnprintf vsnprintf; 616 617 int _filbuf(FILE *fp); 618 int _flsbuf(int c, FILE *fp); 619 620 int _fputc_nolock(int c, FILE *fp) 621 { 622 if (--fp._cnt >= 0) 623 return *fp._ptr++ = cast(char)c; 624 else 625 return _flsbuf(c, fp); 626 } 627 628 int _fgetc_nolock(FILE *fp) 629 { 630 if (--fp._cnt >= 0) 631 return *fp._ptr++; 632 else 633 return _filbuf(fp); 634 } 635 636 int _lock_file(FILE *fp); 637 int _unlock_file(FILE *fp); 638} 639else version( linux ) 640{ 641 // No unsafe pointer manipulation. 642 @trusted 643 { 644 void rewind(FILE* stream); 645 pure void clearerr(FILE* stream); 646 pure int feof(FILE* stream); 647 pure int ferror(FILE* stream); 648 int fileno(FILE *); 649 } 650 651 int snprintf(char* s, size_t n, in char* format, ...); 652 int vsnprintf(char* s, size_t n, in char* format, va_list arg); 653} 654else version( OSX ) 655{ 656 // No unsafe pointer manipulation. 657 @trusted 658 { 659 void rewind(FILE*); 660 pure void clearerr(FILE*); 661 pure int feof(FILE*); 662 pure int ferror(FILE*); 663 int fileno(FILE*); 664 } 665 666 int snprintf(char* s, size_t n, in char* format, ...); 667 int vsnprintf(char* s, size_t n, in char* format, va_list arg); 668} 669else version( FreeBSD ) 670{ 671 // No unsafe pointer manipulation. 672 @trusted 673 { 674 void rewind(FILE*); 675 pure void clearerr(FILE*); 676 pure int feof(FILE*); 677 pure int ferror(FILE*); 678 int fileno(FILE*); 679 } 680 681 int snprintf(char* s, size_t n, in char* format, ...); 682 int vsnprintf(char* s, size_t n, in char* format, va_list arg); 683} 684else version (Solaris) 685{ 686 // No unsafe pointer manipulation. 687 @trusted 688 { 689 void rewind(FILE*); 690 pure void clearerr(FILE*); 691 pure int feof(FILE*); 692 pure int ferror(FILE*); 693 int fileno(FILE*); 694 } 695 696 int snprintf(char* s, size_t n, in char* format, ...); 697 int vsnprintf(char* s, size_t n, in char* format, va_list arg); 698} 699else 700{ 701 static assert( false, "Unsupported platform" ); 702} 703 704void perror(in char* s); 705 706version (DigitalMars) version (Win32) 707{ 708 import core.sys.windows.windows; 709 710 enum 711 { 712 FHND_APPEND = 0x04, 713 FHND_DEVICE = 0x08, 714 FHND_TEXT = 0x10, 715 FHND_BYTE = 0x20, 716 FHND_WCHAR = 0x40, 717 } 718 719 private enum _MAX_SEMAPHORES = 10 + _NFILE; 720 private enum _semIO = 3; 721 722 private extern __gshared short _iSemLockCtrs[_MAX_SEMAPHORES]; 723 private extern __gshared int _iSemThreadIds[_MAX_SEMAPHORES]; 724 private extern __gshared int _iSemNestCount[_MAX_SEMAPHORES]; 725 private extern __gshared HANDLE[_NFILE] _osfhnd; 726 private extern __gshared ubyte[_NFILE] __fhnd_info; 727 728 private void _WaitSemaphore(int iSemaphore); 729 private void _ReleaseSemaphore(int iSemaphore); 730 731 // this is copied from semlock.h in DMC's runtime. 732 private void LockSemaphore(uint num) 733 { 734 asm 735 { 736 mov EDX, num; 737 lock; 738 inc _iSemLockCtrs[EDX * 2]; 739 jz lsDone; 740 push EDX; 741 call _WaitSemaphore; 742 add ESP, 4; 743 } 744 745 lsDone: {} 746 } 747 748 // this is copied from semlock.h in DMC's runtime. 749 private void UnlockSemaphore(uint num) 750 { 751 asm 752 { 753 mov EDX, num; 754 lock; 755 dec _iSemLockCtrs[EDX * 2]; 756 js usDone; 757 push EDX; 758 call _ReleaseSemaphore; 759 add ESP, 4; 760 } 761 762 usDone: {} 763 } 764 765 // This converts a HANDLE to a file descriptor in DMC's runtime 766 int _handleToFD(HANDLE h, int flags) 767 { 768 LockSemaphore(_semIO); 769 scope(exit) UnlockSemaphore(_semIO); 770 771 foreach (fd; 0 .. _NFILE) 772 { 773 if (!_osfhnd[fd]) 774 { 775 _osfhnd[fd] = h; 776 __fhnd_info[fd] = cast(ubyte)flags; 777 return fd; 778 } 779 } 780 781 return -1; 782 } 783 784 HANDLE _fdToHandle(int fd) 785 { 786 // no semaphore is required, once inserted, a file descriptor 787 // doesn't change. 788 if (fd < 0 || fd >= _NFILE) 789 return null; 790 791 return _osfhnd[fd]; 792 } 793 794 enum 795 { 796 O_RDONLY = 0x000, 797 O_WRONLY = 0x001, 798 O_RDWR = 0x002, 799 O_APPEND = 0x008, 800 O_CREAT = 0x100, 801 O_TRUNC = 0x200, 802 O_EXCL = 0x400, 803 } 804 805 enum 806 { 807 S_IREAD = 0x0100, 808 S_IWRITE = 0x0080, 809 } 810 811 enum 812 { 813 STDIN_FILENO = 0, 814 STDOUT_FILENO = 1, 815 STDERR_FILENO = 2, 816 } 817 818 int open(const(char)* filename, int flags, ...); 819 int close(int fd); 820 FILE *fdopen(int fd, const(char)* flags); 821}